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