1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/* crypto/bio/bio_lib.c */
20/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
21 * All rights reserved.
22 *
23 * This package is an SSL implementation written
24 * by Eric Young (eay@cryptsoft.com).
25 * The implementation was written so as to conform with Netscapes SSL.
26 *
27 * This library is free for commercial and non-commercial use as long as
28 * the following conditions are aheared to.  The following conditions
29 * apply to all code found in this distribution, be it the RC4, RSA,
30 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
31 * included with this distribution is covered by the same copyright terms
32 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
33 *
34 * Copyright remains Eric Young's, and as such any Copyright notices in
35 * the code are not to be removed.
36 * If this package is used in a product, Eric Young should be given attribution
37 * as the author of the parts of the library used.
38 * This can be in the form of a textual message at program startup or
39 * in documentation (online or textual) provided with the package.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the copyright
45 *    notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 *    notice, this list of conditions and the following disclaimer in the
48 *    documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 *    must display the following acknowledgement:
51 *    "This product includes cryptographic software written by
52 *     Eric Young (eay@cryptsoft.com)"
53 *    The word 'cryptographic' can be left out if the rouines from the library
54 *    being used are not cryptographic related :-).
55 * 4. If you include any Windows specific code (or a derivative thereof) from
56 *    the apps directory (application code) you must include an acknowledgement:
57 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
58 *
59 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * The licence and distribution terms for any publically available version or
72 * derivative of this code cannot be changed.  i.e. this code cannot simply be
73 * copied and put under another distribution licence
74 * [including the GNU Public Licence.]
75 */
76
77#include <stdio.h>
78#include <errno.h>
79#include <openssl/crypto.h>
80#include "cryptlib.h"
81#include <openssl/bio.h>
82#include <openssl/stack.h>
83
84static STACK_OF(CRYPTO_EX_DATA_FUNCS) *bio_meth=NULL;
85static int bio_meth_num=0;
86
87BIO *BIO_new(const BIO_METHOD *method)
88	{
89	BIO *ret=NULL;
90
91	ret=(BIO *)Malloc(sizeof(BIO));
92	if (ret == NULL)
93		{
94		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
95		return(NULL);
96		}
97	if (!BIO_set(ret,method))
98		{
99		Free(ret);
100		ret=NULL;
101		}
102	return(ret);
103	}
104
105int BIO_set(BIO *bio, const BIO_METHOD *method)
106	{
107	bio->method=method;
108	bio->callback=NULL;
109	bio->cb_arg=NULL;
110	bio->init=0;
111	bio->shutdown=1;
112	bio->flags=0;
113	bio->retry_reason=0;
114	bio->num=0;
115	bio->ptr=NULL;
116	bio->prev_bio=NULL;
117	bio->next_bio=NULL;
118	bio->references=1;
119	bio->num_read=0L;
120	bio->num_write=0L;
121	CRYPTO_new_ex_data(bio_meth,bio,&bio->ex_data);
122	if (method->create != NULL)
123		if (!method->create(bio))
124			return(0);
125	return(1);
126	}
127
128int BIO_free(BIO *a)
129	{
130	int ret=0,i;
131
132	if (a == NULL) return(0);
133
134	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
135#ifdef REF_PRINT
136	REF_PRINT("BIO",a);
137#endif
138	if (i > 0) return(1);
139#ifdef REF_CHECK
140	if (i < 0)
141		{
142		fprintf(stderr,"BIO_free, bad reference count\n");
143		abort();
144		}
145#endif
146	if ((a->callback != NULL) &&
147		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
148			return(i);
149
150	CRYPTO_free_ex_data(bio_meth,a,&a->ex_data);
151
152	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
153	ret=a->method->destroy(a);
154	Free(a);
155	return(1);
156	}
157
158int BIO_read(BIO *b, void *out, int outl)
159	{
160	int i;
161	long (*cb)();
162
163	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
164		{
165		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
166		return(-2);
167		}
168
169	cb=b->callback;
170	if ((cb != NULL) &&
171		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
172			return(i);
173
174	if (!b->init)
175		{
176		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
177		return(-2);
178		}
179
180	i=b->method->bread(b,out,outl);
181
182	if (i > 0) b->num_read+=(unsigned long)i;
183
184	if (cb != NULL)
185		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
186			0L,(long)i);
187	return(i);
188	}
189
190int BIO_write(BIO *b, const void *in, int inl)
191	{
192	int i;
193	long (*cb)();
194
195	if (b == NULL)
196		return(0);
197
198	cb=b->callback;
199	if ((b->method == NULL) || (b->method->bwrite == NULL))
200		{
201		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
202		return(-2);
203		}
204
205	if ((cb != NULL) &&
206		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
207			return(i);
208
209	if (!b->init)
210		{
211		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
212		return(-2);
213		}
214
215	i=b->method->bwrite(b,in,inl);
216
217	if (i > 0) b->num_write+=(unsigned long)i;
218
219	/* This is evil and not thread safe.  If the BIO has been freed,
220	 * we must not call the callback.  The only way to be able to
221	 * determine this is the reference count which is now invalid since
222	 * the memory has been free()ed.
223	 */
224	if (b->references <= 0) abort();
225	if (cb != NULL) /* && (b->references >= 1)) */
226		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
227			0L,(long)i);
228	return(i);
229	}
230
231int BIO_puts(BIO *b, const char *in)
232	{
233	int i;
234	long (*cb)();
235
236	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
237		{
238		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
239		return(-2);
240		}
241
242	cb=b->callback;
243
244	if ((cb != NULL) &&
245		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
246			return(i);
247
248	if (!b->init)
249		{
250		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
251		return(-2);
252		}
253
254	i=b->method->bputs(b,in);
255
256	if (cb != NULL)
257		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
258			0L,(long)i);
259	return(i);
260	}
261
262int BIO_gets(BIO *b, char *in, int inl)
263	{
264	int i;
265	long (*cb)();
266
267	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
268		{
269		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
270		return(-2);
271		}
272
273	cb=b->callback;
274
275	if ((cb != NULL) &&
276		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
277			return(i);
278
279	if (!b->init)
280		{
281		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
282		return(-2);
283		}
284
285	i=b->method->bgets(b,in,inl);
286
287	if (cb != NULL)
288		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
289			0L,(long)i);
290	return(i);
291	}
292
293long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
294	{
295	int i;
296
297	i=iarg;
298	return(BIO_ctrl(b,cmd,larg,(char *)&i));
299	}
300
301char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
302	{
303	char *p=NULL;
304
305	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
306		return(NULL);
307	else
308		return(p);
309	}
310
311long BIO_ctrl(BIO *b, int cmd, long larg, void *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
338long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)())
339	{
340	long ret;
341	long (*cb)();
342
343	if (b == NULL) return(0);
344
345	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
346		{
347		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
348		return(-2);
349		}
350
351	cb=b->callback;
352
353	if ((cb != NULL) &&
354		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
355		return(ret);
356
357	ret=b->method->callback_ctrl(b,cmd,fp);
358
359	if (cb != NULL)
360		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
361			0,ret);
362	return(ret);
363	}
364
365/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
366 * do; but those macros have inappropriate return type, and for interfacing
367 * from other programming languages, C macros aren't much of a help anyway. */
368size_t BIO_ctrl_pending(BIO *bio)
369	{
370	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
371	}
372
373size_t BIO_ctrl_wpending(BIO *bio)
374	{
375	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
376	}
377
378
379/* put the 'bio' on the end of b's list of operators */
380BIO *BIO_push(BIO *b, BIO *bio)
381	{
382	BIO *lb;
383
384	if (b == NULL) return(bio);
385	lb=b;
386	while (lb->next_bio != NULL)
387		lb=lb->next_bio;
388	lb->next_bio=bio;
389	if (bio != NULL)
390		bio->prev_bio=lb;
391	/* called to do internal processing */
392	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
393	return(b);
394	}
395
396/* Remove the first and return the rest */
397BIO *BIO_pop(BIO *b)
398	{
399	BIO *ret;
400
401	if (b == NULL) return(NULL);
402	ret=b->next_bio;
403
404	if (b->prev_bio != NULL)
405		b->prev_bio->next_bio=b->next_bio;
406	if (b->next_bio != NULL)
407		b->next_bio->prev_bio=b->prev_bio;
408
409	b->next_bio=NULL;
410	b->prev_bio=NULL;
411	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
412	return(ret);
413	}
414
415BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
416	{
417	BIO *b,*last;
418
419	b=last=bio;
420	for (;;)
421		{
422		if (!BIO_should_retry(b)) break;
423		last=b;
424		b=b->next_bio;
425		if (b == NULL) break;
426		}
427	if (reason != NULL) *reason=last->retry_reason;
428	return(last);
429	}
430
431int BIO_get_retry_reason(BIO *bio)
432	{
433	return(bio->retry_reason);
434	}
435
436BIO *BIO_find_type(BIO *bio, int type)
437	{
438	int mt,mask;
439
440	mask=type&0xff;
441	do	{
442		if (bio->method != NULL)
443			{
444			mt=bio->method->type;
445
446			if (!mask)
447				{
448				if (mt & type) return(bio);
449				}
450			else if (mt == type)
451				return(bio);
452			}
453		bio=bio->next_bio;
454		} while (bio != NULL);
455	return(NULL);
456	}
457
458void BIO_free_all(BIO *bio)
459	{
460	BIO *b;
461	int ref;
462
463	while (bio != NULL)
464		{
465		b=bio;
466		ref=b->references;
467		bio=bio->next_bio;
468		BIO_free(b);
469		/* Since ref count > 1, don't free anyone else. */
470		if (ref > 1) break;
471		}
472	}
473
474BIO *BIO_dup_chain(BIO *in)
475	{
476	BIO *ret=NULL,*eoc=NULL,*bio,*new;
477
478	for (bio=in; bio != NULL; bio=bio->next_bio)
479		{
480		if ((new=BIO_new(bio->method)) == NULL) goto err;
481		new->callback=bio->callback;
482		new->cb_arg=bio->cb_arg;
483		new->init=bio->init;
484		new->shutdown=bio->shutdown;
485		new->flags=bio->flags;
486
487		/* This will let SSL_s_sock() work with stdin/stdout */
488		new->num=bio->num;
489
490		if (!BIO_dup_state(bio,(char *)new))
491			{
492			BIO_free(new);
493			goto err;
494			}
495
496		/* copy app data */
497		if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data))
498			goto err;
499
500		if (ret == NULL)
501			{
502			eoc=new;
503			ret=eoc;
504			}
505		else
506			{
507			BIO_push(eoc,new);
508			eoc=new;
509			}
510		}
511	return(ret);
512err:
513	if (ret != NULL)
514		BIO_free(ret);
515	return(NULL);
516	}
517
518void BIO_copy_next_retry(BIO *b)
519	{
520	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
521	b->retry_reason=b->next_bio->retry_reason;
522	}
523
524int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
525	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
526	{
527	bio_meth_num++;
528	return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth,
529		argl,argp,new_func,dup_func,free_func));
530	}
531
532int BIO_set_ex_data(BIO *bio, int idx, void *data)
533	{
534	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
535	}
536
537void *BIO_get_ex_data(BIO *bio, int idx)
538	{
539	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
540	}
541
542unsigned long BIO_number_read(BIO *bio)
543{
544	if(bio) return bio->num_read;
545	return 0;
546}
547
548unsigned long BIO_number_written(BIO *bio)
549{
550	if(bio) return bio->num_write;
551	return 0;
552}
553