OLD | NEW |
| (Empty) |
1 /* crypto/bio/bio_lib.c */ | |
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | |
3 * All rights reserved. | |
4 * | |
5 * This package is an SSL implementation written | |
6 * by Eric Young (eay@cryptsoft.com). | |
7 * The implementation was written so as to conform with Netscapes SSL. | |
8 * | |
9 * This library is free for commercial and non-commercial use as long as | |
10 * the following conditions are aheared to. The following conditions | |
11 * apply to all code found in this distribution, be it the RC4, RSA, | |
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
13 * included with this distribution is covered by the same copyright terms | |
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
15 * | |
16 * Copyright remains Eric Young's, and as such any Copyright notices in | |
17 * the code are not to be removed. | |
18 * If this package is used in a product, Eric Young should be given attribution | |
19 * as the author of the parts of the library used. | |
20 * This can be in the form of a textual message at program startup or | |
21 * in documentation (online or textual) provided with the package. | |
22 * | |
23 * Redistribution and use in source and binary forms, with or without | |
24 * modification, are permitted provided that the following conditions | |
25 * are met: | |
26 * 1. Redistributions of source code must retain the copyright | |
27 * notice, this list of conditions and the following disclaimer. | |
28 * 2. Redistributions in binary form must reproduce the above copyright | |
29 * notice, this list of conditions and the following disclaimer in the | |
30 * documentation and/or other materials provided with the distribution. | |
31 * 3. All advertising materials mentioning features or use of this software | |
32 * must display the following acknowledgement: | |
33 * "This product includes cryptographic software written by | |
34 * Eric Young (eay@cryptsoft.com)" | |
35 * The word 'cryptographic' can be left out if the rouines from the library | |
36 * being used are not cryptographic related :-). | |
37 * 4. If you include any Windows specific code (or a derivative thereof) from | |
38 * the apps directory (application code) you must include an acknowledgement: | |
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
40 * | |
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | |
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
51 * SUCH DAMAGE. | |
52 * | |
53 * The licence and distribution terms for any publically available version or | |
54 * derivative of this code cannot be changed. i.e. this code cannot simply be | |
55 * copied and put under another distribution licence | |
56 * [including the GNU Public Licence.] | |
57 */ | |
58 | |
59 #include <stdio.h> | |
60 #include <errno.h> | |
61 #include <openssl/crypto.h> | |
62 #include "cryptlib.h" | |
63 #include <openssl/bio.h> | |
64 #include <openssl/stack.h> | |
65 | |
66 BIO *BIO_new(BIO_METHOD *method) | |
67 { | |
68 BIO *ret=NULL; | |
69 | |
70 ret=(BIO *)OPENSSL_malloc(sizeof(BIO)); | |
71 if (ret == NULL) | |
72 { | |
73 BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE); | |
74 return(NULL); | |
75 } | |
76 if (!BIO_set(ret,method)) | |
77 { | |
78 OPENSSL_free(ret); | |
79 ret=NULL; | |
80 } | |
81 return(ret); | |
82 } | |
83 | |
84 int BIO_set(BIO *bio, BIO_METHOD *method) | |
85 { | |
86 bio->method=method; | |
87 bio->callback=NULL; | |
88 bio->cb_arg=NULL; | |
89 bio->init=0; | |
90 bio->shutdown=1; | |
91 bio->flags=0; | |
92 bio->retry_reason=0; | |
93 bio->num=0; | |
94 bio->ptr=NULL; | |
95 bio->prev_bio=NULL; | |
96 bio->next_bio=NULL; | |
97 bio->references=1; | |
98 bio->num_read=0L; | |
99 bio->num_write=0L; | |
100 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); | |
101 if (method->create != NULL) | |
102 if (!method->create(bio)) | |
103 { | |
104 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, | |
105 &bio->ex_data); | |
106 return(0); | |
107 } | |
108 return(1); | |
109 } | |
110 | |
111 int BIO_free(BIO *a) | |
112 { | |
113 int i; | |
114 | |
115 if (a == NULL) return(0); | |
116 | |
117 i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO); | |
118 #ifdef REF_PRINT | |
119 REF_PRINT("BIO",a); | |
120 #endif | |
121 if (i > 0) return(1); | |
122 #ifdef REF_CHECK | |
123 if (i < 0) | |
124 { | |
125 fprintf(stderr,"BIO_free, bad reference count\n"); | |
126 abort(); | |
127 } | |
128 #endif | |
129 if ((a->callback != NULL) && | |
130 ((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0)) | |
131 return(i); | |
132 | |
133 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); | |
134 | |
135 if ((a->method == NULL) || (a->method->destroy == NULL)) return(1); | |
136 a->method->destroy(a); | |
137 OPENSSL_free(a); | |
138 return(1); | |
139 } | |
140 | |
141 void BIO_vfree(BIO *a) | |
142 { BIO_free(a); } | |
143 | |
144 void BIO_clear_flags(BIO *b, int flags) | |
145 { | |
146 b->flags &= ~flags; | |
147 } | |
148 | |
149 int BIO_test_flags(const BIO *b, int flags) | |
150 { | |
151 return (b->flags & flags); | |
152 } | |
153 | |
154 void BIO_set_flags(BIO *b, int flags) | |
155 { | |
156 b->flags |= flags; | |
157 } | |
158 | |
159 long (*BIO_get_callback(const BIO *b))(struct bio_st *,int,const char *,int, lon
g,long) | |
160 { | |
161 return b->callback; | |
162 } | |
163 | |
164 void BIO_set_callback(BIO *b, long (*cb)(struct bio_st *,int,const char *,int, l
ong,long)) | |
165 { | |
166 b->callback = cb; | |
167 } | |
168 | |
169 void BIO_set_callback_arg(BIO *b, char *arg) | |
170 { | |
171 b->cb_arg = arg; | |
172 } | |
173 | |
174 char * BIO_get_callback_arg(const BIO *b) | |
175 { | |
176 return b->cb_arg; | |
177 } | |
178 | |
179 const char * BIO_method_name(const BIO *b) | |
180 { | |
181 return b->method->name; | |
182 } | |
183 | |
184 int BIO_method_type(const BIO *b) | |
185 { | |
186 return b->method->type; | |
187 } | |
188 | |
189 | |
190 int BIO_read(BIO *b, void *out, int outl) | |
191 { | |
192 int i; | |
193 long (*cb)(BIO *,int,const char *,int,long,long); | |
194 | |
195 if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) | |
196 { | |
197 BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD); | |
198 return(-2); | |
199 } | |
200 | |
201 cb=b->callback; | |
202 if ((cb != NULL) && | |
203 ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0)) | |
204 return(i); | |
205 | |
206 if (!b->init) | |
207 { | |
208 BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED); | |
209 return(-2); | |
210 } | |
211 | |
212 i=b->method->bread(b,out,outl); | |
213 | |
214 if (i > 0) b->num_read+=(unsigned long)i; | |
215 | |
216 if (cb != NULL) | |
217 i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl, | |
218 0L,(long)i); | |
219 return(i); | |
220 } | |
221 | |
222 int BIO_write(BIO *b, const void *in, int inl) | |
223 { | |
224 int i; | |
225 long (*cb)(BIO *,int,const char *,int,long,long); | |
226 | |
227 if (b == NULL) | |
228 return(0); | |
229 | |
230 cb=b->callback; | |
231 if ((b->method == NULL) || (b->method->bwrite == NULL)) | |
232 { | |
233 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD); | |
234 return(-2); | |
235 } | |
236 | |
237 if ((cb != NULL) && | |
238 ((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0)) | |
239 return(i); | |
240 | |
241 if (!b->init) | |
242 { | |
243 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED); | |
244 return(-2); | |
245 } | |
246 | |
247 i=b->method->bwrite(b,in,inl); | |
248 | |
249 if (i > 0) b->num_write+=(unsigned long)i; | |
250 | |
251 if (cb != NULL) | |
252 i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl, | |
253 0L,(long)i); | |
254 return(i); | |
255 } | |
256 | |
257 int BIO_puts(BIO *b, const char *in) | |
258 { | |
259 int i; | |
260 long (*cb)(BIO *,int,const char *,int,long,long); | |
261 | |
262 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) | |
263 { | |
264 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD); | |
265 return(-2); | |
266 } | |
267 | |
268 cb=b->callback; | |
269 | |
270 if ((cb != NULL) && | |
271 ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0)) | |
272 return(i); | |
273 | |
274 if (!b->init) | |
275 { | |
276 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED); | |
277 return(-2); | |
278 } | |
279 | |
280 i=b->method->bputs(b,in); | |
281 | |
282 if (i > 0) b->num_write+=(unsigned long)i; | |
283 | |
284 if (cb != NULL) | |
285 i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0, | |
286 0L,(long)i); | |
287 return(i); | |
288 } | |
289 | |
290 int BIO_gets(BIO *b, char *in, int inl) | |
291 { | |
292 int i; | |
293 long (*cb)(BIO *,int,const char *,int,long,long); | |
294 | |
295 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) | |
296 { | |
297 BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD); | |
298 return(-2); | |
299 } | |
300 | |
301 cb=b->callback; | |
302 | |
303 if ((cb != NULL) && | |
304 ((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0)) | |
305 return(i); | |
306 | |
307 if (!b->init) | |
308 { | |
309 BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED); | |
310 return(-2); | |
311 } | |
312 | |
313 i=b->method->bgets(b,in,inl); | |
314 | |
315 if (cb != NULL) | |
316 i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl, | |
317 0L,(long)i); | |
318 return(i); | |
319 } | |
320 | |
321 int BIO_indent(BIO *b,int indent,int max) | |
322 { | |
323 if(indent < 0) | |
324 indent=0; | |
325 if(indent > max) | |
326 indent=max; | |
327 while(indent--) | |
328 if(BIO_puts(b," ") != 1) | |
329 return 0; | |
330 return 1; | |
331 } | |
332 | |
333 long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) | |
334 { | |
335 int i; | |
336 | |
337 i=iarg; | |
338 return(BIO_ctrl(b,cmd,larg,(char *)&i)); | |
339 } | |
340 | |
341 char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) | |
342 { | |
343 char *p=NULL; | |
344 | |
345 if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0) | |
346 return(NULL); | |
347 else | |
348 return(p); | |
349 } | |
350 | |
351 long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) | |
352 { | |
353 long ret; | |
354 long (*cb)(BIO *,int,const char *,int,long,long); | |
355 | |
356 if (b == NULL) return(0); | |
357 | |
358 if ((b->method == NULL) || (b->method->ctrl == NULL)) | |
359 { | |
360 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); | |
361 return(-2); | |
362 } | |
363 | |
364 cb=b->callback; | |
365 | |
366 if ((cb != NULL) && | |
367 ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0)) | |
368 return(ret); | |
369 | |
370 ret=b->method->ctrl(b,cmd,larg,parg); | |
371 | |
372 if (cb != NULL) | |
373 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd, | |
374 larg,ret); | |
375 return(ret); | |
376 } | |
377 | |
378 long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const c
har *, int, long, long)) | |
379 { | |
380 long ret; | |
381 long (*cb)(BIO *,int,const char *,int,long,long); | |
382 | |
383 if (b == NULL) return(0); | |
384 | |
385 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) | |
386 { | |
387 BIOerr(BIO_F_BIO_CALLBACK_CTRL,BIO_R_UNSUPPORTED_METHOD); | |
388 return(-2); | |
389 } | |
390 | |
391 cb=b->callback; | |
392 | |
393 if ((cb != NULL) && | |
394 ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0)) | |
395 return(ret); | |
396 | |
397 ret=b->method->callback_ctrl(b,cmd,fp); | |
398 | |
399 if (cb != NULL) | |
400 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd, | |
401 0,ret); | |
402 return(ret); | |
403 } | |
404 | |
405 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros | |
406 * do; but those macros have inappropriate return type, and for interfacing | |
407 * from other programming languages, C macros aren't much of a help anyway. */ | |
408 size_t BIO_ctrl_pending(BIO *bio) | |
409 { | |
410 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); | |
411 } | |
412 | |
413 size_t BIO_ctrl_wpending(BIO *bio) | |
414 { | |
415 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); | |
416 } | |
417 | |
418 | |
419 /* put the 'bio' on the end of b's list of operators */ | |
420 BIO *BIO_push(BIO *b, BIO *bio) | |
421 { | |
422 BIO *lb; | |
423 | |
424 if (b == NULL) return(bio); | |
425 lb=b; | |
426 while (lb->next_bio != NULL) | |
427 lb=lb->next_bio; | |
428 lb->next_bio=bio; | |
429 if (bio != NULL) | |
430 bio->prev_bio=lb; | |
431 /* called to do internal processing */ | |
432 BIO_ctrl(b,BIO_CTRL_PUSH,0,lb); | |
433 return(b); | |
434 } | |
435 | |
436 /* Remove the first and return the rest */ | |
437 BIO *BIO_pop(BIO *b) | |
438 { | |
439 BIO *ret; | |
440 | |
441 if (b == NULL) return(NULL); | |
442 ret=b->next_bio; | |
443 | |
444 BIO_ctrl(b,BIO_CTRL_POP,0,b); | |
445 | |
446 if (b->prev_bio != NULL) | |
447 b->prev_bio->next_bio=b->next_bio; | |
448 if (b->next_bio != NULL) | |
449 b->next_bio->prev_bio=b->prev_bio; | |
450 | |
451 b->next_bio=NULL; | |
452 b->prev_bio=NULL; | |
453 return(ret); | |
454 } | |
455 | |
456 BIO *BIO_get_retry_BIO(BIO *bio, int *reason) | |
457 { | |
458 BIO *b,*last; | |
459 | |
460 b=last=bio; | |
461 for (;;) | |
462 { | |
463 if (!BIO_should_retry(b)) break; | |
464 last=b; | |
465 b=b->next_bio; | |
466 if (b == NULL) break; | |
467 } | |
468 if (reason != NULL) *reason=last->retry_reason; | |
469 return(last); | |
470 } | |
471 | |
472 int BIO_get_retry_reason(BIO *bio) | |
473 { | |
474 return(bio->retry_reason); | |
475 } | |
476 | |
477 BIO *BIO_find_type(BIO *bio, int type) | |
478 { | |
479 int mt,mask; | |
480 | |
481 if(!bio) return NULL; | |
482 mask=type&0xff; | |
483 do { | |
484 if (bio->method != NULL) | |
485 { | |
486 mt=bio->method->type; | |
487 | |
488 if (!mask) | |
489 { | |
490 if (mt & type) return(bio); | |
491 } | |
492 else if (mt == type) | |
493 return(bio); | |
494 } | |
495 bio=bio->next_bio; | |
496 } while (bio != NULL); | |
497 return(NULL); | |
498 } | |
499 | |
500 BIO *BIO_next(BIO *b) | |
501 { | |
502 if(!b) return NULL; | |
503 return b->next_bio; | |
504 } | |
505 | |
506 void BIO_free_all(BIO *bio) | |
507 { | |
508 BIO *b; | |
509 int ref; | |
510 | |
511 while (bio != NULL) | |
512 { | |
513 b=bio; | |
514 ref=b->references; | |
515 bio=bio->next_bio; | |
516 BIO_free(b); | |
517 /* Since ref count > 1, don't free anyone else. */ | |
518 if (ref > 1) break; | |
519 } | |
520 } | |
521 | |
522 BIO *BIO_dup_chain(BIO *in) | |
523 { | |
524 BIO *ret=NULL,*eoc=NULL,*bio,*new_bio; | |
525 | |
526 for (bio=in; bio != NULL; bio=bio->next_bio) | |
527 { | |
528 if ((new_bio=BIO_new(bio->method)) == NULL) goto err; | |
529 new_bio->callback=bio->callback; | |
530 new_bio->cb_arg=bio->cb_arg; | |
531 new_bio->init=bio->init; | |
532 new_bio->shutdown=bio->shutdown; | |
533 new_bio->flags=bio->flags; | |
534 | |
535 /* This will let SSL_s_sock() work with stdin/stdout */ | |
536 new_bio->num=bio->num; | |
537 | |
538 if (!BIO_dup_state(bio,(char *)new_bio)) | |
539 { | |
540 BIO_free(new_bio); | |
541 goto err; | |
542 } | |
543 | |
544 /* copy app data */ | |
545 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, | |
546 &bio->ex_data)) | |
547 goto err; | |
548 | |
549 if (ret == NULL) | |
550 { | |
551 eoc=new_bio; | |
552 ret=eoc; | |
553 } | |
554 else | |
555 { | |
556 BIO_push(eoc,new_bio); | |
557 eoc=new_bio; | |
558 } | |
559 } | |
560 return(ret); | |
561 err: | |
562 if (ret != NULL) | |
563 BIO_free(ret); | |
564 return(NULL); | |
565 } | |
566 | |
567 void BIO_copy_next_retry(BIO *b) | |
568 { | |
569 BIO_set_flags(b,BIO_get_retry_flags(b->next_bio)); | |
570 b->retry_reason=b->next_bio->retry_reason; | |
571 } | |
572 | |
573 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |
574 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) | |
575 { | |
576 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, | |
577 new_func, dup_func, free_func); | |
578 } | |
579 | |
580 int BIO_set_ex_data(BIO *bio, int idx, void *data) | |
581 { | |
582 return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data)); | |
583 } | |
584 | |
585 void *BIO_get_ex_data(BIO *bio, int idx) | |
586 { | |
587 return(CRYPTO_get_ex_data(&(bio->ex_data),idx)); | |
588 } | |
589 | |
590 unsigned long BIO_number_read(BIO *bio) | |
591 { | |
592 if(bio) return bio->num_read; | |
593 return 0; | |
594 } | |
595 | |
596 unsigned long BIO_number_written(BIO *bio) | |
597 { | |
598 if(bio) return bio->num_write; | |
599 return 0; | |
600 } | |
601 | |
602 IMPLEMENT_STACK_OF(BIO) | |
OLD | NEW |