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