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