1 /* crypto/bio/bss_mem.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 "bio.h" 63 64 #ifndef NOPROTO 65 static int mem_write(BIO *h,char *buf,int num); 66 static int mem_read(BIO *h,char *buf,int size); 67 static int mem_puts(BIO *h,char *str); 68 static int mem_gets(BIO *h,char *str,int size); 69 static long mem_ctrl(BIO *h,int cmd,long arg1,char *arg2); 70 static int mem_new(BIO *h); 71 static int mem_free(BIO *data); 72 #else 73 static int mem_write(); 74 static int mem_read(); 75 static int mem_puts(); 76 static int mem_gets(); 77 static long mem_ctrl(); 78 static int mem_new(); 79 static int mem_free(); 80 #endif 81 82 static BIO_METHOD mem_method= 83 { 84 BIO_TYPE_MEM, 85 "memory buffer", 86 mem_write, 87 mem_read, 88 mem_puts, 89 mem_gets, 90 mem_ctrl, 91 mem_new, 92 mem_free, 93 }; 94 95 BIO_METHOD *BIO_s_mem() 96 { 97 return(&mem_method); 98 } 99 100 static int mem_new(bi) 101 BIO *bi; 102 { 103 BUF_MEM *b; 104 105 if ((b=BUF_MEM_new()) == NULL) 106 return(0); 107 bi->shutdown=1; 108 bi->init=1; 109 bi->num=0; 110 bi->ptr=(char *)b; 111 return(1); 112 } 113 114 static int mem_free(a) 115 BIO *a; 116 { 117 if (a == NULL) return(0); 118 if (a->shutdown) 119 { 120 if ((a->init) && (a->ptr != NULL)) 121 { 122 BUF_MEM_free((BUF_MEM *)a->ptr); 123 a->ptr=NULL; 124 } 125 } 126 return(1); 127 } 128 129 static int mem_read(b,out,outl) 130 BIO *b; 131 char *out; 132 int outl; 133 { 134 int ret= -1; 135 BUF_MEM *bm; 136 int i; 137 char *from,*to; 138 139 bm=(BUF_MEM *)b->ptr; 140 BIO_clear_retry_flags(b); 141 ret=(outl > bm->length)?bm->length:outl; 142 if ((out != NULL) && (ret > 0)) 143 { 144 memcpy(out,bm->data,ret); 145 bm->length-=ret; 146 /* memmove(&(bm->data[0]),&(bm->data[ret]), bm->length); */ 147 from=(char *)&(bm->data[ret]); 148 to=(char *)&(bm->data[0]); 149 for (i=0; i<bm->length; i++) 150 to[i]=from[i]; 151 } 152 else if (bm->length == 0) 153 { 154 BIO_set_retry_read(b); 155 ret= -1; 156 } 157 return(ret); 158 } 159 160 static int mem_write(b,in,inl) 161 BIO *b; 162 char *in; 163 int inl; 164 { 165 int ret= -1; 166 int blen; 167 BUF_MEM *bm; 168 169 bm=(BUF_MEM *)b->ptr; 170 if (in == NULL) 171 { 172 BIOerr(BIO_F_MEM_WRITE,BIO_R_NULL_PARAMETER); 173 goto end; 174 } 175 176 BIO_clear_retry_flags(b); 177 blen=bm->length; 178 if (BUF_MEM_grow(bm,blen+inl) != (blen+inl)) 179 goto end; 180 memcpy(&(bm->data[blen]),in,inl); 181 ret=inl; 182 end: 183 return(ret); 184 } 185 186 static long mem_ctrl(b,cmd,num,ptr) 187 BIO *b; 188 int cmd; 189 long num; 190 char *ptr; 191 { 192 long ret=1; 193 char **pptr; 194 195 BUF_MEM *bm=(BUF_MEM *)b->ptr; 196 197 switch (cmd) 198 { 199 case BIO_CTRL_RESET: 200 if (bm->data != NULL) 201 memset(bm->data,0,bm->max); 202 bm->length=0; 203 break; 204 case BIO_CTRL_EOF: 205 ret=(long)(bm->length == 0); 206 break; 207 case BIO_CTRL_INFO: 208 ret=(long)bm->length; 209 if (ptr != NULL) 210 { 211 pptr=(char **)ptr; 212 *pptr=(char *)&(bm->data[0]); 213 } 214 break; 215 case BIO_C_SET_BUF_MEM: 216 mem_free(b); 217 b->shutdown=(int)num; 218 b->ptr=ptr; 219 break; 220 case BIO_C_GET_BUF_MEM_PTR: 221 if (ptr != NULL) 222 { 223 pptr=(char **)ptr; 224 *pptr=(char *)bm; 225 } 226 break; 227 case BIO_CTRL_GET_CLOSE: 228 ret=(long)b->shutdown; 229 break; 230 case BIO_CTRL_SET_CLOSE: 231 b->shutdown=(int)num; 232 break; 233 234 case BIO_CTRL_WPENDING: 235 ret=0L; 236 break; 237 case BIO_CTRL_PENDING: 238 ret=(long)bm->length; 239 break; 240 case BIO_CTRL_DUP: 241 case BIO_CTRL_FLUSH: 242 ret=1; 243 break; 244 case BIO_CTRL_PUSH: 245 case BIO_CTRL_POP: 246 default: 247 ret=0; 248 break; 249 } 250 return(ret); 251 } 252 253 static int mem_gets(bp,buf,size) 254 BIO *bp; 255 char *buf; 256 int size; 257 { 258 int i,j; 259 int ret= -1; 260 char *p; 261 BUF_MEM *bm=(BUF_MEM *)bp->ptr; 262 263 BIO_clear_retry_flags(bp); 264 j=bm->length; 265 if (j <= 0) return(0); 266 p=bm->data; 267 for (i=0; i<j; i++) 268 { 269 if (p[i] == '\n') break; 270 } 271 if (i == j) 272 { 273 BIO_set_retry_read(bp); 274 /* return(-1); change the semantics 0.6.6a */ 275 } 276 else 277 i++; 278 /* i is the max to copy */ 279 if ((size-1) < i) i=size-1; 280 i=mem_read(bp,buf,i); 281 if (i > 0) buf[i]='\0'; 282 ret=i; 283 return(ret); 284 } 285 286 static int mem_puts(bp,str) 287 BIO *bp; 288 char *str; 289 { 290 int n,ret; 291 292 n=strlen(str); 293 ret=mem_write(bp,str,n); 294 /* memory semantics is that it will always work */ 295 return(ret); 296 } 297 298