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