1 /* $OpenBSD: bio_lib.c,v 1.29 2019/04/14 17:39:03 jsing Exp $ */ 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 <errno.h> 60 #include <stdio.h> 61 62 #include <openssl/bio.h> 63 #include <openssl/crypto.h> 64 #include <openssl/err.h> 65 #include <openssl/stack.h> 66 67 int 68 BIO_get_new_index(void) 69 { 70 static int bio_type_index = BIO_TYPE_START; 71 int index; 72 73 /* The index will collide with the BIO flag bits if it exceeds 255. */ 74 index = CRYPTO_add(&bio_type_index, 1, CRYPTO_LOCK_BIO); 75 if (index > 255) 76 return -1; 77 78 return index; 79 } 80 81 BIO * 82 BIO_new(const BIO_METHOD *method) 83 { 84 BIO *ret = NULL; 85 86 ret = malloc(sizeof(BIO)); 87 if (ret == NULL) { 88 BIOerror(ERR_R_MALLOC_FAILURE); 89 return (NULL); 90 } 91 if (!BIO_set(ret, method)) { 92 free(ret); 93 ret = NULL; 94 } 95 return (ret); 96 } 97 98 int 99 BIO_set(BIO *bio, const BIO_METHOD *method) 100 { 101 bio->method = method; 102 bio->callback = NULL; 103 bio->cb_arg = NULL; 104 bio->init = 0; 105 bio->shutdown = 1; 106 bio->flags = 0; 107 bio->retry_reason = 0; 108 bio->num = 0; 109 bio->ptr = NULL; 110 bio->prev_bio = NULL; 111 bio->next_bio = NULL; 112 bio->references = 1; 113 bio->num_read = 0L; 114 bio->num_write = 0L; 115 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 116 if (method->create != NULL) 117 if (!method->create(bio)) { 118 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, 119 &bio->ex_data); 120 return (0); 121 } 122 return (1); 123 } 124 125 int 126 BIO_free(BIO *a) 127 { 128 int i; 129 130 if (a == NULL) 131 return (0); 132 133 i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO); 134 if (i > 0) 135 return (1); 136 if ((a->callback != NULL) && 137 ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0)) 138 return (i); 139 140 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); 141 142 if (a->method != NULL && a->method->destroy != NULL) 143 a->method->destroy(a); 144 free(a); 145 return (1); 146 } 147 148 void 149 BIO_vfree(BIO *a) 150 { 151 BIO_free(a); 152 } 153 154 int 155 BIO_up_ref(BIO *bio) 156 { 157 int refs = CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO); 158 return (refs > 1) ? 1 : 0; 159 } 160 161 void * 162 BIO_get_data(BIO *a) 163 { 164 return (a->ptr); 165 } 166 167 void 168 BIO_set_data(BIO *a, void *ptr) 169 { 170 a->ptr = ptr; 171 } 172 173 void 174 BIO_set_init(BIO *a, int init) 175 { 176 a->init = init; 177 } 178 179 int 180 BIO_get_shutdown(BIO *a) 181 { 182 return (a->shutdown); 183 } 184 185 void 186 BIO_set_shutdown(BIO *a, int shut) 187 { 188 a->shutdown = shut; 189 } 190 191 void 192 BIO_clear_flags(BIO *b, int flags) 193 { 194 b->flags &= ~flags; 195 } 196 197 int 198 BIO_test_flags(const BIO *b, int flags) 199 { 200 return (b->flags & flags); 201 } 202 203 void 204 BIO_set_flags(BIO *b, int flags) 205 { 206 b->flags |= flags; 207 } 208 209 long 210 (*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, int, 211 long, long) 212 { 213 return b->callback; 214 } 215 216 void 217 BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *, int, 218 long, long)) 219 { 220 b->callback = cb; 221 } 222 223 void 224 BIO_set_callback_arg(BIO *b, char *arg) 225 { 226 b->cb_arg = arg; 227 } 228 229 char * 230 BIO_get_callback_arg(const BIO *b) 231 { 232 return b->cb_arg; 233 } 234 235 const char * 236 BIO_method_name(const BIO *b) 237 { 238 return b->method->name; 239 } 240 241 int 242 BIO_method_type(const BIO *b) 243 { 244 return b->method->type; 245 } 246 247 int 248 BIO_read(BIO *b, void *out, int outl) 249 { 250 int i; 251 long (*cb)(BIO *, int, const char *, int, long, long); 252 253 if (b == NULL) 254 return (0); 255 256 if (out == NULL || outl <= 0) 257 return (0); 258 259 if (b->method == NULL || b->method->bread == NULL) { 260 BIOerror(BIO_R_UNSUPPORTED_METHOD); 261 return (-2); 262 } 263 264 cb = b->callback; 265 if ((cb != NULL) && 266 ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0)) 267 return (i); 268 269 if (!b->init) { 270 BIOerror(BIO_R_UNINITIALIZED); 271 return (-2); 272 } 273 274 i = b->method->bread(b, out, outl); 275 276 if (i > 0) 277 b->num_read += (unsigned long)i; 278 279 if (cb != NULL) 280 i = (int)cb(b, BIO_CB_READ|BIO_CB_RETURN, out, outl, 281 0L, (long)i); 282 283 return (i); 284 } 285 286 int 287 BIO_write(BIO *b, const void *in, int inl) 288 { 289 int i; 290 long (*cb)(BIO *, int, const char *, int, long, long); 291 292 if (b == NULL) 293 return (0); 294 295 if (in == NULL || inl <= 0) 296 return (0); 297 298 if (b->method == NULL || b->method->bwrite == NULL) { 299 BIOerror(BIO_R_UNSUPPORTED_METHOD); 300 return (-2); 301 } 302 303 cb = b->callback; 304 if ((cb != NULL) && 305 ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0)) 306 return (i); 307 308 if (!b->init) { 309 BIOerror(BIO_R_UNINITIALIZED); 310 return (-2); 311 } 312 313 i = b->method->bwrite(b, in, inl); 314 315 if (i > 0) 316 b->num_write += (unsigned long)i; 317 318 if (cb != NULL) 319 i = (int)cb(b, BIO_CB_WRITE|BIO_CB_RETURN, in, inl, 320 0L, (long)i); 321 return (i); 322 } 323 324 int 325 BIO_puts(BIO *b, const char *in) 326 { 327 int i; 328 long (*cb)(BIO *, int, const char *, int, long, long); 329 330 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { 331 BIOerror(BIO_R_UNSUPPORTED_METHOD); 332 return (-2); 333 } 334 335 cb = b->callback; 336 337 if ((cb != NULL) && 338 ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0)) 339 return (i); 340 341 if (!b->init) { 342 BIOerror(BIO_R_UNINITIALIZED); 343 return (-2); 344 } 345 346 i = b->method->bputs(b, in); 347 348 if (i > 0) 349 b->num_write += (unsigned long)i; 350 351 if (cb != NULL) 352 i = (int)cb(b, BIO_CB_PUTS|BIO_CB_RETURN, in, 0, 0L, (long)i); 353 return (i); 354 } 355 356 int 357 BIO_gets(BIO *b, char *in, int inl) 358 { 359 int i; 360 long (*cb)(BIO *, int, const char *, int, long, long); 361 362 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { 363 BIOerror(BIO_R_UNSUPPORTED_METHOD); 364 return (-2); 365 } 366 367 cb = b->callback; 368 369 if ((cb != NULL) && 370 ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0)) 371 return (i); 372 373 if (!b->init) { 374 BIOerror(BIO_R_UNINITIALIZED); 375 return (-2); 376 } 377 378 i = b->method->bgets(b, in, inl); 379 380 if (cb != NULL) 381 i = (int)cb(b, BIO_CB_GETS|BIO_CB_RETURN, in, inl, 0L, (long)i); 382 return (i); 383 } 384 385 int 386 BIO_indent(BIO *b, int indent, int max) 387 { 388 if (indent < 0) 389 indent = 0; 390 if (indent > max) 391 indent = max; 392 while (indent--) 393 if (BIO_puts(b, " ") != 1) 394 return 0; 395 return 1; 396 } 397 398 long 399 BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) 400 { 401 int i; 402 403 i = iarg; 404 return (BIO_ctrl(b, cmd, larg, (char *)&i)); 405 } 406 407 char * 408 BIO_ptr_ctrl(BIO *b, int cmd, long larg) 409 { 410 char *p = NULL; 411 412 if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) 413 return (NULL); 414 else 415 return (p); 416 } 417 418 long 419 BIO_ctrl(BIO *b, int cmd, long larg, void *parg) 420 { 421 long ret; 422 long (*cb)(BIO *, int, const char *, int, long, long); 423 424 if (b == NULL) 425 return (0); 426 427 if ((b->method == NULL) || (b->method->ctrl == NULL)) { 428 BIOerror(BIO_R_UNSUPPORTED_METHOD); 429 return (-2); 430 } 431 432 cb = b->callback; 433 434 if ((cb != NULL) && 435 ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0)) 436 return (ret); 437 438 ret = b->method->ctrl(b, cmd, larg, parg); 439 440 if (cb != NULL) 441 ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, parg, cmd, larg, ret); 442 return (ret); 443 } 444 445 long 446 BIO_callback_ctrl(BIO *b, int cmd, 447 void (*fp)(struct bio_st *, int, const char *, int, long, long)) 448 { 449 long ret; 450 long (*cb)(BIO *, int, const char *, int, long, long); 451 452 if (b == NULL) 453 return (0); 454 455 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) { 456 BIOerror(BIO_R_UNSUPPORTED_METHOD); 457 return (-2); 458 } 459 460 cb = b->callback; 461 462 if ((cb != NULL) && 463 ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0)) 464 return (ret); 465 466 ret = b->method->callback_ctrl(b, cmd, fp); 467 468 if (cb != NULL) 469 ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, (void *)&fp, cmd, 0, ret); 470 return (ret); 471 } 472 473 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros 474 * do; but those macros have inappropriate return type, and for interfacing 475 * from other programming languages, C macros aren't much of a help anyway. */ 476 size_t 477 BIO_ctrl_pending(BIO *bio) 478 { 479 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 480 } 481 482 size_t 483 BIO_ctrl_wpending(BIO *bio) 484 { 485 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 486 } 487 488 489 /* put the 'bio' on the end of b's list of operators */ 490 BIO * 491 BIO_push(BIO *b, BIO *bio) 492 { 493 BIO *lb; 494 495 if (b == NULL) 496 return (bio); 497 lb = b; 498 while (lb->next_bio != NULL) 499 lb = lb->next_bio; 500 lb->next_bio = bio; 501 if (bio != NULL) 502 bio->prev_bio = lb; 503 /* called to do internal processing */ 504 BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb); 505 return (b); 506 } 507 508 /* Remove the first and return the rest */ 509 BIO * 510 BIO_pop(BIO *b) 511 { 512 BIO *ret; 513 514 if (b == NULL) 515 return (NULL); 516 ret = b->next_bio; 517 518 BIO_ctrl(b, BIO_CTRL_POP, 0, b); 519 520 if (b->prev_bio != NULL) 521 b->prev_bio->next_bio = b->next_bio; 522 if (b->next_bio != NULL) 523 b->next_bio->prev_bio = b->prev_bio; 524 525 b->next_bio = NULL; 526 b->prev_bio = NULL; 527 return (ret); 528 } 529 530 BIO * 531 BIO_get_retry_BIO(BIO *bio, int *reason) 532 { 533 BIO *b, *last; 534 535 b = last = bio; 536 for (;;) { 537 if (!BIO_should_retry(b)) 538 break; 539 last = b; 540 b = b->next_bio; 541 if (b == NULL) 542 break; 543 } 544 if (reason != NULL) 545 *reason = last->retry_reason; 546 return (last); 547 } 548 549 int 550 BIO_get_retry_reason(BIO *bio) 551 { 552 return (bio->retry_reason); 553 } 554 555 BIO * 556 BIO_find_type(BIO *bio, int type) 557 { 558 int mt, mask; 559 560 if (!bio) 561 return NULL; 562 mask = type & 0xff; 563 do { 564 if (bio->method != NULL) { 565 mt = bio->method->type; 566 if (!mask) { 567 if (mt & type) 568 return (bio); 569 } else if (mt == type) 570 return (bio); 571 } 572 bio = bio->next_bio; 573 } while (bio != NULL); 574 return (NULL); 575 } 576 577 BIO * 578 BIO_next(BIO *b) 579 { 580 if (!b) 581 return NULL; 582 return b->next_bio; 583 } 584 585 void 586 BIO_free_all(BIO *bio) 587 { 588 BIO *b; 589 int ref; 590 591 while (bio != NULL) { 592 b = bio; 593 ref = b->references; 594 bio = bio->next_bio; 595 BIO_free(b); 596 /* Since ref count > 1, don't free anyone else. */ 597 if (ref > 1) 598 break; 599 } 600 } 601 602 BIO * 603 BIO_dup_chain(BIO *in) 604 { 605 BIO *ret = NULL, *eoc = NULL, *bio, *new_bio; 606 607 for (bio = in; bio != NULL; bio = bio->next_bio) { 608 if ((new_bio = BIO_new(bio->method)) == NULL) 609 goto err; 610 new_bio->callback = bio->callback; 611 new_bio->cb_arg = bio->cb_arg; 612 new_bio->init = bio->init; 613 new_bio->shutdown = bio->shutdown; 614 new_bio->flags = bio->flags; 615 616 /* This will let SSL_s_sock() work with stdin/stdout */ 617 new_bio->num = bio->num; 618 619 if (!BIO_dup_state(bio, (char *)new_bio)) { 620 BIO_free(new_bio); 621 goto err; 622 } 623 624 /* copy app data */ 625 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, 626 &new_bio->ex_data, &bio->ex_data)) 627 goto err; 628 629 if (ret == NULL) { 630 eoc = new_bio; 631 ret = eoc; 632 } else { 633 BIO_push(eoc, new_bio); 634 eoc = new_bio; 635 } 636 } 637 return (ret); 638 err: 639 BIO_free(ret); 640 return (NULL); 641 642 } 643 644 void 645 BIO_copy_next_retry(BIO *b) 646 { 647 BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); 648 b->retry_reason = b->next_bio->retry_reason; 649 } 650 651 int 652 BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 653 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 654 { 655 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, 656 new_func, dup_func, free_func); 657 } 658 659 int 660 BIO_set_ex_data(BIO *bio, int idx, void *data) 661 { 662 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data)); 663 } 664 665 void * 666 BIO_get_ex_data(BIO *bio, int idx) 667 { 668 return (CRYPTO_get_ex_data(&(bio->ex_data), idx)); 669 } 670 671 unsigned long 672 BIO_number_read(BIO *bio) 673 { 674 if (bio) 675 return bio->num_read; 676 return 0; 677 } 678 679 unsigned long 680 BIO_number_written(BIO *bio) 681 { 682 if (bio) 683 return bio->num_write; 684 return 0; 685 } 686