bio_lib.c revision 59191
155714Skris/* crypto/bio/bio_lib.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <errno.h>
6155714Skris#include <openssl/crypto.h>
6255714Skris#include "cryptlib.h"
6355714Skris#include <openssl/bio.h>
6455714Skris#include <openssl/stack.h>
6555714Skris
6659191Skrisstatic STACK_OF(CRYPTO_EX_DATA_FUNCS) *bio_meth=NULL;
6755714Skrisstatic int bio_meth_num=0;
6855714Skris
6955714SkrisBIO *BIO_new(BIO_METHOD *method)
7055714Skris	{
7155714Skris	BIO *ret=NULL;
7255714Skris
7355714Skris	ret=(BIO *)Malloc(sizeof(BIO));
7455714Skris	if (ret == NULL)
7555714Skris		{
7655714Skris		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
7755714Skris		return(NULL);
7855714Skris		}
7955714Skris	if (!BIO_set(ret,method))
8055714Skris		{
8155714Skris		Free(ret);
8255714Skris		ret=NULL;
8355714Skris		}
8455714Skris	return(ret);
8555714Skris	}
8655714Skris
8755714Skrisint BIO_set(BIO *bio, BIO_METHOD *method)
8855714Skris	{
8955714Skris	bio->method=method;
9055714Skris	bio->callback=NULL;
9155714Skris	bio->cb_arg=NULL;
9255714Skris	bio->init=0;
9355714Skris	bio->shutdown=1;
9455714Skris	bio->flags=0;
9555714Skris	bio->retry_reason=0;
9655714Skris	bio->num=0;
9755714Skris	bio->ptr=NULL;
9855714Skris	bio->prev_bio=NULL;
9955714Skris	bio->next_bio=NULL;
10055714Skris	bio->references=1;
10155714Skris	bio->num_read=0L;
10255714Skris	bio->num_write=0L;
10359191Skris	CRYPTO_new_ex_data(bio_meth,bio,&bio->ex_data);
10455714Skris	if (method->create != NULL)
10555714Skris		if (!method->create(bio))
10655714Skris			return(0);
10755714Skris	return(1);
10855714Skris	}
10955714Skris
11055714Skrisint BIO_free(BIO *a)
11155714Skris	{
11255714Skris	int ret=0,i;
11355714Skris
11455714Skris	if (a == NULL) return(0);
11555714Skris
11655714Skris	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
11755714Skris#ifdef REF_PRINT
11855714Skris	REF_PRINT("BIO",a);
11955714Skris#endif
12055714Skris	if (i > 0) return(1);
12155714Skris#ifdef REF_CHECK
12255714Skris	if (i < 0)
12355714Skris		{
12455714Skris		fprintf(stderr,"BIO_free, bad reference count\n");
12555714Skris		abort();
12655714Skris		}
12755714Skris#endif
12855714Skris	if ((a->callback != NULL) &&
12955714Skris		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
13055714Skris			return(i);
13155714Skris
13259191Skris	CRYPTO_free_ex_data(bio_meth,a,&a->ex_data);
13355714Skris
13455714Skris	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
13555714Skris	ret=a->method->destroy(a);
13655714Skris	Free(a);
13755714Skris	return(1);
13855714Skris	}
13955714Skris
14055714Skrisint BIO_read(BIO *b, void *out, int outl)
14155714Skris	{
14255714Skris	int i;
14355714Skris	long (*cb)();
14455714Skris
14555714Skris	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
14655714Skris		{
14755714Skris		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
14855714Skris		return(-2);
14955714Skris		}
15055714Skris
15155714Skris	cb=b->callback;
15255714Skris	if ((cb != NULL) &&
15355714Skris		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
15455714Skris			return(i);
15555714Skris
15655714Skris	if (!b->init)
15755714Skris		{
15855714Skris		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
15955714Skris		return(-2);
16055714Skris		}
16155714Skris
16255714Skris	i=b->method->bread(b,out,outl);
16355714Skris
16455714Skris	if (i > 0) b->num_read+=(unsigned long)i;
16555714Skris
16655714Skris	if (cb != NULL)
16755714Skris		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
16855714Skris			0L,(long)i);
16955714Skris	return(i);
17055714Skris	}
17155714Skris
17259191Skrisint BIO_write(BIO *b, const void *in, int inl)
17355714Skris	{
17455714Skris	int i;
17555714Skris	long (*cb)();
17655714Skris
17755714Skris	if (b == NULL)
17855714Skris		return(0);
17955714Skris
18055714Skris	cb=b->callback;
18155714Skris	if ((b->method == NULL) || (b->method->bwrite == NULL))
18255714Skris		{
18355714Skris		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
18455714Skris		return(-2);
18555714Skris		}
18655714Skris
18755714Skris	if ((cb != NULL) &&
18855714Skris		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
18955714Skris			return(i);
19055714Skris
19155714Skris	if (!b->init)
19255714Skris		{
19355714Skris		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
19455714Skris		return(-2);
19555714Skris		}
19655714Skris
19755714Skris	i=b->method->bwrite(b,in,inl);
19855714Skris
19955714Skris	if (i > 0) b->num_write+=(unsigned long)i;
20055714Skris
20155714Skris	/* This is evil and not thread safe.  If the BIO has been freed,
20255714Skris	 * we must not call the callback.  The only way to be able to
20355714Skris	 * determine this is the reference count which is now invalid since
20455714Skris	 * the memory has been free()ed.
20555714Skris	 */
20655714Skris	if (b->references <= 0) abort();
20755714Skris	if (cb != NULL) /* && (b->references >= 1)) */
20855714Skris		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
20955714Skris			0L,(long)i);
21055714Skris	return(i);
21155714Skris	}
21255714Skris
21355714Skrisint BIO_puts(BIO *b, const char *in)
21455714Skris	{
21555714Skris	int i;
21655714Skris	long (*cb)();
21755714Skris
21855714Skris	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
21955714Skris		{
22055714Skris		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
22155714Skris		return(-2);
22255714Skris		}
22355714Skris
22455714Skris	cb=b->callback;
22555714Skris
22655714Skris	if ((cb != NULL) &&
22755714Skris		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
22855714Skris			return(i);
22955714Skris
23055714Skris	if (!b->init)
23155714Skris		{
23255714Skris		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
23355714Skris		return(-2);
23455714Skris		}
23555714Skris
23655714Skris	i=b->method->bputs(b,in);
23755714Skris
23855714Skris	if (cb != NULL)
23955714Skris		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
24055714Skris			0L,(long)i);
24155714Skris	return(i);
24255714Skris	}
24355714Skris
24455714Skrisint BIO_gets(BIO *b, char *in, int inl)
24555714Skris	{
24655714Skris	int i;
24755714Skris	long (*cb)();
24855714Skris
24955714Skris	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
25055714Skris		{
25155714Skris		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
25255714Skris		return(-2);
25355714Skris		}
25455714Skris
25555714Skris	cb=b->callback;
25655714Skris
25755714Skris	if ((cb != NULL) &&
25855714Skris		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
25955714Skris			return(i);
26055714Skris
26155714Skris	if (!b->init)
26255714Skris		{
26355714Skris		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
26455714Skris		return(-2);
26555714Skris		}
26655714Skris
26755714Skris	i=b->method->bgets(b,in,inl);
26855714Skris
26955714Skris	if (cb != NULL)
27055714Skris		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
27155714Skris			0L,(long)i);
27255714Skris	return(i);
27355714Skris	}
27455714Skris
27555714Skrislong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
27655714Skris	{
27755714Skris	int i;
27855714Skris
27955714Skris	i=iarg;
28055714Skris	return(BIO_ctrl(b,cmd,larg,(char *)&i));
28155714Skris	}
28255714Skris
28355714Skrischar *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
28455714Skris	{
28555714Skris	char *p=NULL;
28655714Skris
28755714Skris	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
28855714Skris		return(NULL);
28955714Skris	else
29055714Skris		return(p);
29155714Skris	}
29255714Skris
29355714Skrislong BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
29455714Skris	{
29555714Skris	long ret;
29655714Skris	long (*cb)();
29755714Skris
29855714Skris	if (b == NULL) return(0);
29955714Skris
30055714Skris	if ((b->method == NULL) || (b->method->ctrl == NULL))
30155714Skris		{
30255714Skris		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
30355714Skris		return(-2);
30455714Skris		}
30555714Skris
30655714Skris	cb=b->callback;
30755714Skris
30855714Skris	if ((cb != NULL) &&
30955714Skris		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
31055714Skris		return(ret);
31155714Skris
31255714Skris	ret=b->method->ctrl(b,cmd,larg,parg);
31355714Skris
31455714Skris	if (cb != NULL)
31555714Skris		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
31655714Skris			larg,ret);
31755714Skris	return(ret);
31855714Skris	}
31955714Skris
32059191Skrislong BIO_callback_ctrl(BIO *b, int cmd, void (*fp)())
32159191Skris	{
32259191Skris	long ret;
32359191Skris	long (*cb)();
32459191Skris
32559191Skris	if (b == NULL) return(0);
32659191Skris
32759191Skris	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
32859191Skris		{
32959191Skris		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
33059191Skris		return(-2);
33159191Skris		}
33259191Skris
33359191Skris	cb=b->callback;
33459191Skris
33559191Skris	if ((cb != NULL) &&
33659191Skris		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
33759191Skris		return(ret);
33859191Skris
33959191Skris	ret=b->method->callback_ctrl(b,cmd,fp);
34059191Skris
34159191Skris	if (cb != NULL)
34259191Skris		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
34359191Skris			0,ret);
34459191Skris	return(ret);
34559191Skris	}
34659191Skris
34755714Skris/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
34855714Skris * do; but those macros have inappropriate return type, and for interfacing
34955714Skris * from other programming languages, C macros aren't much of a help anyway. */
35055714Skrissize_t BIO_ctrl_pending(BIO *bio)
35159191Skris	{
35255714Skris	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
35355714Skris	}
35455714Skris
35555714Skrissize_t BIO_ctrl_wpending(BIO *bio)
35659191Skris	{
35755714Skris	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
35855714Skris	}
35955714Skris
36055714Skris
36155714Skris/* put the 'bio' on the end of b's list of operators */
36255714SkrisBIO *BIO_push(BIO *b, BIO *bio)
36355714Skris	{
36455714Skris	BIO *lb;
36555714Skris
36655714Skris	if (b == NULL) return(bio);
36755714Skris	lb=b;
36855714Skris	while (lb->next_bio != NULL)
36955714Skris		lb=lb->next_bio;
37055714Skris	lb->next_bio=bio;
37155714Skris	if (bio != NULL)
37255714Skris		bio->prev_bio=lb;
37355714Skris	/* called to do internal processing */
37455714Skris	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
37555714Skris	return(b);
37655714Skris	}
37755714Skris
37855714Skris/* Remove the first and return the rest */
37955714SkrisBIO *BIO_pop(BIO *b)
38055714Skris	{
38155714Skris	BIO *ret;
38255714Skris
38355714Skris	if (b == NULL) return(NULL);
38455714Skris	ret=b->next_bio;
38555714Skris
38655714Skris	if (b->prev_bio != NULL)
38755714Skris		b->prev_bio->next_bio=b->next_bio;
38855714Skris	if (b->next_bio != NULL)
38955714Skris		b->next_bio->prev_bio=b->prev_bio;
39055714Skris
39155714Skris	b->next_bio=NULL;
39255714Skris	b->prev_bio=NULL;
39355714Skris	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
39455714Skris	return(ret);
39555714Skris	}
39655714Skris
39755714SkrisBIO *BIO_get_retry_BIO(BIO *bio, int *reason)
39855714Skris	{
39955714Skris	BIO *b,*last;
40055714Skris
40155714Skris	b=last=bio;
40255714Skris	for (;;)
40355714Skris		{
40455714Skris		if (!BIO_should_retry(b)) break;
40555714Skris		last=b;
40655714Skris		b=b->next_bio;
40755714Skris		if (b == NULL) break;
40855714Skris		}
40955714Skris	if (reason != NULL) *reason=last->retry_reason;
41055714Skris	return(last);
41155714Skris	}
41255714Skris
41355714Skrisint BIO_get_retry_reason(BIO *bio)
41455714Skris	{
41555714Skris	return(bio->retry_reason);
41655714Skris	}
41755714Skris
41855714SkrisBIO *BIO_find_type(BIO *bio, int type)
41955714Skris	{
42055714Skris	int mt,mask;
42155714Skris
42255714Skris	mask=type&0xff;
42355714Skris	do	{
42455714Skris		if (bio->method != NULL)
42555714Skris			{
42655714Skris			mt=bio->method->type;
42755714Skris
42855714Skris			if (!mask)
42955714Skris				{
43055714Skris				if (mt & type) return(bio);
43155714Skris				}
43255714Skris			else if (mt == type)
43355714Skris				return(bio);
43455714Skris			}
43555714Skris		bio=bio->next_bio;
43655714Skris		} while (bio != NULL);
43755714Skris	return(NULL);
43855714Skris	}
43955714Skris
44055714Skrisvoid BIO_free_all(BIO *bio)
44155714Skris	{
44255714Skris	BIO *b;
44355714Skris	int ref;
44455714Skris
44555714Skris	while (bio != NULL)
44655714Skris		{
44755714Skris		b=bio;
44855714Skris		ref=b->references;
44955714Skris		bio=bio->next_bio;
45055714Skris		BIO_free(b);
45155714Skris		/* Since ref count > 1, don't free anyone else. */
45255714Skris		if (ref > 1) break;
45355714Skris		}
45455714Skris	}
45555714Skris
45655714SkrisBIO *BIO_dup_chain(BIO *in)
45755714Skris	{
45855714Skris	BIO *ret=NULL,*eoc=NULL,*bio,*new;
45955714Skris
46055714Skris	for (bio=in; bio != NULL; bio=bio->next_bio)
46155714Skris		{
46255714Skris		if ((new=BIO_new(bio->method)) == NULL) goto err;
46355714Skris		new->callback=bio->callback;
46455714Skris		new->cb_arg=bio->cb_arg;
46555714Skris		new->init=bio->init;
46655714Skris		new->shutdown=bio->shutdown;
46755714Skris		new->flags=bio->flags;
46855714Skris
46955714Skris		/* This will let SSL_s_sock() work with stdin/stdout */
47055714Skris		new->num=bio->num;
47155714Skris
47255714Skris		if (!BIO_dup_state(bio,(char *)new))
47355714Skris			{
47455714Skris			BIO_free(new);
47555714Skris			goto err;
47655714Skris			}
47755714Skris
47855714Skris		/* copy app data */
47955714Skris		if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data))
48055714Skris			goto err;
48155714Skris
48255714Skris		if (ret == NULL)
48355714Skris			{
48455714Skris			eoc=new;
48555714Skris			ret=eoc;
48655714Skris			}
48755714Skris		else
48855714Skris			{
48955714Skris			BIO_push(eoc,new);
49055714Skris			eoc=new;
49155714Skris			}
49255714Skris		}
49355714Skris	return(ret);
49455714Skriserr:
49555714Skris	if (ret != NULL)
49655714Skris		BIO_free(ret);
49755714Skris	return(NULL);
49855714Skris	}
49955714Skris
50055714Skrisvoid BIO_copy_next_retry(BIO *b)
50155714Skris	{
50255714Skris	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
50355714Skris	b->retry_reason=b->next_bio->retry_reason;
50455714Skris	}
50555714Skris
50659191Skrisint BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
50759191Skris	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
50855714Skris	{
50955714Skris	bio_meth_num++;
51055714Skris	return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth,
51155714Skris		argl,argp,new_func,dup_func,free_func));
51255714Skris	}
51355714Skris
51459191Skrisint BIO_set_ex_data(BIO *bio, int idx, void *data)
51555714Skris	{
51655714Skris	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
51755714Skris	}
51855714Skris
51959191Skrisvoid *BIO_get_ex_data(BIO *bio, int idx)
52055714Skris	{
52155714Skris	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
52255714Skris	}
52355714Skris
52459191Skrisunsigned long BIO_number_read(BIO *bio)
52559191Skris{
52659191Skris	if(bio) return bio->num_read;
52759191Skris	return 0;
52859191Skris}
52959191Skris
53059191Skrisunsigned long BIO_number_written(BIO *bio)
53159191Skris{
53259191Skris	if(bio) return bio->num_write;
53359191Skris	return 0;
53459191Skris}
535