os/ossrv/ssl/libcrypto/src/crypto/bio/bio_lib.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 <openssl/crypto.h>
    62 #include "cryptlib.h"
    63 #include <openssl/bio.h>
    64 #include <openssl/stack.h>
    65 
    66 EXPORT_C BIO *BIO_new(BIO_METHOD *method)
    67 	{
    68 	BIO *ret=NULL;
    69 
    70 	ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
    71 	if (ret == NULL)
    72 		{
    73 		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
    74 		return(NULL);
    75 		}
    76 #ifdef SYMBIAN
    77    memset(ret,0,sizeof(BIO));
    78 #endif		
    79 	if (!BIO_set(ret,method))
    80 		{
    81 		OPENSSL_free(ret);
    82 		ret=NULL;
    83 		}
    84 	return(ret);
    85 	}
    86 
    87 EXPORT_C int BIO_set(BIO *bio, BIO_METHOD *method)
    88 	{
    89 	bio->method=method;
    90 	bio->callback=NULL;
    91 	bio->cb_arg=NULL;
    92 	bio->init=0;
    93 	bio->shutdown=1;
    94 	bio->flags=0;
    95 	bio->retry_reason=0;
    96 	bio->num=0;
    97 	bio->ptr=NULL;
    98 	bio->prev_bio=NULL;
    99 	bio->next_bio=NULL;
   100 	bio->references=1;
   101 	bio->num_read=0L;
   102 	bio->num_write=0L;
   103 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
   104 	if (method->create != NULL)
   105 		if (!method->create(bio))
   106 			{
   107 			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
   108 					&bio->ex_data);
   109 			return(0);
   110 			}
   111 	return(1);
   112 	}
   113 
   114 EXPORT_C int BIO_free(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(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
   137 
   138 	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
   139 	ret=a->method->destroy(a);
   140 	OPENSSL_free(a);
   141 	return(1);
   142 	}
   143 
   144 EXPORT_C void BIO_vfree(BIO *a)
   145     { BIO_free(a); }
   146 
   147 EXPORT_C void BIO_clear_flags(BIO *b, int flags)
   148 	{
   149 	b->flags &= ~flags;
   150 	}
   151 
   152 EXPORT_C int	BIO_test_flags(const BIO *b, int flags)
   153 	{
   154 	return (b->flags & flags);
   155 	}
   156 
   157 EXPORT_C void	BIO_set_flags(BIO *b, int flags)
   158 	{
   159 	b->flags |= flags;
   160 	}
   161 
   162 EXPORT_C long (*BIO_get_callback(const BIO *b))(struct bio_st *,int,const char *,int, long,long)
   163 	{
   164 	return b->callback;
   165 	}
   166 
   167 EXPORT_C void BIO_set_callback(BIO *b, long (*cb)(struct bio_st *,int,const char *,int, long,long))
   168 	{
   169 	b->callback = cb;
   170 	}
   171 
   172 EXPORT_C void BIO_set_callback_arg(BIO *b, char *arg)
   173 	{
   174 	b->cb_arg = arg;
   175 	}
   176 
   177 EXPORT_C char * BIO_get_callback_arg(const BIO *b)
   178 	{
   179 	return b->cb_arg;
   180 	}
   181 
   182 EXPORT_C const char * BIO_method_name(const BIO *b)
   183 	{
   184 	return b->method->name;
   185 	}
   186 
   187 EXPORT_C int BIO_method_type(const BIO *b)
   188 	{
   189 	return b->method->type;
   190 	}
   191 EXPORT_C int BIO_read(BIO *b, void *out, int outl)
   192 	{
   193 	int i;
   194 	long (*cb)(BIO *,int,const char *,int,long,long);
   195 
   196 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
   197 		{
   198 		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
   199 		return(-2);
   200 		}
   201 
   202 	cb=b->callback;
   203 	if ((cb != NULL) &&
   204 		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
   205 			return(i);
   206 
   207 	if (!b->init)
   208 		{
   209 		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
   210 		return(-2);
   211 		}
   212 
   213 	i=b->method->bread(b,out,outl);
   214 
   215 	if (i > 0) b->num_read+=(unsigned long)i;
   216 
   217 	if (cb != NULL)
   218 		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
   219 			0L,(long)i);
   220 	return(i);
   221 	}
   222 
   223 EXPORT_C int BIO_write(BIO *b, const void *in, int inl)
   224 	{
   225 	int i;
   226 	long (*cb)(BIO *,int,const char *,int,long,long);
   227 
   228 	if (b == NULL)
   229 		return(0);
   230 
   231 	cb=b->callback;
   232 	if ((b->method == NULL) || (b->method->bwrite == NULL))
   233 		{
   234 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
   235 		return(-2);
   236 		}
   237 
   238 	if ((cb != NULL) &&
   239 		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
   240 			return(i);
   241 
   242 	if (!b->init)
   243 		{
   244 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
   245 		return(-2);
   246 		}
   247 
   248 	i=b->method->bwrite(b,in,inl);
   249 
   250 	if (i > 0) b->num_write+=(unsigned long)i;
   251 
   252 	if (cb != NULL)
   253 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
   254 			0L,(long)i);
   255 	return(i);
   256 	}
   257 
   258 EXPORT_C int BIO_puts(BIO *b, const char *in)
   259 	{
   260 	int i;
   261 	long (*cb)(BIO *,int,const char *,int,long,long);
   262 
   263 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
   264 		{
   265 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
   266 		return(-2);
   267 		}
   268 
   269 	cb=b->callback;
   270 
   271 	if ((cb != NULL) &&
   272 		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
   273 			return(i);
   274 
   275 	if (!b->init)
   276 		{
   277 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
   278 		return(-2);
   279 		}
   280 
   281 	i=b->method->bputs(b,in);
   282 
   283 	if (i > 0) b->num_write+=(unsigned long)i;
   284 
   285 	if (cb != NULL)
   286 		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
   287 			0L,(long)i);
   288 	return(i);
   289 	}
   290 
   291 EXPORT_C int BIO_gets(BIO *b, char *in, int inl)
   292 	{
   293 	int i;
   294 	long (*cb)(BIO *,int,const char *,int,long,long);
   295 
   296 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
   297 		{
   298 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
   299 		return(-2);
   300 		}
   301 
   302 	cb=b->callback;
   303 
   304 	if ((cb != NULL) &&
   305 		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
   306 			return(i);
   307 
   308 	if (!b->init)
   309 		{
   310 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
   311 		return(-2);
   312 		}
   313 
   314 	i=b->method->bgets(b,in,inl);
   315 
   316 	if (cb != NULL)
   317 		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
   318 			0L,(long)i);
   319 	return(i);
   320 	}
   321 
   322 EXPORT_C int BIO_indent(BIO *b,int indent,int max)
   323 	{
   324 	if(indent < 0)
   325 		indent=0;
   326 	if(indent > max)
   327 		indent=max;
   328 	while(indent--)
   329 		if(BIO_puts(b," ") != 1)
   330 			return 0;
   331 	return 1;
   332 	}
   333 
   334 EXPORT_C long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
   335 	{
   336 	int i;
   337 
   338 	i=iarg;
   339 	return(BIO_ctrl(b,cmd,larg,(char *)&i));
   340 	}
   341 
   342 EXPORT_C char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
   343 	{
   344 	char *p=NULL;
   345 
   346 	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
   347 		return(NULL);
   348 	else
   349 		return(p);
   350 	}
   351 
   352 EXPORT_C long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
   353 	{
   354 	long ret;
   355 	long (*cb)(BIO *,int,const char *,int,long,long);
   356 
   357 	if (b == NULL) return(0);
   358 
   359 	if ((b->method == NULL) || (b->method->ctrl == NULL))
   360 		{
   361 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
   362 		return(-2);
   363 		}
   364 
   365 	cb=b->callback;
   366 
   367 	if ((cb != NULL) &&
   368 		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
   369 		return(ret);
   370 
   371 	ret=b->method->ctrl(b,cmd,larg,parg);
   372 
   373 	if (cb != NULL)
   374 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
   375 			larg,ret);
   376 	return(ret);
   377 	}
   378 
   379 EXPORT_C long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
   380 	{
   381 	long ret;
   382 	long (*cb)(BIO *,int,const char *,int,long,long);
   383 
   384 	if (b == NULL) return(0);
   385 
   386 	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
   387 		{
   388 		BIOerr(BIO_F_BIO_CALLBACK_CTRL,BIO_R_UNSUPPORTED_METHOD);
   389 		return(-2);
   390 		}
   391 
   392 	cb=b->callback;
   393 
   394 	if ((cb != NULL) &&
   395 		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
   396 		return(ret);
   397 
   398 	ret=b->method->callback_ctrl(b,cmd,fp);
   399 
   400 	if (cb != NULL)
   401 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
   402 			0,ret);
   403 	return(ret);
   404 	}
   405 
   406 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
   407  * do; but those macros have inappropriate return type, and for interfacing
   408  * from other programming languages, C macros aren't much of a help anyway. */
   409 EXPORT_C size_t BIO_ctrl_pending(BIO *bio)
   410 	{
   411 	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
   412 	}
   413 
   414 EXPORT_C size_t BIO_ctrl_wpending(BIO *bio)
   415 	{
   416 	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
   417 	}
   418 
   419 
   420 /* put the 'bio' on the end of b's list of operators */
   421 EXPORT_C BIO *BIO_push(BIO *b, BIO *bio)
   422 	{
   423 	BIO *lb;
   424 
   425 	if (b == NULL) return(bio);
   426 	lb=b;
   427 	while (lb->next_bio != NULL)
   428 		lb=lb->next_bio;
   429 	lb->next_bio=bio;
   430 	if (bio != NULL)
   431 		bio->prev_bio=lb;
   432 	/* called to do internal processing */
   433 	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
   434 	return(b);
   435 	}
   436 
   437 /* Remove the first and return the rest */
   438 EXPORT_C BIO *BIO_pop(BIO *b)
   439 	{
   440 	BIO *ret;
   441 
   442 	if (b == NULL) return(NULL);
   443 	ret=b->next_bio;
   444 
   445 	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
   446 
   447 	if (b->prev_bio != NULL)
   448 		b->prev_bio->next_bio=b->next_bio;
   449 	if (b->next_bio != NULL)
   450 		b->next_bio->prev_bio=b->prev_bio;
   451 
   452 	b->next_bio=NULL;
   453 	b->prev_bio=NULL;
   454 	return(ret);
   455 	}
   456 
   457 EXPORT_C BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
   458 	{
   459 	BIO *b,*last;
   460 
   461 	b=last=bio;
   462 	for (;;)
   463 		{
   464 		if (!BIO_should_retry(b)) break;
   465 		last=b;
   466 		b=b->next_bio;
   467 		if (b == NULL) break;
   468 		}
   469 	if (reason != NULL) *reason=last->retry_reason;
   470 	return(last);
   471 	}
   472 
   473 EXPORT_C int BIO_get_retry_reason(BIO *bio)
   474 	{
   475 	return(bio->retry_reason);
   476 	}
   477 
   478 EXPORT_C BIO *BIO_find_type(BIO *bio, int type)
   479 	{
   480 	int mt,mask;
   481 
   482 	if(!bio) return NULL;
   483 	mask=type&0xff;
   484 	do	{
   485 		if (bio->method != NULL)
   486 			{
   487 			mt=bio->method->type;
   488 
   489 			if (!mask)
   490 				{
   491 				if (mt & type) return(bio);
   492 				}
   493 			else if (mt == type)
   494 				return(bio);
   495 			}
   496 		bio=bio->next_bio;
   497 		} while (bio != NULL);
   498 	return(NULL);
   499 	}
   500 
   501 EXPORT_C BIO *BIO_next(BIO *b)
   502 	{
   503 	if(!b) return NULL;
   504 	return b->next_bio;
   505 	}
   506 
   507 EXPORT_C void BIO_free_all(BIO *bio)
   508 	{
   509 	BIO *b;
   510 	int ref;
   511 
   512 	while (bio != NULL)
   513 		{
   514 		b=bio;
   515 		ref=b->references;
   516 		bio=bio->next_bio;
   517 		BIO_free(b);
   518 		/* Since ref count > 1, don't free anyone else. */
   519 		if (ref > 1) break;
   520 		}
   521 	}
   522 
   523 EXPORT_C BIO *BIO_dup_chain(BIO *in)
   524 	{
   525 	BIO *ret=NULL,*eoc=NULL,*bio,*new;
   526 
   527 	for (bio=in; bio != NULL; bio=bio->next_bio)
   528 		{
   529 		if ((new=BIO_new(bio->method)) == NULL) goto err;
   530 		new->callback=bio->callback;
   531 		new->cb_arg=bio->cb_arg;
   532 		new->init=bio->init;
   533 		new->shutdown=bio->shutdown;
   534 		new->flags=bio->flags;
   535 
   536 		/* This will let SSL_s_sock() work with stdin/stdout */
   537 		new->num=bio->num;
   538 
   539 		if (!BIO_dup_state(bio,(char *)new))
   540 			{
   541 			BIO_free(new);
   542 			goto err;
   543 			}
   544 
   545 		/* copy app data */
   546 		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data,
   547 					&bio->ex_data))
   548 			goto err;
   549 
   550 		if (ret == NULL)
   551 			{
   552 			eoc=new;
   553 			ret=eoc;
   554 			}
   555 		else
   556 			{
   557 			BIO_push(eoc,new);
   558 			eoc=new;
   559 			}
   560 		}
   561 	return(ret);
   562 err:
   563 	if (ret != NULL)
   564 		BIO_free(ret);
   565 	return(NULL);	
   566 	}
   567 
   568 EXPORT_C void BIO_copy_next_retry(BIO *b)
   569 	{
   570 	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
   571 	b->retry_reason=b->next_bio->retry_reason;
   572 	}
   573 
   574 EXPORT_C int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
   575 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
   576 	{
   577 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
   578 				new_func, dup_func, free_func);
   579 	}
   580 
   581 EXPORT_C int BIO_set_ex_data(BIO *bio, int idx, void *data)
   582 	{
   583 	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
   584 	}
   585 
   586 EXPORT_C void *BIO_get_ex_data(BIO *bio, int idx)
   587 	{
   588 	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
   589 	}
   590 
   591 EXPORT_C unsigned long BIO_number_read(BIO *bio)
   592 {
   593 	if(bio) return bio->num_read;
   594 	return 0;
   595 }
   596 
   597 EXPORT_C unsigned long BIO_number_written(BIO *bio)
   598 {
   599 	if(bio) return bio->num_write;
   600 	return 0;
   601 }
   602 
   603 IMPLEMENT_STACK_OF(BIO)