xref: /openbsd-src/lib/libcrypto/bio/bio_lib.c (revision 62a742911104f98b9185b2c6b6007d9b1c36396c)
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 "crypto.h"
62 #include "cryptlib.h"
63 #include "bio.h"
64 #include "stack.h"
65 
66 static STACK *bio_meth=NULL;
67 static int bio_meth_num=0;
68 
69 BIO *BIO_new(method)
70 BIO_METHOD *method;
71 	{
72 	BIO *ret=NULL;
73 
74 	ret=(BIO *)Malloc(sizeof(BIO));
75 	if (ret == NULL)
76 		{
77 		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
78 		return(NULL);
79 		}
80 	if (!BIO_set(ret,method))
81 		{
82 		Free(ret);
83 		ret=NULL;
84 		}
85 	return(ret);
86 	}
87 
88 int BIO_set(bio,method)
89 BIO *bio;
90 BIO_METHOD *method;
91 	{
92 	bio->method=method;
93 	bio->callback=NULL;
94 	bio->cb_arg=NULL;
95 	bio->init=0;
96 	bio->shutdown=1;
97 	bio->flags=0;
98 	bio->retry_reason=0;
99 	bio->num=0;
100 	bio->ptr=NULL;
101 	bio->prev_bio=NULL;
102 	bio->next_bio=NULL;
103 	bio->references=1;
104 	bio->num_read=0L;
105 	bio->num_write=0L;
106 	CRYPTO_new_ex_data(bio_meth,(char *)bio,&bio->ex_data);
107 	if (method->create != NULL)
108 		if (!method->create(bio))
109 			return(0);
110 	return(1);
111 	}
112 
113 int BIO_free(a)
114 BIO *a;
115 	{
116 	int ret=0,i;
117 
118 	if (a == NULL) return(0);
119 
120 	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
121 #ifdef REF_PRINT
122 	REF_PRINT("BIO",a);
123 #endif
124         if (i > 0) return(1);
125 #ifdef REF_CHECK
126 	if (i < 0)
127 		{
128 		fprintf(stderr,"BIO_free, bad reference count\n");
129 		abort();
130 		}
131 #endif
132 	if ((a->callback != NULL) &&
133 		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
134 			return(i);
135 
136 	CRYPTO_free_ex_data(bio_meth,(char *)a,&a->ex_data);
137 
138 	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
139 	ret=a->method->destroy(a);
140 	Free(a);
141 	return(1);
142 	}
143 
144 int BIO_read(b,out,outl)
145 BIO *b;
146 char *out;
147 int outl;
148 	{
149 	int i;
150 	long (*cb)();
151 
152 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
153 		{
154 		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
155 		return(-2);
156 		}
157 
158 	cb=b->callback;
159 	if ((cb != NULL) &&
160 		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
161 			return(i);
162 
163 	if (!b->init)
164 		{
165 		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITALISED);
166 		return(-2);
167 		}
168 
169 	i=b->method->bread(b,out,outl);
170 	if (i > 0) b->num_read+=(unsigned long)i;
171 
172 	if (cb != NULL)
173 		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
174 			0L,(long)i);
175 	return(i);
176 	}
177 
178 int BIO_write(b,in,inl)
179 BIO *b;
180 char *in;
181 int inl;
182 	{
183 	int i;
184 	long (*cb)();
185 
186 	if (b == NULL)
187 		return(0);
188 
189 	cb=b->callback;
190 	if ((b->method == NULL) || (b->method->bwrite == NULL))
191 		{
192 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
193 		return(-2);
194 		}
195 
196 	if ((cb != NULL) &&
197 		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
198 			return(i);
199 
200 	if (!b->init)
201 		{
202 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITALISED);
203 		return(-2);
204 		}
205 
206 	i=b->method->bwrite(b,in,inl);
207 	if (i > 0) b->num_write+=(unsigned long)i;
208 
209 	if (cb != NULL)
210 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
211 			0L,(long)i);
212 	return(i);
213 	}
214 
215 int BIO_puts(b,in)
216 BIO *b;
217 char *in;
218 	{
219 	int i;
220 	long (*cb)();
221 
222 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
223 		{
224 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
225 		return(-2);
226 		}
227 
228 	cb=b->callback;
229 
230 	if ((cb != NULL) &&
231 		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
232 			return(i);
233 
234 	if (!b->init)
235 		{
236 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITALISED);
237 		return(-2);
238 		}
239 
240 	i=b->method->bputs(b,in);
241 
242 	if (cb != NULL)
243 		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
244 			0L,(long)i);
245 	return(i);
246 	}
247 
248 int BIO_gets(b,in,inl)
249 BIO *b;
250 char *in;
251 int inl;
252 	{
253 	int i;
254 	long (*cb)();
255 
256 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
257 		{
258 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
259 		return(-2);
260 		}
261 
262 	cb=b->callback;
263 
264 	if ((cb != NULL) &&
265 		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
266 			return(i);
267 
268 	if (!b->init)
269 		{
270 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITALISED);
271 		return(-2);
272 		}
273 
274 	i=b->method->bgets(b,in,inl);
275 
276 	if (cb != NULL)
277 		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
278 			0L,(long)i);
279 	return(i);
280 	}
281 
282 long BIO_int_ctrl(b,cmd,larg,iarg)
283 BIO *b;
284 int cmd;
285 long larg;
286 int iarg;
287 	{
288 	int i;
289 
290 	i=iarg;
291 	return(BIO_ctrl(b,cmd,larg,(char *)&i));
292 	}
293 
294 char *BIO_ptr_ctrl(b,cmd,larg)
295 BIO *b;
296 int cmd;
297 long larg;
298 	{
299 	char *p=NULL;
300 
301 	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
302 		return(NULL);
303 	else
304 		return(p);
305 	}
306 
307 long BIO_ctrl(b,cmd,larg,parg)
308 BIO *b;
309 int cmd;
310 long larg;
311 char *parg;
312 	{
313 	long ret;
314 	long (*cb)();
315 
316 	if (b == NULL) return(0);
317 
318 	if ((b->method == NULL) || (b->method->ctrl == NULL))
319 		{
320 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
321 		return(-2);
322 		}
323 
324 	cb=b->callback;
325 
326 	if ((cb != NULL) &&
327 		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
328 		return(ret);
329 
330 	ret=b->method->ctrl(b,cmd,larg,parg);
331 
332 	if (cb != NULL)
333 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
334 			larg,ret);
335 	return(ret);
336 	}
337 
338 /* put the 'bio' on the end of b's list of operators */
339 BIO *BIO_push(b,bio)
340 BIO *b,*bio;
341 	{
342 	BIO *lb;
343 
344 	if (b == NULL) return(bio);
345 	lb=b;
346 	while (lb->next_bio != NULL)
347 		lb=lb->next_bio;
348 	lb->next_bio=bio;
349 	if (bio != NULL)
350 		bio->prev_bio=lb;
351 	/* called to do internal processing */
352 	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
353 	return(b);
354 	}
355 
356 /* Remove the first and return the rest */
357 BIO *BIO_pop(b)
358 BIO *b;
359 	{
360 	BIO *ret;
361 
362 	if (b == NULL) return(NULL);
363 	ret=b->next_bio;
364 
365 	if (b->prev_bio != NULL)
366 		b->prev_bio->next_bio=b->next_bio;
367 	if (b->next_bio != NULL)
368 		b->next_bio->prev_bio=b->prev_bio;
369 
370 	b->next_bio=NULL;
371 	b->prev_bio=NULL;
372 	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
373 	return(ret);
374 	}
375 
376 BIO *BIO_get_retry_BIO(bio,reason)
377 BIO *bio;
378 int *reason;
379 	{
380 	BIO *b,*last;
381 
382 	b=last=bio;
383 	for (;;)
384 		{
385 		if (!BIO_should_retry(b)) break;
386 		last=b;
387 		b=b->next_bio;
388 		if (b == NULL) break;
389 		}
390 	if (reason != NULL) *reason=last->retry_reason;
391 	return(last);
392 	}
393 
394 int BIO_get_retry_reason(bio)
395 BIO *bio;
396 	{
397 	return(bio->retry_reason);
398 	}
399 
400 BIO *BIO_find_type(bio,type)
401 BIO *bio;
402 int type;
403 	{
404 	int mt,mask;
405 
406 	mask=type&0xff;
407 	do	{
408 		if (bio->method != NULL)
409 			{
410 			mt=bio->method->type;
411 
412 			if (!mask)
413 				{
414 				if (mt & type) return(bio);
415 				}
416 			else if (mt == type)
417 				return(bio);
418 			}
419 		bio=bio->next_bio;
420 		} while (bio != NULL);
421 	return(NULL);
422 	}
423 
424 void BIO_free_all(bio)
425 BIO *bio;
426 	{
427 	BIO *b;
428 	int ref;
429 
430 	while (bio != NULL)
431 		{
432 		b=bio;
433 		ref=b->references;
434 		bio=bio->next_bio;
435 		BIO_free(b);
436 		/* Since ref count > 1, don't free anyone else. */
437 		if (ref > 1) break;
438 		}
439 	}
440 
441 BIO *BIO_dup_chain(in)
442 BIO *in;
443 	{
444 	BIO *ret=NULL,*eoc=NULL,*bio,*new;
445 
446 	for (bio=in; bio != NULL; bio=bio->next_bio)
447 		{
448 		if ((new=BIO_new(bio->method)) == NULL) goto err;
449 		new->callback=bio->callback;
450 		new->cb_arg=bio->cb_arg;
451 		new->init=bio->init;
452 		new->shutdown=bio->shutdown;
453 		new->flags=bio->flags;
454 
455 		/* This will let SSL_s_sock() work with stdin/stdout */
456 		new->num=bio->num;
457 
458 		if (!BIO_dup_state(bio,(char *)new))
459 			{
460 			BIO_free(new);
461 			goto err;
462 			}
463 
464 	        /* copy app data */
465 	        if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data))
466 	                goto err;
467 
468 		if (ret == NULL)
469 			{
470 			eoc=new;
471 			ret=eoc;
472 			}
473 		else
474 			{
475 			BIO_push(eoc,new);
476 			eoc=new;
477 			}
478 		}
479 	return(ret);
480 err:
481 	if (ret != NULL)
482 		BIO_free(ret);
483 	return(NULL);
484 	}
485 
486 void BIO_copy_next_retry(b)
487 BIO *b;
488 	{
489 	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
490 	b->retry_reason=b->next_bio->retry_reason;
491 	}
492 
493 int BIO_get_ex_new_index(argl,argp,new_func,dup_func,free_func)
494 long argl;
495 char *argp;
496 int (*new_func)();
497 int (*dup_func)();
498 void (*free_func)();
499         {
500         bio_meth_num++;
501         return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth,
502                 argl,argp,new_func,dup_func,free_func));
503         }
504 
505 int BIO_set_ex_data(bio,idx,data)
506 BIO *bio;
507 int idx;
508 char *data;
509 	{
510 	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
511 	}
512 
513 char *BIO_get_ex_data(bio,idx)
514 BIO *bio;
515 int idx;
516 	{
517 	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
518 	}
519 
520