| 1 | /* | 
| 2 |  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  * | 
| 4 |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
| 5 |  * this file except in compliance with the License.  You can obtain a copy | 
| 6 |  * in the file LICENSE in the source distribution or at | 
| 7 |  * https://www.openssl.org/source/license.html | 
| 8 |  */ | 
| 9 |  | 
| 10 | #include <stdio.h> | 
| 11 | #include <errno.h> | 
| 12 | #include <openssl/crypto.h> | 
| 13 | #include "bio_local.h" | 
| 14 | #include "internal/cryptlib.h" | 
| 15 |  | 
| 16 |  | 
| 17 | /* | 
| 18 |  * Helper macro for the callback to determine whether an operator expects a | 
| 19 |  * len parameter or not | 
| 20 |  */ | 
| 21 | #define HAS_LEN_OPER(o)        ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \ | 
| 22 |                                 (o) == BIO_CB_GETS) | 
| 23 |  | 
| 24 | /* | 
| 25 |  * Helper function to work out whether to call the new style callback or the old | 
| 26 |  * one, and translate between the two. | 
| 27 |  * | 
| 28 |  * This has a long return type for consistency with the old callback. Similarly | 
| 29 |  * for the "long" used for "inret" | 
| 30 |  */ | 
| 31 | static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len, | 
| 32 |                               int argi, long argl, long inret, size_t *processed) | 
| 33 | { | 
| 34 |     long ret; | 
| 35 |     int bareoper; | 
| 36 |  | 
| 37 |     if (b->callback_ex != NULL) | 
| 38 |         return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed); | 
| 39 |  | 
| 40 |     /* Strip off any BIO_CB_RETURN flag */ | 
| 41 |     bareoper = oper & ~BIO_CB_RETURN; | 
| 42 |  | 
| 43 |     /* | 
| 44 |      * We have an old style callback, so we will have to do nasty casts and | 
| 45 |      * check for overflows. | 
| 46 |      */ | 
| 47 |     if (HAS_LEN_OPER(bareoper)) { | 
| 48 |         /* In this case |len| is set, and should be used instead of |argi| */ | 
| 49 |         if (len > INT_MAX) | 
| 50 |             return -1; | 
| 51 |  | 
| 52 |         argi = (int)len; | 
| 53 |     } | 
| 54 |  | 
| 55 |     if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { | 
| 56 |         if (*processed > INT_MAX) | 
| 57 |             return -1; | 
| 58 |         inret = *processed; | 
| 59 |     } | 
| 60 |  | 
| 61 |     ret = b->callback(b, oper, argp, argi, argl, inret); | 
| 62 |  | 
| 63 |     if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { | 
| 64 |         *processed = (size_t)ret; | 
| 65 |         ret = 1; | 
| 66 |     } | 
| 67 |  | 
| 68 |     return ret; | 
| 69 | } | 
| 70 |  | 
| 71 | BIO *BIO_new(const BIO_METHOD *method) | 
| 72 | { | 
| 73 |     BIO *bio = OPENSSL_zalloc(sizeof(*bio)); | 
| 74 |  | 
| 75 |     if (bio == NULL) { | 
| 76 |         BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); | 
| 77 |         return NULL; | 
| 78 |     } | 
| 79 |  | 
| 80 |     bio->method = method; | 
| 81 |     bio->shutdown = 1; | 
| 82 |     bio->references = 1; | 
| 83 |  | 
| 84 |     if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data)) | 
| 85 |         goto err; | 
| 86 |  | 
| 87 |     bio->lock = CRYPTO_THREAD_lock_new(); | 
| 88 |     if (bio->lock == NULL) { | 
| 89 |         BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); | 
| 90 |         CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); | 
| 91 |         goto err; | 
| 92 |     } | 
| 93 |  | 
| 94 |     if (method->create != NULL && !method->create(bio)) { | 
| 95 |         BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL); | 
| 96 |         CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); | 
| 97 |         CRYPTO_THREAD_lock_free(bio->lock); | 
| 98 |         goto err; | 
| 99 |     } | 
| 100 |     if (method->create == NULL) | 
| 101 |         bio->init = 1; | 
| 102 |  | 
| 103 |     return bio; | 
| 104 |  | 
| 105 | err: | 
| 106 |     OPENSSL_free(bio); | 
| 107 |     return NULL; | 
| 108 | } | 
| 109 |  | 
| 110 | int BIO_free(BIO *a) | 
| 111 | { | 
| 112 |     int ret; | 
| 113 |  | 
| 114 |     if (a == NULL) | 
| 115 |         return 0; | 
| 116 |  | 
| 117 |     if (CRYPTO_DOWN_REF(&a->references, &ret, a->lock) <= 0) | 
| 118 |         return 0; | 
| 119 |  | 
| 120 |     REF_PRINT_COUNT("BIO" , a); | 
| 121 |     if (ret > 0) | 
| 122 |         return 1; | 
| 123 |     REF_ASSERT_ISNT(ret < 0); | 
| 124 |  | 
| 125 |     if (a->callback != NULL || a->callback_ex != NULL) { | 
| 126 |         ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL); | 
| 127 |         if (ret <= 0) | 
| 128 |             return ret; | 
| 129 |     } | 
| 130 |  | 
| 131 |     if ((a->method != NULL) && (a->method->destroy != NULL)) | 
| 132 |         a->method->destroy(a); | 
| 133 |  | 
| 134 |     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); | 
| 135 |  | 
| 136 |     CRYPTO_THREAD_lock_free(a->lock); | 
| 137 |  | 
| 138 |     OPENSSL_free(a); | 
| 139 |  | 
| 140 |     return 1; | 
| 141 | } | 
| 142 |  | 
| 143 | void BIO_set_data(BIO *a, void *ptr) | 
| 144 | { | 
| 145 |     a->ptr = ptr; | 
| 146 | } | 
| 147 |  | 
| 148 | void *BIO_get_data(BIO *a) | 
| 149 | { | 
| 150 |     return a->ptr; | 
| 151 | } | 
| 152 |  | 
| 153 | void BIO_set_init(BIO *a, int init) | 
| 154 | { | 
| 155 |     a->init = init; | 
| 156 | } | 
| 157 |  | 
| 158 | int BIO_get_init(BIO *a) | 
| 159 | { | 
| 160 |     return a->init; | 
| 161 | } | 
| 162 |  | 
| 163 | void BIO_set_shutdown(BIO *a, int shut) | 
| 164 | { | 
| 165 |     a->shutdown = shut; | 
| 166 | } | 
| 167 |  | 
| 168 | int BIO_get_shutdown(BIO *a) | 
| 169 | { | 
| 170 |     return a->shutdown; | 
| 171 | } | 
| 172 |  | 
| 173 | void BIO_vfree(BIO *a) | 
| 174 | { | 
| 175 |     BIO_free(a); | 
| 176 | } | 
| 177 |  | 
| 178 | int BIO_up_ref(BIO *a) | 
| 179 | { | 
| 180 |     int i; | 
| 181 |  | 
| 182 |     if (CRYPTO_UP_REF(&a->references, &i, a->lock) <= 0) | 
| 183 |         return 0; | 
| 184 |  | 
| 185 |     REF_PRINT_COUNT("BIO" , a); | 
| 186 |     REF_ASSERT_ISNT(i < 2); | 
| 187 |     return ((i > 1) ? 1 : 0); | 
| 188 | } | 
| 189 |  | 
| 190 | void BIO_clear_flags(BIO *b, int flags) | 
| 191 | { | 
| 192 |     b->flags &= ~flags; | 
| 193 | } | 
| 194 |  | 
| 195 | int BIO_test_flags(const BIO *b, int flags) | 
| 196 | { | 
| 197 |     return (b->flags & flags); | 
| 198 | } | 
| 199 |  | 
| 200 | void BIO_set_flags(BIO *b, int flags) | 
| 201 | { | 
| 202 |     b->flags |= flags; | 
| 203 | } | 
| 204 |  | 
| 205 | BIO_callback_fn BIO_get_callback(const BIO *b) | 
| 206 | { | 
| 207 |     return b->callback; | 
| 208 | } | 
| 209 |  | 
| 210 | void BIO_set_callback(BIO *b, BIO_callback_fn cb) | 
| 211 | { | 
| 212 |     b->callback = cb; | 
| 213 | } | 
| 214 |  | 
| 215 | BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b) | 
| 216 | { | 
| 217 |     return b->callback_ex; | 
| 218 | } | 
| 219 |  | 
| 220 | void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb) | 
| 221 | { | 
| 222 |     b->callback_ex = cb; | 
| 223 | } | 
| 224 |  | 
| 225 | void BIO_set_callback_arg(BIO *b, char *arg) | 
| 226 | { | 
| 227 |     b->cb_arg = arg; | 
| 228 | } | 
| 229 |  | 
| 230 | char *BIO_get_callback_arg(const BIO *b) | 
| 231 | { | 
| 232 |     return b->cb_arg; | 
| 233 | } | 
| 234 |  | 
| 235 | const char *BIO_method_name(const BIO *b) | 
| 236 | { | 
| 237 |     return b->method->name; | 
| 238 | } | 
| 239 |  | 
| 240 | int BIO_method_type(const BIO *b) | 
| 241 | { | 
| 242 |     return b->method->type; | 
| 243 | } | 
| 244 |  | 
| 245 | /* | 
| 246 |  * This is essentially the same as BIO_read_ex() except that it allows | 
| 247 |  * 0 or a negative value to indicate failure (retryable or not) in the return. | 
| 248 |  * This is for compatibility with the old style BIO_read(), where existing code | 
| 249 |  * may make assumptions about the return value that it might get. | 
| 250 |  */ | 
| 251 | static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes) | 
| 252 | { | 
| 253 |     int ret; | 
| 254 |  | 
| 255 |     if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) { | 
| 256 |         BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNSUPPORTED_METHOD); | 
| 257 |         return -2; | 
| 258 |     } | 
| 259 |  | 
| 260 |     if ((b->callback != NULL || b->callback_ex != NULL) && | 
| 261 |         ((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L, | 
| 262 |                                        NULL)) <= 0)) | 
| 263 |         return ret; | 
| 264 |  | 
| 265 |     if (!b->init) { | 
| 266 |         BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED); | 
| 267 |         return -2; | 
| 268 |     } | 
| 269 |  | 
| 270 |     ret = b->method->bread(b, data, dlen, readbytes); | 
| 271 |  | 
| 272 |     if (ret > 0) | 
| 273 |         b->num_read += (uint64_t)*readbytes; | 
| 274 |  | 
| 275 |     if (b->callback != NULL || b->callback_ex != NULL) | 
| 276 |         ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data, | 
| 277 |                                      dlen, 0, 0L, ret, readbytes); | 
| 278 |  | 
| 279 |     /* Shouldn't happen */ | 
| 280 |     if (ret > 0 && *readbytes > dlen) { | 
| 281 |         BIOerr(BIO_F_BIO_READ_INTERN, ERR_R_INTERNAL_ERROR); | 
| 282 |         return -1; | 
| 283 |     } | 
| 284 |  | 
| 285 |     return ret; | 
| 286 | } | 
| 287 |  | 
| 288 | int BIO_read(BIO *b, void *data, int dlen) | 
| 289 | { | 
| 290 |     size_t readbytes; | 
| 291 |     int ret; | 
| 292 |  | 
| 293 |     if (dlen < 0) | 
| 294 |         return 0; | 
| 295 |  | 
| 296 |     ret = bio_read_intern(b, data, (size_t)dlen, &readbytes); | 
| 297 |  | 
| 298 |     if (ret > 0) { | 
| 299 |         /* *readbytes should always be <= dlen */ | 
| 300 |         ret = (int)readbytes; | 
| 301 |     } | 
| 302 |  | 
| 303 |     return ret; | 
| 304 | } | 
| 305 |  | 
| 306 | int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes) | 
| 307 | { | 
| 308 |     int ret; | 
| 309 |  | 
| 310 |     ret = bio_read_intern(b, data, dlen, readbytes); | 
| 311 |  | 
| 312 |     if (ret > 0) | 
| 313 |         ret = 1; | 
| 314 |     else | 
| 315 |         ret = 0; | 
| 316 |  | 
| 317 |     return ret; | 
| 318 | } | 
| 319 |  | 
| 320 | static int bio_write_intern(BIO *b, const void *data, size_t dlen, | 
| 321 |                             size_t *written) | 
| 322 | { | 
| 323 |     int ret; | 
| 324 |  | 
| 325 |     if (b == NULL) | 
| 326 |         return 0; | 
| 327 |  | 
| 328 |     if ((b->method == NULL) || (b->method->bwrite == NULL)) { | 
| 329 |         BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNSUPPORTED_METHOD); | 
| 330 |         return -2; | 
| 331 |     } | 
| 332 |  | 
| 333 |     if ((b->callback != NULL || b->callback_ex != NULL) && | 
| 334 |         ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L, | 
| 335 |                                        NULL)) <= 0)) | 
| 336 |         return ret; | 
| 337 |  | 
| 338 |     if (!b->init) { | 
| 339 |         BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNINITIALIZED); | 
| 340 |         return -2; | 
| 341 |     } | 
| 342 |  | 
| 343 |     ret = b->method->bwrite(b, data, dlen, written); | 
| 344 |  | 
| 345 |     if (ret > 0) | 
| 346 |         b->num_write += (uint64_t)*written; | 
| 347 |  | 
| 348 |     if (b->callback != NULL || b->callback_ex != NULL) | 
| 349 |         ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data, | 
| 350 |                                      dlen, 0, 0L, ret, written); | 
| 351 |  | 
| 352 |     return ret; | 
| 353 | } | 
| 354 |  | 
| 355 | int BIO_write(BIO *b, const void *data, int dlen) | 
| 356 | { | 
| 357 |     size_t written; | 
| 358 |     int ret; | 
| 359 |  | 
| 360 |     if (dlen < 0) | 
| 361 |         return 0; | 
| 362 |  | 
| 363 |     ret = bio_write_intern(b, data, (size_t)dlen, &written); | 
| 364 |  | 
| 365 |     if (ret > 0) { | 
| 366 |         /* *written should always be <= dlen */ | 
| 367 |         ret = (int)written; | 
| 368 |     } | 
| 369 |  | 
| 370 |     return ret; | 
| 371 | } | 
| 372 |  | 
| 373 | int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written) | 
| 374 | { | 
| 375 |     int ret; | 
| 376 |  | 
| 377 |     ret = bio_write_intern(b, data, dlen, written); | 
| 378 |  | 
| 379 |     if (ret > 0) | 
| 380 |         ret = 1; | 
| 381 |     else | 
| 382 |         ret = 0; | 
| 383 |  | 
| 384 |     return ret; | 
| 385 | } | 
| 386 |  | 
| 387 | int BIO_puts(BIO *b, const char *buf) | 
| 388 | { | 
| 389 |     int ret; | 
| 390 |     size_t written = 0; | 
| 391 |  | 
| 392 |     if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { | 
| 393 |         BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD); | 
| 394 |         return -2; | 
| 395 |     } | 
| 396 |  | 
| 397 |     if (b->callback != NULL || b->callback_ex != NULL) { | 
| 398 |         ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL); | 
| 399 |         if (ret <= 0) | 
| 400 |             return ret; | 
| 401 |     } | 
| 402 |  | 
| 403 |     if (!b->init) { | 
| 404 |         BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED); | 
| 405 |         return -2; | 
| 406 |     } | 
| 407 |  | 
| 408 |     ret = b->method->bputs(b, buf); | 
| 409 |  | 
| 410 |     if (ret > 0) { | 
| 411 |         b->num_write += (uint64_t)ret; | 
| 412 |         written = ret; | 
| 413 |         ret = 1; | 
| 414 |     } | 
| 415 |  | 
| 416 |     if (b->callback != NULL || b->callback_ex != NULL) | 
| 417 |         ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0, | 
| 418 |                                      0L, ret, &written); | 
| 419 |  | 
| 420 |     if (ret > 0) { | 
| 421 |         if (written > INT_MAX) { | 
| 422 |             BIOerr(BIO_F_BIO_PUTS, BIO_R_LENGTH_TOO_LONG); | 
| 423 |             ret = -1; | 
| 424 |         } else { | 
| 425 |             ret = (int)written; | 
| 426 |         } | 
| 427 |     } | 
| 428 |  | 
| 429 |     return ret; | 
| 430 | } | 
| 431 |  | 
| 432 | int BIO_gets(BIO *b, char *buf, int size) | 
| 433 | { | 
| 434 |     int ret; | 
| 435 |     size_t readbytes = 0; | 
| 436 |  | 
| 437 |     if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { | 
| 438 |         BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD); | 
| 439 |         return -2; | 
| 440 |     } | 
| 441 |  | 
| 442 |     if (size < 0) { | 
| 443 |         BIOerr(BIO_F_BIO_GETS, BIO_R_INVALID_ARGUMENT); | 
| 444 |         return 0; | 
| 445 |     } | 
| 446 |  | 
| 447 |     if (b->callback != NULL || b->callback_ex != NULL) { | 
| 448 |         ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL); | 
| 449 |         if (ret <= 0) | 
| 450 |             return ret; | 
| 451 |     } | 
| 452 |  | 
| 453 |     if (!b->init) { | 
| 454 |         BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED); | 
| 455 |         return -2; | 
| 456 |     } | 
| 457 |  | 
| 458 |     ret = b->method->bgets(b, buf, size); | 
| 459 |  | 
| 460 |     if (ret > 0) { | 
| 461 |         readbytes = ret; | 
| 462 |         ret = 1; | 
| 463 |     } | 
| 464 |  | 
| 465 |     if (b->callback != NULL || b->callback_ex != NULL) | 
| 466 |         ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size, | 
| 467 |                                      0, 0L, ret, &readbytes); | 
| 468 |  | 
| 469 |     if (ret > 0) { | 
| 470 |         /* Shouldn't happen */ | 
| 471 |         if (readbytes > (size_t)size) | 
| 472 |             ret = -1; | 
| 473 |         else | 
| 474 |             ret = (int)readbytes; | 
| 475 |     } | 
| 476 |  | 
| 477 |     return ret; | 
| 478 | } | 
| 479 |  | 
| 480 | int BIO_indent(BIO *b, int indent, int max) | 
| 481 | { | 
| 482 |     if (indent < 0) | 
| 483 |         indent = 0; | 
| 484 |     if (indent > max) | 
| 485 |         indent = max; | 
| 486 |     while (indent--) | 
| 487 |         if (BIO_puts(b, " " ) != 1) | 
| 488 |             return 0; | 
| 489 |     return 1; | 
| 490 | } | 
| 491 |  | 
| 492 | long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) | 
| 493 | { | 
| 494 |     int i; | 
| 495 |  | 
| 496 |     i = iarg; | 
| 497 |     return BIO_ctrl(b, cmd, larg, (char *)&i); | 
| 498 | } | 
| 499 |  | 
| 500 | void *BIO_ptr_ctrl(BIO *b, int cmd, long larg) | 
| 501 | { | 
| 502 |     void *p = NULL; | 
| 503 |  | 
| 504 |     if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) | 
| 505 |         return NULL; | 
| 506 |     else | 
| 507 |         return p; | 
| 508 | } | 
| 509 |  | 
| 510 | long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) | 
| 511 | { | 
| 512 |     long ret; | 
| 513 |  | 
| 514 |     if (b == NULL) | 
| 515 |         return 0; | 
| 516 |  | 
| 517 |     if ((b->method == NULL) || (b->method->ctrl == NULL)) { | 
| 518 |         BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD); | 
| 519 |         return -2; | 
| 520 |     } | 
| 521 |  | 
| 522 |     if (b->callback != NULL || b->callback_ex != NULL) { | 
| 523 |         ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL); | 
| 524 |         if (ret <= 0) | 
| 525 |             return ret; | 
| 526 |     } | 
| 527 |  | 
| 528 |     ret = b->method->ctrl(b, cmd, larg, parg); | 
| 529 |  | 
| 530 |     if (b->callback != NULL || b->callback_ex != NULL) | 
| 531 |         ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, | 
| 532 |                                 larg, ret, NULL); | 
| 533 |  | 
| 534 |     return ret; | 
| 535 | } | 
| 536 |  | 
| 537 | long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) | 
| 538 | { | 
| 539 |     long ret; | 
| 540 |  | 
| 541 |     if (b == NULL) | 
| 542 |         return 0; | 
| 543 |  | 
| 544 |     if ((b->method == NULL) || (b->method->callback_ctrl == NULL) | 
| 545 |             || (cmd != BIO_CTRL_SET_CALLBACK)) { | 
| 546 |         BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD); | 
| 547 |         return -2; | 
| 548 |     } | 
| 549 |  | 
| 550 |     if (b->callback != NULL || b->callback_ex != NULL) { | 
| 551 |         ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L, | 
| 552 |                                 NULL); | 
| 553 |         if (ret <= 0) | 
| 554 |             return ret; | 
| 555 |     } | 
| 556 |  | 
| 557 |     ret = b->method->callback_ctrl(b, cmd, fp); | 
| 558 |  | 
| 559 |     if (b->callback != NULL || b->callback_ex != NULL) | 
| 560 |         ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0, | 
| 561 |                                 cmd, 0, ret, NULL); | 
| 562 |  | 
| 563 |     return ret; | 
| 564 | } | 
| 565 |  | 
| 566 | /* | 
| 567 |  * It is unfortunate to duplicate in functions what the BIO_(w)pending macros | 
| 568 |  * do; but those macros have inappropriate return type, and for interfacing | 
| 569 |  * from other programming languages, C macros aren't much of a help anyway. | 
| 570 |  */ | 
| 571 | size_t BIO_ctrl_pending(BIO *bio) | 
| 572 | { | 
| 573 |     return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); | 
| 574 | } | 
| 575 |  | 
| 576 | size_t BIO_ctrl_wpending(BIO *bio) | 
| 577 | { | 
| 578 |     return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); | 
| 579 | } | 
| 580 |  | 
| 581 | /* put the 'bio' on the end of b's list of operators */ | 
| 582 | BIO *BIO_push(BIO *b, BIO *bio) | 
| 583 | { | 
| 584 |     BIO *lb; | 
| 585 |  | 
| 586 |     if (b == NULL) | 
| 587 |         return bio; | 
| 588 |     lb = b; | 
| 589 |     while (lb->next_bio != NULL) | 
| 590 |         lb = lb->next_bio; | 
| 591 |     lb->next_bio = bio; | 
| 592 |     if (bio != NULL) | 
| 593 |         bio->prev_bio = lb; | 
| 594 |     /* called to do internal processing */ | 
| 595 |     BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb); | 
| 596 |     return b; | 
| 597 | } | 
| 598 |  | 
| 599 | /* Remove the first and return the rest */ | 
| 600 | BIO *BIO_pop(BIO *b) | 
| 601 | { | 
| 602 |     BIO *ret; | 
| 603 |  | 
| 604 |     if (b == NULL) | 
| 605 |         return NULL; | 
| 606 |     ret = b->next_bio; | 
| 607 |  | 
| 608 |     BIO_ctrl(b, BIO_CTRL_POP, 0, b); | 
| 609 |  | 
| 610 |     if (b->prev_bio != NULL) | 
| 611 |         b->prev_bio->next_bio = b->next_bio; | 
| 612 |     if (b->next_bio != NULL) | 
| 613 |         b->next_bio->prev_bio = b->prev_bio; | 
| 614 |  | 
| 615 |     b->next_bio = NULL; | 
| 616 |     b->prev_bio = NULL; | 
| 617 |     return ret; | 
| 618 | } | 
| 619 |  | 
| 620 | BIO *BIO_get_retry_BIO(BIO *bio, int *reason) | 
| 621 | { | 
| 622 |     BIO *b, *last; | 
| 623 |  | 
| 624 |     b = last = bio; | 
| 625 |     for (;;) { | 
| 626 |         if (!BIO_should_retry(b)) | 
| 627 |             break; | 
| 628 |         last = b; | 
| 629 |         b = b->next_bio; | 
| 630 |         if (b == NULL) | 
| 631 |             break; | 
| 632 |     } | 
| 633 |     if (reason != NULL) | 
| 634 |         *reason = last->retry_reason; | 
| 635 |     return last; | 
| 636 | } | 
| 637 |  | 
| 638 | int BIO_get_retry_reason(BIO *bio) | 
| 639 | { | 
| 640 |     return bio->retry_reason; | 
| 641 | } | 
| 642 |  | 
| 643 | void BIO_set_retry_reason(BIO *bio, int reason) | 
| 644 | { | 
| 645 |     bio->retry_reason = reason; | 
| 646 | } | 
| 647 |  | 
| 648 | BIO *BIO_find_type(BIO *bio, int type) | 
| 649 | { | 
| 650 |     int mt, mask; | 
| 651 |  | 
| 652 |     if (bio == NULL) | 
| 653 |         return NULL; | 
| 654 |     mask = type & 0xff; | 
| 655 |     do { | 
| 656 |         if (bio->method != NULL) { | 
| 657 |             mt = bio->method->type; | 
| 658 |  | 
| 659 |             if (!mask) { | 
| 660 |                 if (mt & type) | 
| 661 |                     return bio; | 
| 662 |             } else if (mt == type) | 
| 663 |                 return bio; | 
| 664 |         } | 
| 665 |         bio = bio->next_bio; | 
| 666 |     } while (bio != NULL); | 
| 667 |     return NULL; | 
| 668 | } | 
| 669 |  | 
| 670 | BIO *BIO_next(BIO *b) | 
| 671 | { | 
| 672 |     if (b == NULL) | 
| 673 |         return NULL; | 
| 674 |     return b->next_bio; | 
| 675 | } | 
| 676 |  | 
| 677 | void BIO_set_next(BIO *b, BIO *next) | 
| 678 | { | 
| 679 |     b->next_bio = next; | 
| 680 | } | 
| 681 |  | 
| 682 | void BIO_free_all(BIO *bio) | 
| 683 | { | 
| 684 |     BIO *b; | 
| 685 |     int ref; | 
| 686 |  | 
| 687 |     while (bio != NULL) { | 
| 688 |         b = bio; | 
| 689 |         ref = b->references; | 
| 690 |         bio = bio->next_bio; | 
| 691 |         BIO_free(b); | 
| 692 |         /* Since ref count > 1, don't free anyone else. */ | 
| 693 |         if (ref > 1) | 
| 694 |             break; | 
| 695 |     } | 
| 696 | } | 
| 697 |  | 
| 698 | BIO *BIO_dup_chain(BIO *in) | 
| 699 | { | 
| 700 |     BIO *ret = NULL, *eoc = NULL, *bio, *new_bio; | 
| 701 |  | 
| 702 |     for (bio = in; bio != NULL; bio = bio->next_bio) { | 
| 703 |         if ((new_bio = BIO_new(bio->method)) == NULL) | 
| 704 |             goto err; | 
| 705 |         new_bio->callback = bio->callback; | 
| 706 |         new_bio->callback_ex = bio->callback_ex; | 
| 707 |         new_bio->cb_arg = bio->cb_arg; | 
| 708 |         new_bio->init = bio->init; | 
| 709 |         new_bio->shutdown = bio->shutdown; | 
| 710 |         new_bio->flags = bio->flags; | 
| 711 |  | 
| 712 |         /* This will let SSL_s_sock() work with stdin/stdout */ | 
| 713 |         new_bio->num = bio->num; | 
| 714 |  | 
| 715 |         if (!BIO_dup_state(bio, (char *)new_bio)) { | 
| 716 |             BIO_free(new_bio); | 
| 717 |             goto err; | 
| 718 |         } | 
| 719 |  | 
| 720 |         /* copy app data */ | 
| 721 |         if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, | 
| 722 |                                 &bio->ex_data)) { | 
| 723 |             BIO_free(new_bio); | 
| 724 |             goto err; | 
| 725 |         } | 
| 726 |  | 
| 727 |         if (ret == NULL) { | 
| 728 |             eoc = new_bio; | 
| 729 |             ret = eoc; | 
| 730 |         } else { | 
| 731 |             BIO_push(eoc, new_bio); | 
| 732 |             eoc = new_bio; | 
| 733 |         } | 
| 734 |     } | 
| 735 |     return ret; | 
| 736 |  err: | 
| 737 |     BIO_free_all(ret); | 
| 738 |  | 
| 739 |     return NULL; | 
| 740 | } | 
| 741 |  | 
| 742 | void BIO_copy_next_retry(BIO *b) | 
| 743 | { | 
| 744 |     BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); | 
| 745 |     b->retry_reason = b->next_bio->retry_reason; | 
| 746 | } | 
| 747 |  | 
| 748 | int BIO_set_ex_data(BIO *bio, int idx, void *data) | 
| 749 | { | 
| 750 |     return CRYPTO_set_ex_data(&(bio->ex_data), idx, data); | 
| 751 | } | 
| 752 |  | 
| 753 | void *BIO_get_ex_data(BIO *bio, int idx) | 
| 754 | { | 
| 755 |     return CRYPTO_get_ex_data(&(bio->ex_data), idx); | 
| 756 | } | 
| 757 |  | 
| 758 | uint64_t BIO_number_read(BIO *bio) | 
| 759 | { | 
| 760 |     if (bio) | 
| 761 |         return bio->num_read; | 
| 762 |     return 0; | 
| 763 | } | 
| 764 |  | 
| 765 | uint64_t BIO_number_written(BIO *bio) | 
| 766 | { | 
| 767 |     if (bio) | 
| 768 |         return bio->num_write; | 
| 769 |     return 0; | 
| 770 | } | 
| 771 |  | 
| 772 | void bio_free_ex_data(BIO *bio) | 
| 773 | { | 
| 774 |     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); | 
| 775 | } | 
| 776 |  | 
| 777 | void bio_cleanup(void) | 
| 778 | { | 
| 779 | #ifndef OPENSSL_NO_SOCK | 
| 780 |     bio_sock_cleanup_int(); | 
| 781 |     CRYPTO_THREAD_lock_free(bio_lookup_lock); | 
| 782 |     bio_lookup_lock = NULL; | 
| 783 | #endif | 
| 784 |     CRYPTO_THREAD_lock_free(bio_type_lock); | 
| 785 |     bio_type_lock = NULL; | 
| 786 | } | 
| 787 |  |