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