os/ossrv/ssl/libcrypto/src/crypto/bio/bf_lbuf.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* crypto/bio/bf_buff.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 "cryptlib.h"
    62 #include <openssl/bio.h>
    63 #include <openssl/evp.h>
    64 
    65 static int linebuffer_write(BIO *h, const char *buf,int num);
    66 static int linebuffer_read(BIO *h, char *buf, int size);
    67 static int linebuffer_puts(BIO *h, const char *str);
    68 static int linebuffer_gets(BIO *h, char *str, int size);
    69 static long linebuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
    70 static int linebuffer_new(BIO *h);
    71 static int linebuffer_free(BIO *data);
    72 static long linebuffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
    73 
    74 /* A 10k maximum should be enough for most purposes */
    75 #define DEFAULT_LINEBUFFER_SIZE	1024*10
    76 
    77 /* #define DEBUG */
    78 
    79 static BIO_METHOD methods_linebuffer=
    80 	{
    81 	BIO_TYPE_LINEBUFFER,
    82 	"linebuffer",
    83 	linebuffer_write,
    84 	linebuffer_read,
    85 	linebuffer_puts,
    86 	linebuffer_gets,
    87 	linebuffer_ctrl,
    88 	linebuffer_new,
    89 	linebuffer_free,
    90 	linebuffer_callback_ctrl,
    91 	};
    92 
    93 BIO_METHOD *BIO_f_linebuffer(void)
    94 	{
    95 	return(&methods_linebuffer);
    96 	}
    97 
    98 typedef struct bio_linebuffer_ctx_struct
    99 	{
   100 	char *obuf;		/* the output char array */
   101 	int obuf_size;		/* how big is the output buffer */
   102 	int obuf_len;		/* how many bytes are in it */
   103 	} BIO_LINEBUFFER_CTX;
   104 
   105 static int linebuffer_new(BIO *bi)
   106 	{
   107 	BIO_LINEBUFFER_CTX *ctx;
   108 
   109 	ctx=(BIO_LINEBUFFER_CTX *)OPENSSL_malloc(sizeof(BIO_LINEBUFFER_CTX));
   110 	if (ctx == NULL) return(0);
   111 	ctx->obuf=(char *)OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE);
   112 	if (ctx->obuf == NULL) { OPENSSL_free(ctx); return(0); }
   113 	ctx->obuf_size=DEFAULT_LINEBUFFER_SIZE;
   114 	ctx->obuf_len=0;
   115 
   116 	bi->init=1;
   117 	bi->ptr=(char *)ctx;
   118 	bi->flags=0;
   119 	return(1);
   120 	}
   121 
   122 static int linebuffer_free(BIO *a)
   123 	{
   124 	BIO_LINEBUFFER_CTX *b;
   125 
   126 	if (a == NULL) return(0);
   127 	b=(BIO_LINEBUFFER_CTX *)a->ptr;
   128 	if (b->obuf != NULL) OPENSSL_free(b->obuf);
   129 	OPENSSL_free(a->ptr);
   130 	a->ptr=NULL;
   131 	a->init=0;
   132 	a->flags=0;
   133 	return(1);
   134 	}
   135 	
   136 static int linebuffer_read(BIO *b, char *out, int outl)
   137 	{
   138 	int ret=0;
   139  
   140 	if (out == NULL) return(0);
   141 	if (b->next_bio == NULL) return(0);
   142 	ret=BIO_read(b->next_bio,out,outl);
   143 	BIO_clear_retry_flags(b);
   144 	BIO_copy_next_retry(b);
   145 	return(ret);
   146 	}
   147 
   148 static int linebuffer_write(BIO *b, const char *in, int inl)
   149 	{
   150 	int i,num=0,foundnl;
   151 	BIO_LINEBUFFER_CTX *ctx;
   152 
   153 	if ((in == NULL) || (inl <= 0)) return(0);
   154 	ctx=(BIO_LINEBUFFER_CTX *)b->ptr;
   155 	if ((ctx == NULL) || (b->next_bio == NULL)) return(0);
   156 
   157 	BIO_clear_retry_flags(b);
   158 
   159 	do
   160 		{
   161 		const char *p;
   162 
   163 		for(p = in; p < in + inl && *p != '\n'; p++)
   164 			;
   165 		if (*p == '\n')
   166 			{
   167 			p++;
   168 			foundnl = 1;
   169 			}
   170 		else
   171 			foundnl = 0;
   172 
   173 		/* If a NL was found and we already have text in the save
   174 		   buffer, concatenate them and write */
   175 		while ((foundnl || p - in > ctx->obuf_size - ctx->obuf_len)
   176 			&& ctx->obuf_len > 0)
   177 			{
   178 			int orig_olen = ctx->obuf_len;
   179 			
   180 			i = ctx->obuf_size - ctx->obuf_len;
   181 			if (p - in > 0)
   182 				{
   183 				if (i >= p - in)
   184 					{
   185 					memcpy(&(ctx->obuf[ctx->obuf_len]),
   186 						in,p - in);
   187 					ctx->obuf_len += p - in;
   188 					inl -= p - in;
   189 					num += p - in;
   190 					in = p;
   191 					}
   192 				else
   193 					{
   194 					memcpy(&(ctx->obuf[ctx->obuf_len]),
   195 						in,i);
   196 					ctx->obuf_len += i;
   197 					inl -= i;
   198 					in += i;
   199 					num += i;
   200 					}
   201 				}
   202 
   203 #if 0
   204 BIO_write(b->next_bio, "<*<", 3);
   205 #endif
   206 			i=BIO_write(b->next_bio,
   207 				ctx->obuf, ctx->obuf_len);
   208 			if (i <= 0)
   209 				{
   210 				ctx->obuf_len = orig_olen;
   211 				BIO_copy_next_retry(b);
   212 
   213 #if 0
   214 BIO_write(b->next_bio, ">*>", 3);
   215 #endif
   216 				if (i < 0) return((num > 0)?num:i);
   217 				if (i == 0) return(num);
   218 				}
   219 #if 0
   220 BIO_write(b->next_bio, ">*>", 3);
   221 #endif
   222 			if (i < ctx->obuf_len)
   223 				memmove(ctx->obuf, ctx->obuf + i,
   224 					ctx->obuf_len - i);
   225 			ctx->obuf_len-=i;
   226 			}
   227 
   228 		/* Now that the save buffer is emptied, let's write the input
   229 		   buffer if a NL was found and there is anything to write. */
   230 		if ((foundnl || p - in > ctx->obuf_size) && p - in > 0)
   231 			{
   232 #if 0
   233 BIO_write(b->next_bio, "<*<", 3);
   234 #endif
   235 			i=BIO_write(b->next_bio,in,p - in);
   236 			if (i <= 0)
   237 				{
   238 				BIO_copy_next_retry(b);
   239 #if 0
   240 BIO_write(b->next_bio, ">*>", 3);
   241 #endif
   242 				if (i < 0) return((num > 0)?num:i);
   243 				if (i == 0) return(num);
   244 				}
   245 #if 0
   246 BIO_write(b->next_bio, ">*>", 3);
   247 #endif
   248 			num+=i;
   249 			in+=i;
   250 			inl-=i;
   251 			}
   252 		}
   253 	while(foundnl && inl > 0);
   254 	/* We've written as much as we can.  The rest of the input buffer, if
   255 	   any, is text that doesn't and with a NL and therefore needs to be
   256 	   saved for the next trip. */
   257 	if (inl > 0)
   258 		{
   259 		memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl);
   260 		ctx->obuf_len += inl;
   261 		num += inl;
   262 		}
   263 	return num;
   264 	}
   265 
   266 static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr)
   267 	{
   268 	BIO *dbio;
   269 	BIO_LINEBUFFER_CTX *ctx;
   270 	long ret=1;
   271 	char *p;
   272 	int r;
   273 	int obs;
   274 
   275 	ctx=(BIO_LINEBUFFER_CTX *)b->ptr;
   276 
   277 	switch (cmd)
   278 		{
   279 	case BIO_CTRL_RESET:
   280 		ctx->obuf_len=0;
   281 		if (b->next_bio == NULL) return(0);
   282 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
   283 		break;
   284 	case BIO_CTRL_INFO:
   285 		ret=(long)ctx->obuf_len;
   286 		break;
   287 	case BIO_CTRL_WPENDING:
   288 		ret=(long)ctx->obuf_len;
   289 		if (ret == 0)
   290 			{
   291 			if (b->next_bio == NULL) return(0);
   292 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
   293 			}
   294 		break;
   295 	case BIO_C_SET_BUFF_SIZE:
   296 		obs=(int)num;
   297 		p=ctx->obuf;
   298 		if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size))
   299 			{
   300 			p=(char *)OPENSSL_malloc((int)num);
   301 			if (p == NULL)
   302 				goto malloc_error;
   303 			}
   304 		if (ctx->obuf != p)
   305 			{
   306 			if (ctx->obuf_len > obs)
   307 				{
   308 				ctx->obuf_len = obs;
   309 				}
   310 			memcpy(p, ctx->obuf, ctx->obuf_len);
   311 			OPENSSL_free(ctx->obuf);
   312 			ctx->obuf=p;
   313 			ctx->obuf_size=obs;
   314 			}
   315 		break;
   316 	case BIO_C_DO_STATE_MACHINE:
   317 		if (b->next_bio == NULL) return(0);
   318 		BIO_clear_retry_flags(b);
   319 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
   320 		BIO_copy_next_retry(b);
   321 		break;
   322 
   323 	case BIO_CTRL_FLUSH:
   324 		if (b->next_bio == NULL) return(0);
   325 		if (ctx->obuf_len <= 0)
   326 			{
   327 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
   328 			break;
   329 			}
   330 
   331 		for (;;)
   332 			{
   333 			BIO_clear_retry_flags(b);
   334 			if (ctx->obuf_len > 0)
   335 				{
   336 				r=BIO_write(b->next_bio,
   337 					ctx->obuf, ctx->obuf_len);
   338 #if 0
   339 fprintf(stderr,"FLUSH %3d -> %3d\n",ctx->obuf_len,r);
   340 #endif
   341 				BIO_copy_next_retry(b);
   342 				if (r <= 0) return((long)r);
   343 				if (r < ctx->obuf_len)
   344 					memmove(ctx->obuf, ctx->obuf + r,
   345 						ctx->obuf_len - r);
   346 				ctx->obuf_len-=r;
   347 				}
   348 			else
   349 				{
   350 				ctx->obuf_len=0;
   351 				ret=1;
   352 				break;
   353 				}
   354 			}
   355 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
   356 		break;
   357 	case BIO_CTRL_DUP:
   358 		dbio=(BIO *)ptr;
   359 		if (	!BIO_set_write_buffer_size(dbio,ctx->obuf_size))
   360 			ret=0;
   361 		break;
   362 	default:
   363 		if (b->next_bio == NULL) return(0);
   364 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
   365 		break;
   366 		}
   367 	return(ret);
   368 malloc_error:
   369 	BIOerr(BIO_F_LINEBUFFER_CTRL,ERR_R_MALLOC_FAILURE);
   370 	return(0);
   371 	}
   372 
   373 static long linebuffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
   374 	{
   375 	long ret=1;
   376 
   377 	if (b->next_bio == NULL) return(0);
   378 	switch (cmd)
   379 		{
   380 	default:
   381 		ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
   382 		break;
   383 		}
   384 	return(ret);
   385 	}
   386 
   387 static int linebuffer_gets(BIO *b, char *buf, int size)
   388 	{
   389 	if (b->next_bio == NULL) return(0);
   390 	return(BIO_gets(b->next_bio,buf,size));
   391 	}
   392 
   393 static int linebuffer_puts(BIO *b, const char *str)
   394 	{
   395 	return(linebuffer_write(b,str,strlen(str)));
   396 	}
   397