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