bio_lib.c revision 296465
1185377Ssam/* crypto/bio/bio_lib.c */ 2185377Ssam/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3185377Ssam * All rights reserved. 4185377Ssam * 5185377Ssam * This package is an SSL implementation written 6185377Ssam * by Eric Young (eay@cryptsoft.com). 7185377Ssam * The implementation was written so as to conform with Netscapes SSL. 8185377Ssam * 9185377Ssam * This library is free for commercial and non-commercial use as long as 10185377Ssam * the following conditions are aheared to. The following conditions 11185377Ssam * apply to all code found in this distribution, be it the RC4, RSA, 12185377Ssam * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13185377Ssam * included with this distribution is covered by the same copyright terms 14185377Ssam * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15185377Ssam * 16185377Ssam * Copyright remains Eric Young's, and as such any Copyright notices in 17204644Srpaulo * the code are not to be removed. 18185377Ssam * If this package is used in a product, Eric Young should be given attribution 19185377Ssam * as the author of the parts of the library used. 20185377Ssam * This can be in the form of a textual message at program startup or 21185377Ssam * in documentation (online or textual) provided with the package. 22185377Ssam * 23185377Ssam * Redistribution and use in source and binary forms, with or without 24185377Ssam * modification, are permitted provided that the following conditions 25185377Ssam * are met: 26185377Ssam * 1. Redistributions of source code must retain the copyright 27185377Ssam * notice, this list of conditions and the following disclaimer. 28185377Ssam * 2. Redistributions in binary form must reproduce the above copyright 29185377Ssam * notice, this list of conditions and the following disclaimer in the 30185377Ssam * documentation and/or other materials provided with the distribution. 31185377Ssam * 3. All advertising materials mentioning features or use of this software 32185377Ssam * must display the following acknowledgement: 33185377Ssam * "This product includes cryptographic software written by 34185377Ssam * Eric Young (eay@cryptsoft.com)" 35185377Ssam * The word 'cryptographic' can be left out if the rouines from the library 36185377Ssam * being used are not cryptographic related :-). 37185377Ssam * 4. If you include any Windows specific code (or a derivative thereof) from 38185377Ssam * the apps directory (application code) you must include an acknowledgement: 39185377Ssam * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40185377Ssam * 41185377Ssam * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42185377Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43185377Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44185377Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45185377Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46185377Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47185377Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48185377Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49185377Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50185377Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51185377Ssam * SUCH DAMAGE. 52185377Ssam * 53185377Ssam * The licence and distribution terms for any publically available version or 54185377Ssam * derivative of this code cannot be changed. i.e. this code cannot simply be 55185377Ssam * copied and put under another distribution licence 56185377Ssam * [including the GNU Public Licence.] 57185377Ssam */ 58185377Ssam 59185377Ssam#include <stdio.h> 60185377Ssam#include <errno.h> 61185377Ssam#include <openssl/crypto.h> 62185377Ssam#include "cryptlib.h" 63185377Ssam#include <openssl/bio.h> 64185377Ssam#include <openssl/stack.h> 65185377Ssam 66185377SsamBIO *BIO_new(BIO_METHOD *method) 67185377Ssam{ 68185377Ssam BIO *ret = NULL; 69185377Ssam 70185377Ssam ret = (BIO *)OPENSSL_malloc(sizeof(BIO)); 71185377Ssam if (ret == NULL) { 72185377Ssam BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); 73185377Ssam return (NULL); 74185377Ssam } 75185377Ssam if (!BIO_set(ret, method)) { 76185377Ssam OPENSSL_free(ret); 77185377Ssam ret = NULL; 78185377Ssam } 79185377Ssam return (ret); 80185377Ssam} 81185377Ssam 82185377Ssamint BIO_set(BIO *bio, BIO_METHOD *method) 83185377Ssam{ 84185377Ssam bio->method = method; 85185377Ssam bio->callback = NULL; 86185377Ssam bio->cb_arg = NULL; 87185377Ssam bio->init = 0; 88185377Ssam bio->shutdown = 1; 89185377Ssam bio->flags = 0; 90185377Ssam bio->retry_reason = 0; 91185377Ssam bio->num = 0; 92185377Ssam bio->ptr = NULL; 93185377Ssam bio->prev_bio = NULL; 94185377Ssam bio->next_bio = NULL; 95185377Ssam bio->references = 1; 96185377Ssam bio->num_read = 0L; 97185377Ssam bio->num_write = 0L; 98185377Ssam CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 99185377Ssam if (method->create != NULL) 100185377Ssam if (!method->create(bio)) { 101185377Ssam CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 102185377Ssam return (0); 103185377Ssam } 104185377Ssam return (1); 105185377Ssam} 106185377Ssam 107185377Ssamint BIO_free(BIO *a) 108185377Ssam{ 109262969Sadrian int i; 110185377Ssam 111185377Ssam if (a == NULL) 112185377Ssam return (0); 113265112Sadrian 114265112Sadrian i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO); 115185377Ssam#ifdef REF_PRINT 116185377Ssam REF_PRINT("BIO", a); 117185377Ssam#endif 118185377Ssam if (i > 0) 119265112Sadrian return (1); 120265112Sadrian#ifdef REF_CHECK 121185377Ssam if (i < 0) { 122185377Ssam fprintf(stderr, "BIO_free, bad reference count\n"); 123185377Ssam abort(); 124265112Sadrian } 125265112Sadrian#endif 126185377Ssam if ((a->callback != NULL) && 127185377Ssam ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0)) 128185377Ssam return (i); 129185377Ssam 130185377Ssam CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); 131185377Ssam 132264900Sadrian if ((a->method != NULL) && (a->method->destroy != NULL)) 133185377Ssam a->method->destroy(a); 134185377Ssam OPENSSL_free(a); 135185377Ssam return (1); 136185377Ssam} 137185377Ssam 138185377Ssamvoid BIO_vfree(BIO *a) 139185377Ssam{ 140185377Ssam 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, NULL); 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, NULL); 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; 519 520 for (bio = in; bio != NULL; bio = bio->next_bio) { 521 if ((new = BIO_new(bio->method)) == NULL) 522 goto err; 523 new->callback = bio->callback; 524 new->cb_arg = bio->cb_arg; 525 new->init = bio->init; 526 new->shutdown = bio->shutdown; 527 new->flags = bio->flags; 528 529 /* This will let SSL_s_sock() work with stdin/stdout */ 530 new->num = bio->num; 531 532 if (!BIO_dup_state(bio, (char *)new)) { 533 BIO_free(new); 534 goto err; 535 } 536 537 /* copy app data */ 538 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data, 539 &bio->ex_data)) 540 goto err; 541 542 if (ret == NULL) { 543 eoc = new; 544 ret = eoc; 545 } else { 546 BIO_push(eoc, new); 547 eoc = new; 548 } 549 } 550 return (ret); 551 err: 552 if (ret != NULL) 553 BIO_free(ret); 554 return (NULL); 555} 556 557void BIO_copy_next_retry(BIO *b) 558{ 559 BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); 560 b->retry_reason = b->next_bio->retry_reason; 561} 562 563int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 564 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 565{ 566 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, 567 new_func, dup_func, free_func); 568} 569 570int BIO_set_ex_data(BIO *bio, int idx, void *data) 571{ 572 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data)); 573} 574 575void *BIO_get_ex_data(BIO *bio, int idx) 576{ 577 return (CRYPTO_get_ex_data(&(bio->ex_data), idx)); 578} 579 580unsigned long BIO_number_read(BIO *bio) 581{ 582 if (bio) 583 return bio->num_read; 584 return 0; 585} 586 587unsigned long BIO_number_written(BIO *bio) 588{ 589 if (bio) 590 return bio->num_write; 591 return 0; 592} 593 594IMPLEMENT_STACK_OF(BIO) 595