Coverage Report

Created: 2022-11-30 06:20

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