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