bio_lib.c revision 68651
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 7368651Skris ret=(BIO *)OPENSSL_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 { 8168651Skris OPENSSL_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); 13668651Skris OPENSSL_free(a); 13755714Skris return(1); 13855714Skris } 13955714Skris 14068651Skrisvoid BIO_vfree(BIO *a) 14168651Skris { BIO_free(a); } 14268651Skris 14355714Skrisint BIO_read(BIO *b, void *out, int outl) 14455714Skris { 14555714Skris int i; 14655714Skris long (*cb)(); 14755714Skris 14855714Skris if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) 14955714Skris { 15055714Skris BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD); 15155714Skris return(-2); 15255714Skris } 15355714Skris 15455714Skris cb=b->callback; 15555714Skris if ((cb != NULL) && 15655714Skris ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0)) 15755714Skris return(i); 15855714Skris 15955714Skris if (!b->init) 16055714Skris { 16155714Skris BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED); 16255714Skris return(-2); 16355714Skris } 16455714Skris 16555714Skris i=b->method->bread(b,out,outl); 16655714Skris 16755714Skris if (i > 0) b->num_read+=(unsigned long)i; 16855714Skris 16955714Skris if (cb != NULL) 17055714Skris i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl, 17155714Skris 0L,(long)i); 17255714Skris return(i); 17355714Skris } 17455714Skris 17559191Skrisint BIO_write(BIO *b, const void *in, int inl) 17655714Skris { 17755714Skris int i; 17855714Skris long (*cb)(); 17955714Skris 18055714Skris if (b == NULL) 18155714Skris return(0); 18255714Skris 18355714Skris cb=b->callback; 18455714Skris if ((b->method == NULL) || (b->method->bwrite == NULL)) 18555714Skris { 18655714Skris BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD); 18755714Skris return(-2); 18855714Skris } 18955714Skris 19055714Skris if ((cb != NULL) && 19155714Skris ((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0)) 19255714Skris return(i); 19355714Skris 19455714Skris if (!b->init) 19555714Skris { 19655714Skris BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED); 19755714Skris return(-2); 19855714Skris } 19955714Skris 20055714Skris i=b->method->bwrite(b,in,inl); 20155714Skris 20255714Skris if (i > 0) b->num_write+=(unsigned long)i; 20355714Skris 20468651Skris if (cb != NULL) 20555714Skris i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl, 20655714Skris 0L,(long)i); 20755714Skris return(i); 20855714Skris } 20955714Skris 21055714Skrisint BIO_puts(BIO *b, const char *in) 21155714Skris { 21255714Skris int i; 21355714Skris long (*cb)(); 21455714Skris 21555714Skris if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) 21655714Skris { 21755714Skris BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD); 21855714Skris return(-2); 21955714Skris } 22055714Skris 22155714Skris cb=b->callback; 22255714Skris 22355714Skris if ((cb != NULL) && 22455714Skris ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0)) 22555714Skris return(i); 22655714Skris 22755714Skris if (!b->init) 22855714Skris { 22955714Skris BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED); 23055714Skris return(-2); 23155714Skris } 23255714Skris 23355714Skris i=b->method->bputs(b,in); 23455714Skris 23568651Skris if (i > 0) b->num_write+=(unsigned long)i; 23668651Skris 23755714Skris if (cb != NULL) 23855714Skris i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0, 23955714Skris 0L,(long)i); 24055714Skris return(i); 24155714Skris } 24255714Skris 24355714Skrisint BIO_gets(BIO *b, char *in, int inl) 24455714Skris { 24555714Skris int i; 24655714Skris long (*cb)(); 24755714Skris 24855714Skris if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) 24955714Skris { 25055714Skris BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD); 25155714Skris return(-2); 25255714Skris } 25355714Skris 25455714Skris cb=b->callback; 25555714Skris 25655714Skris if ((cb != NULL) && 25755714Skris ((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0)) 25855714Skris return(i); 25955714Skris 26055714Skris if (!b->init) 26155714Skris { 26255714Skris BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED); 26355714Skris return(-2); 26455714Skris } 26555714Skris 26655714Skris i=b->method->bgets(b,in,inl); 26755714Skris 26855714Skris if (cb != NULL) 26955714Skris i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl, 27055714Skris 0L,(long)i); 27155714Skris return(i); 27255714Skris } 27355714Skris 27455714Skrislong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) 27555714Skris { 27655714Skris int i; 27755714Skris 27855714Skris i=iarg; 27955714Skris return(BIO_ctrl(b,cmd,larg,(char *)&i)); 28055714Skris } 28155714Skris 28255714Skrischar *BIO_ptr_ctrl(BIO *b, int cmd, long larg) 28355714Skris { 28455714Skris char *p=NULL; 28555714Skris 28655714Skris if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0) 28755714Skris return(NULL); 28855714Skris else 28955714Skris return(p); 29055714Skris } 29155714Skris 29255714Skrislong BIO_ctrl(BIO *b, int cmd, long larg, void *parg) 29355714Skris { 29455714Skris long ret; 29555714Skris long (*cb)(); 29655714Skris 29755714Skris if (b == NULL) return(0); 29855714Skris 29955714Skris if ((b->method == NULL) || (b->method->ctrl == NULL)) 30055714Skris { 30155714Skris BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); 30255714Skris return(-2); 30355714Skris } 30455714Skris 30555714Skris cb=b->callback; 30655714Skris 30755714Skris if ((cb != NULL) && 30855714Skris ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0)) 30955714Skris return(ret); 31055714Skris 31155714Skris ret=b->method->ctrl(b,cmd,larg,parg); 31255714Skris 31355714Skris if (cb != NULL) 31455714Skris ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd, 31555714Skris larg,ret); 31655714Skris return(ret); 31755714Skris } 31855714Skris 31968651Skrislong BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long)) 32059191Skris { 32159191Skris long ret; 32259191Skris long (*cb)(); 32359191Skris 32459191Skris if (b == NULL) return(0); 32559191Skris 32659191Skris if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) 32759191Skris { 32859191Skris BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); 32959191Skris return(-2); 33059191Skris } 33159191Skris 33259191Skris cb=b->callback; 33359191Skris 33459191Skris if ((cb != NULL) && 33559191Skris ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0)) 33659191Skris return(ret); 33759191Skris 33859191Skris ret=b->method->callback_ctrl(b,cmd,fp); 33959191Skris 34059191Skris if (cb != NULL) 34159191Skris ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd, 34259191Skris 0,ret); 34359191Skris return(ret); 34459191Skris } 34559191Skris 34655714Skris/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros 34755714Skris * do; but those macros have inappropriate return type, and for interfacing 34855714Skris * from other programming languages, C macros aren't much of a help anyway. */ 34955714Skrissize_t BIO_ctrl_pending(BIO *bio) 35059191Skris { 35155714Skris return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 35255714Skris } 35355714Skris 35455714Skrissize_t BIO_ctrl_wpending(BIO *bio) 35559191Skris { 35655714Skris return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 35755714Skris } 35855714Skris 35955714Skris 36055714Skris/* put the 'bio' on the end of b's list of operators */ 36155714SkrisBIO *BIO_push(BIO *b, BIO *bio) 36255714Skris { 36355714Skris BIO *lb; 36455714Skris 36555714Skris if (b == NULL) return(bio); 36655714Skris lb=b; 36755714Skris while (lb->next_bio != NULL) 36855714Skris lb=lb->next_bio; 36955714Skris lb->next_bio=bio; 37055714Skris if (bio != NULL) 37155714Skris bio->prev_bio=lb; 37255714Skris /* called to do internal processing */ 37355714Skris BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL); 37455714Skris return(b); 37555714Skris } 37655714Skris 37755714Skris/* Remove the first and return the rest */ 37855714SkrisBIO *BIO_pop(BIO *b) 37955714Skris { 38055714Skris BIO *ret; 38155714Skris 38255714Skris if (b == NULL) return(NULL); 38355714Skris ret=b->next_bio; 38455714Skris 38555714Skris if (b->prev_bio != NULL) 38655714Skris b->prev_bio->next_bio=b->next_bio; 38755714Skris if (b->next_bio != NULL) 38855714Skris b->next_bio->prev_bio=b->prev_bio; 38955714Skris 39055714Skris b->next_bio=NULL; 39155714Skris b->prev_bio=NULL; 39255714Skris BIO_ctrl(b,BIO_CTRL_POP,0,NULL); 39355714Skris return(ret); 39455714Skris } 39555714Skris 39655714SkrisBIO *BIO_get_retry_BIO(BIO *bio, int *reason) 39755714Skris { 39855714Skris BIO *b,*last; 39955714Skris 40055714Skris b=last=bio; 40155714Skris for (;;) 40255714Skris { 40355714Skris if (!BIO_should_retry(b)) break; 40455714Skris last=b; 40555714Skris b=b->next_bio; 40655714Skris if (b == NULL) break; 40755714Skris } 40855714Skris if (reason != NULL) *reason=last->retry_reason; 40955714Skris return(last); 41055714Skris } 41155714Skris 41255714Skrisint BIO_get_retry_reason(BIO *bio) 41355714Skris { 41455714Skris return(bio->retry_reason); 41555714Skris } 41655714Skris 41755714SkrisBIO *BIO_find_type(BIO *bio, int type) 41855714Skris { 41955714Skris int mt,mask; 42055714Skris 42168651Skris if(!bio) return NULL; 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 44068651SkrisBIO *BIO_next(BIO *b) 44168651Skris { 44268651Skris if(!b) return NULL; 44368651Skris return b->next_bio; 44468651Skris } 44568651Skris 44655714Skrisvoid BIO_free_all(BIO *bio) 44755714Skris { 44855714Skris BIO *b; 44955714Skris int ref; 45055714Skris 45155714Skris while (bio != NULL) 45255714Skris { 45355714Skris b=bio; 45455714Skris ref=b->references; 45555714Skris bio=bio->next_bio; 45655714Skris BIO_free(b); 45755714Skris /* Since ref count > 1, don't free anyone else. */ 45855714Skris if (ref > 1) break; 45955714Skris } 46055714Skris } 46155714Skris 46255714SkrisBIO *BIO_dup_chain(BIO *in) 46355714Skris { 46455714Skris BIO *ret=NULL,*eoc=NULL,*bio,*new; 46555714Skris 46655714Skris for (bio=in; bio != NULL; bio=bio->next_bio) 46755714Skris { 46855714Skris if ((new=BIO_new(bio->method)) == NULL) goto err; 46955714Skris new->callback=bio->callback; 47055714Skris new->cb_arg=bio->cb_arg; 47155714Skris new->init=bio->init; 47255714Skris new->shutdown=bio->shutdown; 47355714Skris new->flags=bio->flags; 47455714Skris 47555714Skris /* This will let SSL_s_sock() work with stdin/stdout */ 47655714Skris new->num=bio->num; 47755714Skris 47855714Skris if (!BIO_dup_state(bio,(char *)new)) 47955714Skris { 48055714Skris BIO_free(new); 48155714Skris goto err; 48255714Skris } 48355714Skris 48455714Skris /* copy app data */ 48555714Skris if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data)) 48655714Skris goto err; 48755714Skris 48855714Skris if (ret == NULL) 48955714Skris { 49055714Skris eoc=new; 49155714Skris ret=eoc; 49255714Skris } 49355714Skris else 49455714Skris { 49555714Skris BIO_push(eoc,new); 49655714Skris eoc=new; 49755714Skris } 49855714Skris } 49955714Skris return(ret); 50055714Skriserr: 50155714Skris if (ret != NULL) 50255714Skris BIO_free(ret); 50355714Skris return(NULL); 50455714Skris } 50555714Skris 50655714Skrisvoid BIO_copy_next_retry(BIO *b) 50755714Skris { 50855714Skris BIO_set_flags(b,BIO_get_retry_flags(b->next_bio)); 50955714Skris b->retry_reason=b->next_bio->retry_reason; 51055714Skris } 51155714Skris 51259191Skrisint BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 51359191Skris CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 51455714Skris { 51555714Skris bio_meth_num++; 51655714Skris return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth, 51755714Skris argl,argp,new_func,dup_func,free_func)); 51855714Skris } 51955714Skris 52059191Skrisint BIO_set_ex_data(BIO *bio, int idx, void *data) 52155714Skris { 52255714Skris return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data)); 52355714Skris } 52455714Skris 52559191Skrisvoid *BIO_get_ex_data(BIO *bio, int idx) 52655714Skris { 52755714Skris return(CRYPTO_get_ex_data(&(bio->ex_data),idx)); 52855714Skris } 52955714Skris 53059191Skrisunsigned long BIO_number_read(BIO *bio) 53159191Skris{ 53259191Skris if(bio) return bio->num_read; 53359191Skris return 0; 53459191Skris} 53559191Skris 53659191Skrisunsigned long BIO_number_written(BIO *bio) 53759191Skris{ 53859191Skris if(bio) return bio->num_write; 53959191Skris return 0; 54059191Skris} 54168651Skris 54268651SkrisIMPLEMENT_STACK_OF(BIO) 543