1 /* crypto/bio/bio_lib.c */ 2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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, long,long) 160 { 161 return b->callback; 162 } 163 164 void BIO_set_callback(BIO *b, long (*cb)(struct bio_st *,int,const char *,int, long,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 char *, 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) 603