bio_lib.c 12.4 KB
Newer Older
R
Rich Salz 已提交
1 2
/*
 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9 10 11
 */

#include <stdio.h>
#include <errno.h>
12
#include <openssl/crypto.h>
M
Matt Caswell 已提交
13
#include "bio_lcl.h"
14
#include "internal/cryptlib.h"
15

16
BIO *BIO_new(const BIO_METHOD *method)
17
{
F
FdaSilvaYY 已提交
18
    BIO *bio = OPENSSL_zalloc(sizeof(*bio));
19

F
FdaSilvaYY 已提交
20
    if (bio == NULL) {
21 22 23
        BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
        return (NULL);
    }
24

25 26 27
    bio->method = method;
    bio->shutdown = 1;
    bio->references = 1;
F
FdaSilvaYY 已提交
28

29
    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data))
F
FdaSilvaYY 已提交
30
        goto err;
31 32 33

    bio->lock = CRYPTO_THREAD_lock_new();
    if (bio->lock == NULL) {
F
FdaSilvaYY 已提交
34
        BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
35
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
F
FdaSilvaYY 已提交
36
        goto err;
37 38
    }

F
FdaSilvaYY 已提交
39 40 41 42 43
    if (method->create != NULL && !method->create(bio)) {
        BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL);
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
        CRYPTO_THREAD_lock_free(bio->lock);
        goto err;
44 45
    }

F
FdaSilvaYY 已提交
46 47 48 49 50
    return bio;

err:
    OPENSSL_free(bio);
    return NULL;
51
}
52

U
Ulf Möller 已提交
53
int BIO_free(BIO *a)
54 55
{
    int i;
56

57
    if (a == NULL)
58 59 60 61
        return 0;

    if (CRYPTO_atomic_add(&a->references, -1, &i, a->lock) <= 0)
        return 0;
62

R
Rich Salz 已提交
63
    REF_PRINT_COUNT("BIO", a);
64
    if (i > 0)
65
        return 1;
R
Rich Salz 已提交
66
    REF_ASSERT_ISNT(i < 0);
67 68
    if ((a->callback != NULL) &&
        ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
69
        return i;
70

71 72 73
    if ((a->method != NULL) && (a->method->destroy != NULL))
        a->method->destroy(a);

74
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
75

76 77
    CRYPTO_THREAD_lock_free(a->lock);

78
    OPENSSL_free(a);
79 80

    return 1;
81
}
82

M
Matt Caswell 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
void BIO_set_data(BIO *a, void *ptr)
{
    a->ptr = ptr;
}

void *BIO_get_data(BIO *a)
{
    return a->ptr;
}

void BIO_set_init(BIO *a, int init)
{
    a->init = init;
}

int BIO_get_init(BIO *a)
{
    return a->init;
}

void BIO_set_shutdown(BIO *a, int shut)
{
    a->shutdown = shut;
}

int BIO_get_shutdown(BIO *a)
{
    return a->shutdown;
}

B
Ben Laurie 已提交
113
void BIO_vfree(BIO *a)
114 115 116
{
    BIO_free(a);
}
B
Ben Laurie 已提交
117

118 119 120 121 122 123 124 125 126 127 128 129
int BIO_up_ref(BIO *a)
{
    int i;

    if (CRYPTO_atomic_add(&a->references, 1, &i, a->lock) <= 0)
        return 0;

    REF_PRINT_COUNT("BIO", a);
    REF_ASSERT_ISNT(i < 2);
    return ((i > 1) ? 1 : 0);
}

N
Nils Larsch 已提交
130
void BIO_clear_flags(BIO *b, int flags)
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
{
    b->flags &= ~flags;
}

int BIO_test_flags(const BIO *b, int flags)
{
    return (b->flags & flags);
}

void BIO_set_flags(BIO *b, int flags)
{
    b->flags |= flags;
}

long (*BIO_get_callback(const BIO *b)) (struct bio_st *, int, const char *,
                                        int, long, long) {
    return b->callback;
}

void BIO_set_callback(BIO *b,
                      long (*cb) (struct bio_st *, int, const char *, int,
                                  long, long))
{
    b->callback = cb;
}
N
Nils Larsch 已提交
156 157

void BIO_set_callback_arg(BIO *b, char *arg)
158 159 160
{
    b->cb_arg = arg;
}
N
Nils Larsch 已提交
161

162 163 164 165
char *BIO_get_callback_arg(const BIO *b)
{
    return b->cb_arg;
}
N
Nils Larsch 已提交
166

167 168 169 170
const char *BIO_method_name(const BIO *b)
{
    return b->method->name;
}
N
Nils Larsch 已提交
171 172

int BIO_method_type(const BIO *b)
173 174 175
{
    return b->method->type;
}
N
Nils Larsch 已提交
176

B
Ben Laurie 已提交
177
int BIO_read(BIO *b, void *out, int outl)
178 179 180
{
    int i;
    long (*cb) (BIO *, int, const char *, int, long, long);
181

182 183 184 185
    if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
        BIOerr(BIO_F_BIO_READ, BIO_R_UNSUPPORTED_METHOD);
        return (-2);
    }
186

187 188 189 190
    cb = b->callback;
    if ((cb != NULL) &&
        ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
        return (i);
191

192 193 194 195
    if (!b->init) {
        BIOerr(BIO_F_BIO_READ, BIO_R_UNINITIALIZED);
        return (-2);
    }
196

197
    i = b->method->bread(b, out, outl);
198

199
    if (i > 0)
200
        b->num_read += (uint64_t)i;
201

202 203 204 205
    if (cb != NULL)
        i = (int)cb(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0L, (long)i);
    return (i);
}
206

207
int BIO_write(BIO *b, const void *in, int inl)
208 209 210
{
    int i;
    long (*cb) (BIO *, int, const char *, int, long, long);
211

212 213
    if (b == NULL)
        return (0);
214

215 216 217 218 219
    cb = b->callback;
    if ((b->method == NULL) || (b->method->bwrite == NULL)) {
        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNSUPPORTED_METHOD);
        return (-2);
    }
220

221 222 223
    if ((cb != NULL) &&
        ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0))
        return (i);
224

225 226 227 228
    if (!b->init) {
        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNINITIALIZED);
        return (-2);
    }
229

230
    i = b->method->bwrite(b, in, inl);
231

232
    if (i > 0)
233
        b->num_write += (uint64_t)i;
234

235 236 237 238
    if (cb != NULL)
        i = (int)cb(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl, 0L, (long)i);
    return (i);
}
239

U
Ulf Möller 已提交
240
int BIO_puts(BIO *b, const char *in)
241 242 243
{
    int i;
    long (*cb) (BIO *, int, const char *, int, long, long);
244

245 246 247 248
    if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
        BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
        return (-2);
    }
249

250
    cb = b->callback;
251

252 253
    if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0))
        return (i);
254

255 256 257 258
    if (!b->init) {
        BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
        return (-2);
    }
259

260
    i = b->method->bputs(b, in);
261

262
    if (i > 0)
263
        b->num_write += (uint64_t)i;
264

265 266 267 268
    if (cb != NULL)
        i = (int)cb(b, BIO_CB_PUTS | BIO_CB_RETURN, in, 0, 0L, (long)i);
    return (i);
}
269

U
Ulf Möller 已提交
270
int BIO_gets(BIO *b, char *in, int inl)
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
{
    int i;
    long (*cb) (BIO *, int, const char *, int, long, long);

    if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
        BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
        return (-2);
    }

    cb = b->callback;

    if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0))
        return (i);

    if (!b->init) {
        BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
        return (-2);
    }

    i = b->method->bgets(b, in, inl);

    if (cb != NULL)
        i = (int)cb(b, BIO_CB_GETS | BIO_CB_RETURN, in, inl, 0L, (long)i);
    return (i);
}

int BIO_indent(BIO *b, int indent, int max)
{
    if (indent < 0)
        indent = 0;
    if (indent > max)
        indent = max;
    while (indent--)
        if (BIO_puts(b, " ") != 1)
            return 0;
    return 1;
}
308

U
Ulf Möller 已提交
309
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
310 311
{
    int i;
312

313 314 315
    i = iarg;
    return (BIO_ctrl(b, cmd, larg, (char *)&i));
}
316

317
void *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
318
{
319
    void *p = NULL;
320

321 322 323 324 325
    if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
        return (NULL);
    else
        return (p);
}
326

B
Bodo Möller 已提交
327
long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
328 329 330
{
    long ret;
    long (*cb) (BIO *, int, const char *, int, long, long);
331

332 333
    if (b == NULL)
        return (0);
334

335 336 337 338
    if ((b->method == NULL) || (b->method->ctrl == NULL)) {
        BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
        return (-2);
    }
339

340
    cb = b->callback;
341

342 343 344
    if ((cb != NULL) &&
        ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0))
        return (ret);
345

346
    ret = b->method->ctrl(b, cmd, larg, parg);
347

348 349 350 351
    if (cb != NULL)
        ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret);
    return (ret);
}
352

353 354 355 356 357 358
long BIO_callback_ctrl(BIO *b, int cmd,
                       void (*fp) (struct bio_st *, int, const char *, int,
                                   long, long))
{
    long ret;
    long (*cb) (BIO *, int, const char *, int, long, long);
359

360 361
    if (b == NULL)
        return (0);
362

363 364 365 366
    if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
        BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
        return (-2);
    }
367

368
    cb = b->callback;
369

370 371 372
    if ((cb != NULL) &&
        ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0))
        return (ret);
373

374
    ret = b->method->callback_ctrl(b, cmd, fp);
375

376 377 378 379
    if (cb != NULL)
        ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
    return (ret);
}
380

381 382
/*
 * It is unfortunate to duplicate in functions what the BIO_(w)pending macros
B
Bodo Möller 已提交
383
 * do; but those macros have inappropriate return type, and for interfacing
384 385
 * from other programming languages, C macros aren't much of a help anyway.
 */
B
Bodo Möller 已提交
386
size_t BIO_ctrl_pending(BIO *bio)
387 388 389
{
    return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
}
B
Bodo Möller 已提交
390 391

size_t BIO_ctrl_wpending(BIO *bio)
392 393 394
{
    return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
}
B
Bodo Möller 已提交
395

396
/* put the 'bio' on the end of b's list of operators */
U
Ulf Möller 已提交
397
BIO *BIO_push(BIO *b, BIO *bio)
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
{
    BIO *lb;

    if (b == NULL)
        return (bio);
    lb = b;
    while (lb->next_bio != NULL)
        lb = lb->next_bio;
    lb->next_bio = bio;
    if (bio != NULL)
        bio->prev_bio = lb;
    /* called to do internal processing */
    BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
    return (b);
}
413 414

/* Remove the first and return the rest */
U
Ulf Möller 已提交
415
BIO *BIO_pop(BIO *b)
416 417
{
    BIO *ret;
418

419 420 421
    if (b == NULL)
        return (NULL);
    ret = b->next_bio;
422

423
    BIO_ctrl(b, BIO_CTRL_POP, 0, b);
424

425 426 427 428
    if (b->prev_bio != NULL)
        b->prev_bio->next_bio = b->next_bio;
    if (b->next_bio != NULL)
        b->next_bio->prev_bio = b->prev_bio;
429

430 431 432 433
    b->next_bio = NULL;
    b->prev_bio = NULL;
    return (ret);
}
434

U
Ulf Möller 已提交
435
BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
{
    BIO *b, *last;

    b = last = bio;
    for (;;) {
        if (!BIO_should_retry(b))
            break;
        last = b;
        b = b->next_bio;
        if (b == NULL)
            break;
    }
    if (reason != NULL)
        *reason = last->retry_reason;
    return (last);
}
452

U
Ulf Möller 已提交
453
int BIO_get_retry_reason(BIO *bio)
454 455 456
{
    return (bio->retry_reason);
}
457

M
Matt Caswell 已提交
458 459 460 461 462
void BIO_set_retry_reason(BIO *bio, int reason)
{
    bio->retry_reason = reason;
}

U
Ulf Möller 已提交
463
BIO *BIO_find_type(BIO *bio, int type)
464 465 466
{
    int mt, mask;

R
Rich Salz 已提交
467
    if (bio == NULL)
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
        return NULL;
    mask = type & 0xff;
    do {
        if (bio->method != NULL) {
            mt = bio->method->type;

            if (!mask) {
                if (mt & type)
                    return (bio);
            } else if (mt == type)
                return (bio);
        }
        bio = bio->next_bio;
    } while (bio != NULL);
    return (NULL);
}
484

D
 
Dr. Stephen Henson 已提交
485
BIO *BIO_next(BIO *b)
486
{
R
Rich Salz 已提交
487
    if (b == NULL)
488 489 490
        return NULL;
    return b->next_bio;
}
D
 
Dr. Stephen Henson 已提交
491

M
Matt Caswell 已提交
492 493 494 495 496
void BIO_set_next(BIO *b, BIO *next)
{
    b->next_bio = next;
}

U
Ulf Möller 已提交
497
void BIO_free_all(BIO *bio)
498 499 500 501 502 503 504 505 506 507 508 509 510 511
{
    BIO *b;
    int ref;

    while (bio != NULL) {
        b = bio;
        ref = b->references;
        bio = bio->next_bio;
        BIO_free(b);
        /* Since ref count > 1, don't free anyone else. */
        if (ref > 1)
            break;
    }
}
512

U
Ulf Möller 已提交
513
BIO *BIO_dup_chain(BIO *in)
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
{
    BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;

    for (bio = in; bio != NULL; bio = bio->next_bio) {
        if ((new_bio = BIO_new(bio->method)) == NULL)
            goto err;
        new_bio->callback = bio->callback;
        new_bio->cb_arg = bio->cb_arg;
        new_bio->init = bio->init;
        new_bio->shutdown = bio->shutdown;
        new_bio->flags = bio->flags;

        /* This will let SSL_s_sock() work with stdin/stdout */
        new_bio->num = bio->num;

        if (!BIO_dup_state(bio, (char *)new_bio)) {
            BIO_free(new_bio);
            goto err;
        }

        /* copy app data */
        if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
536 537
                                &bio->ex_data)) {
            BIO_free(new_bio);
538
            goto err;
539
        }
540 541 542 543 544 545 546 547 548 549 550

        if (ret == NULL) {
            eoc = new_bio;
            ret = eoc;
        } else {
            BIO_push(eoc, new_bio);
            eoc = new_bio;
        }
    }
    return (ret);
 err:
551 552
    BIO_free_all(ret);

553 554
    return (NULL);
}
555

U
Ulf Möller 已提交
556
void BIO_copy_next_retry(BIO *b)
557 558 559 560
{
    BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
    b->retry_reason = b->next_bio->retry_reason;
}
561

D
 
Dr. Stephen Henson 已提交
562
int BIO_set_ex_data(BIO *bio, int idx, void *data)
563 564 565
{
    return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
}
566

D
 
Dr. Stephen Henson 已提交
567
void *BIO_get_ex_data(BIO *bio, int idx)
568 569 570
{
    return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
}
571

572
uint64_t BIO_number_read(BIO *bio)
573
{
574 575 576
    if (bio)
        return bio->num_read;
    return 0;
577 578
}

579
uint64_t BIO_number_written(BIO *bio)
580
{
581 582 583
    if (bio)
        return bio->num_write;
    return 0;
584
}
585

M
Matt Caswell 已提交
586 587 588 589
void bio_free_ex_data(BIO *bio)
{
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
}
590 591 592 593 594 595 596

void bio_cleanup(void)
{
#ifndef OPENSSL_NO_SOCK
    bio_sock_cleanup_int();
    CRYPTO_THREAD_lock_free(bio_lookup_lock);
    bio_lookup_lock = NULL;
R
Rich Salz 已提交
597 598
    CRYPTO_THREAD_lock_free(bio_type_lock);
    bio_type_lock = NULL;
599 600
#endif
}