1*f5b1c8a1SJohn Marino /* $OpenBSD: bf_buff.c,v 1.22 2015/07/19 01:18:17 beck Exp $ */ 2*f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*f5b1c8a1SJohn Marino * All rights reserved. 4*f5b1c8a1SJohn Marino * 5*f5b1c8a1SJohn Marino * This package is an SSL implementation written 6*f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com). 7*f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL. 8*f5b1c8a1SJohn Marino * 9*f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as 10*f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions 11*f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA, 12*f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms 14*f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*f5b1c8a1SJohn Marino * 16*f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in 17*f5b1c8a1SJohn Marino * the code are not to be removed. 18*f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution 19*f5b1c8a1SJohn Marino * as the author of the parts of the library used. 20*f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or 21*f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package. 22*f5b1c8a1SJohn Marino * 23*f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 24*f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 25*f5b1c8a1SJohn Marino * are met: 26*f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright 27*f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 28*f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 29*f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the 30*f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution. 31*f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software 32*f5b1c8a1SJohn Marino * must display the following acknowledgement: 33*f5b1c8a1SJohn Marino * "This product includes cryptographic software written by 34*f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)" 35*f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library 36*f5b1c8a1SJohn Marino * being used are not cryptographic related :-). 37*f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from 38*f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement: 39*f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*f5b1c8a1SJohn Marino * 41*f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*f5b1c8a1SJohn Marino * SUCH DAMAGE. 52*f5b1c8a1SJohn Marino * 53*f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or 54*f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be 55*f5b1c8a1SJohn Marino * copied and put under another distribution licence 56*f5b1c8a1SJohn Marino * [including the GNU Public Licence.] 57*f5b1c8a1SJohn Marino */ 58*f5b1c8a1SJohn Marino 59*f5b1c8a1SJohn Marino #include <errno.h> 60*f5b1c8a1SJohn Marino #include <stdio.h> 61*f5b1c8a1SJohn Marino #include <string.h> 62*f5b1c8a1SJohn Marino 63*f5b1c8a1SJohn Marino #include <openssl/bio.h> 64*f5b1c8a1SJohn Marino #include <openssl/err.h> 65*f5b1c8a1SJohn Marino 66*f5b1c8a1SJohn Marino static int buffer_write(BIO *h, const char *buf, int num); 67*f5b1c8a1SJohn Marino static int buffer_read(BIO *h, char *buf, int size); 68*f5b1c8a1SJohn Marino static int buffer_puts(BIO *h, const char *str); 69*f5b1c8a1SJohn Marino static int buffer_gets(BIO *h, char *str, int size); 70*f5b1c8a1SJohn Marino static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); 71*f5b1c8a1SJohn Marino static int buffer_new(BIO *h); 72*f5b1c8a1SJohn Marino static int buffer_free(BIO *data); 73*f5b1c8a1SJohn Marino static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); 74*f5b1c8a1SJohn Marino #define DEFAULT_BUFFER_SIZE 4096 75*f5b1c8a1SJohn Marino 76*f5b1c8a1SJohn Marino static BIO_METHOD methods_buffer = { 77*f5b1c8a1SJohn Marino .type = BIO_TYPE_BUFFER, 78*f5b1c8a1SJohn Marino .name = "buffer", 79*f5b1c8a1SJohn Marino .bwrite = buffer_write, 80*f5b1c8a1SJohn Marino .bread = buffer_read, 81*f5b1c8a1SJohn Marino .bputs = buffer_puts, 82*f5b1c8a1SJohn Marino .bgets = buffer_gets, 83*f5b1c8a1SJohn Marino .ctrl = buffer_ctrl, 84*f5b1c8a1SJohn Marino .create = buffer_new, 85*f5b1c8a1SJohn Marino .destroy = buffer_free, 86*f5b1c8a1SJohn Marino .callback_ctrl = buffer_callback_ctrl 87*f5b1c8a1SJohn Marino }; 88*f5b1c8a1SJohn Marino 89*f5b1c8a1SJohn Marino BIO_METHOD * 90*f5b1c8a1SJohn Marino BIO_f_buffer(void) 91*f5b1c8a1SJohn Marino { 92*f5b1c8a1SJohn Marino return (&methods_buffer); 93*f5b1c8a1SJohn Marino } 94*f5b1c8a1SJohn Marino 95*f5b1c8a1SJohn Marino static int 96*f5b1c8a1SJohn Marino buffer_new(BIO *bi) 97*f5b1c8a1SJohn Marino { 98*f5b1c8a1SJohn Marino BIO_F_BUFFER_CTX *ctx; 99*f5b1c8a1SJohn Marino 100*f5b1c8a1SJohn Marino ctx = malloc(sizeof(BIO_F_BUFFER_CTX)); 101*f5b1c8a1SJohn Marino if (ctx == NULL) 102*f5b1c8a1SJohn Marino return (0); 103*f5b1c8a1SJohn Marino ctx->ibuf = malloc(DEFAULT_BUFFER_SIZE); 104*f5b1c8a1SJohn Marino if (ctx->ibuf == NULL) { 105*f5b1c8a1SJohn Marino free(ctx); 106*f5b1c8a1SJohn Marino return (0); 107*f5b1c8a1SJohn Marino } 108*f5b1c8a1SJohn Marino ctx->obuf = malloc(DEFAULT_BUFFER_SIZE); 109*f5b1c8a1SJohn Marino if (ctx->obuf == NULL) { 110*f5b1c8a1SJohn Marino free(ctx->ibuf); 111*f5b1c8a1SJohn Marino free(ctx); 112*f5b1c8a1SJohn Marino return (0); 113*f5b1c8a1SJohn Marino } 114*f5b1c8a1SJohn Marino ctx->ibuf_size = DEFAULT_BUFFER_SIZE; 115*f5b1c8a1SJohn Marino ctx->obuf_size = DEFAULT_BUFFER_SIZE; 116*f5b1c8a1SJohn Marino ctx->ibuf_len = 0; 117*f5b1c8a1SJohn Marino ctx->ibuf_off = 0; 118*f5b1c8a1SJohn Marino ctx->obuf_len = 0; 119*f5b1c8a1SJohn Marino ctx->obuf_off = 0; 120*f5b1c8a1SJohn Marino 121*f5b1c8a1SJohn Marino bi->init = 1; 122*f5b1c8a1SJohn Marino bi->ptr = (char *)ctx; 123*f5b1c8a1SJohn Marino bi->flags = 0; 124*f5b1c8a1SJohn Marino return (1); 125*f5b1c8a1SJohn Marino } 126*f5b1c8a1SJohn Marino 127*f5b1c8a1SJohn Marino static int 128*f5b1c8a1SJohn Marino buffer_free(BIO *a) 129*f5b1c8a1SJohn Marino { 130*f5b1c8a1SJohn Marino BIO_F_BUFFER_CTX *b; 131*f5b1c8a1SJohn Marino 132*f5b1c8a1SJohn Marino if (a == NULL) 133*f5b1c8a1SJohn Marino return (0); 134*f5b1c8a1SJohn Marino b = (BIO_F_BUFFER_CTX *)a->ptr; 135*f5b1c8a1SJohn Marino free(b->ibuf); 136*f5b1c8a1SJohn Marino free(b->obuf); 137*f5b1c8a1SJohn Marino free(a->ptr); 138*f5b1c8a1SJohn Marino a->ptr = NULL; 139*f5b1c8a1SJohn Marino a->init = 0; 140*f5b1c8a1SJohn Marino a->flags = 0; 141*f5b1c8a1SJohn Marino return (1); 142*f5b1c8a1SJohn Marino } 143*f5b1c8a1SJohn Marino 144*f5b1c8a1SJohn Marino static int 145*f5b1c8a1SJohn Marino buffer_read(BIO *b, char *out, int outl) 146*f5b1c8a1SJohn Marino { 147*f5b1c8a1SJohn Marino int i, num = 0; 148*f5b1c8a1SJohn Marino BIO_F_BUFFER_CTX *ctx; 149*f5b1c8a1SJohn Marino 150*f5b1c8a1SJohn Marino if (out == NULL) 151*f5b1c8a1SJohn Marino return (0); 152*f5b1c8a1SJohn Marino ctx = (BIO_F_BUFFER_CTX *)b->ptr; 153*f5b1c8a1SJohn Marino 154*f5b1c8a1SJohn Marino if ((ctx == NULL) || (b->next_bio == NULL)) 155*f5b1c8a1SJohn Marino return (0); 156*f5b1c8a1SJohn Marino num = 0; 157*f5b1c8a1SJohn Marino BIO_clear_retry_flags(b); 158*f5b1c8a1SJohn Marino 159*f5b1c8a1SJohn Marino start: 160*f5b1c8a1SJohn Marino i = ctx->ibuf_len; 161*f5b1c8a1SJohn Marino /* If there is stuff left over, grab it */ 162*f5b1c8a1SJohn Marino if (i != 0) { 163*f5b1c8a1SJohn Marino if (i > outl) 164*f5b1c8a1SJohn Marino i = outl; 165*f5b1c8a1SJohn Marino memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i); 166*f5b1c8a1SJohn Marino ctx->ibuf_off += i; 167*f5b1c8a1SJohn Marino ctx->ibuf_len -= i; 168*f5b1c8a1SJohn Marino num += i; 169*f5b1c8a1SJohn Marino if (outl == i) 170*f5b1c8a1SJohn Marino return (num); 171*f5b1c8a1SJohn Marino outl -= i; 172*f5b1c8a1SJohn Marino out += i; 173*f5b1c8a1SJohn Marino } 174*f5b1c8a1SJohn Marino 175*f5b1c8a1SJohn Marino /* We may have done a partial read. try to do more. 176*f5b1c8a1SJohn Marino * We have nothing in the buffer. 177*f5b1c8a1SJohn Marino * If we get an error and have read some data, just return it 178*f5b1c8a1SJohn Marino * and let them retry to get the error again. 179*f5b1c8a1SJohn Marino * copy direct to parent address space */ 180*f5b1c8a1SJohn Marino if (outl > ctx->ibuf_size) { 181*f5b1c8a1SJohn Marino for (;;) { 182*f5b1c8a1SJohn Marino i = BIO_read(b->next_bio, out, outl); 183*f5b1c8a1SJohn Marino if (i <= 0) { 184*f5b1c8a1SJohn Marino BIO_copy_next_retry(b); 185*f5b1c8a1SJohn Marino if (i < 0) 186*f5b1c8a1SJohn Marino return ((num > 0) ? num : i); 187*f5b1c8a1SJohn Marino if (i == 0) 188*f5b1c8a1SJohn Marino return (num); 189*f5b1c8a1SJohn Marino } 190*f5b1c8a1SJohn Marino num += i; 191*f5b1c8a1SJohn Marino if (outl == i) 192*f5b1c8a1SJohn Marino return (num); 193*f5b1c8a1SJohn Marino out += i; 194*f5b1c8a1SJohn Marino outl -= i; 195*f5b1c8a1SJohn Marino } 196*f5b1c8a1SJohn Marino } 197*f5b1c8a1SJohn Marino /* else */ 198*f5b1c8a1SJohn Marino 199*f5b1c8a1SJohn Marino /* we are going to be doing some buffering */ 200*f5b1c8a1SJohn Marino i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size); 201*f5b1c8a1SJohn Marino if (i <= 0) { 202*f5b1c8a1SJohn Marino BIO_copy_next_retry(b); 203*f5b1c8a1SJohn Marino if (i < 0) 204*f5b1c8a1SJohn Marino return ((num > 0) ? num : i); 205*f5b1c8a1SJohn Marino if (i == 0) 206*f5b1c8a1SJohn Marino return (num); 207*f5b1c8a1SJohn Marino } 208*f5b1c8a1SJohn Marino ctx->ibuf_off = 0; 209*f5b1c8a1SJohn Marino ctx->ibuf_len = i; 210*f5b1c8a1SJohn Marino 211*f5b1c8a1SJohn Marino /* Lets re-read using ourselves :-) */ 212*f5b1c8a1SJohn Marino goto start; 213*f5b1c8a1SJohn Marino } 214*f5b1c8a1SJohn Marino 215*f5b1c8a1SJohn Marino static int 216*f5b1c8a1SJohn Marino buffer_write(BIO *b, const char *in, int inl) 217*f5b1c8a1SJohn Marino { 218*f5b1c8a1SJohn Marino int i, num = 0; 219*f5b1c8a1SJohn Marino BIO_F_BUFFER_CTX *ctx; 220*f5b1c8a1SJohn Marino 221*f5b1c8a1SJohn Marino if ((in == NULL) || (inl <= 0)) 222*f5b1c8a1SJohn Marino return (0); 223*f5b1c8a1SJohn Marino ctx = (BIO_F_BUFFER_CTX *)b->ptr; 224*f5b1c8a1SJohn Marino if ((ctx == NULL) || (b->next_bio == NULL)) 225*f5b1c8a1SJohn Marino return (0); 226*f5b1c8a1SJohn Marino 227*f5b1c8a1SJohn Marino BIO_clear_retry_flags(b); 228*f5b1c8a1SJohn Marino start: 229*f5b1c8a1SJohn Marino i = ctx->obuf_size - (ctx->obuf_len + ctx->obuf_off); 230*f5b1c8a1SJohn Marino /* add to buffer and return */ 231*f5b1c8a1SJohn Marino if (i >= inl) { 232*f5b1c8a1SJohn Marino memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, inl); 233*f5b1c8a1SJohn Marino ctx->obuf_len += inl; 234*f5b1c8a1SJohn Marino return (num + inl); 235*f5b1c8a1SJohn Marino } 236*f5b1c8a1SJohn Marino /* else */ 237*f5b1c8a1SJohn Marino /* stuff already in buffer, so add to it first, then flush */ 238*f5b1c8a1SJohn Marino if (ctx->obuf_len != 0) { 239*f5b1c8a1SJohn Marino if (i > 0) /* lets fill it up if we can */ 240*f5b1c8a1SJohn Marino { 241*f5b1c8a1SJohn Marino memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, i); 242*f5b1c8a1SJohn Marino in += i; 243*f5b1c8a1SJohn Marino inl -= i; 244*f5b1c8a1SJohn Marino num += i; 245*f5b1c8a1SJohn Marino ctx->obuf_len += i; 246*f5b1c8a1SJohn Marino } 247*f5b1c8a1SJohn Marino /* we now have a full buffer needing flushing */ 248*f5b1c8a1SJohn Marino for (;;) { 249*f5b1c8a1SJohn Marino i = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]), 250*f5b1c8a1SJohn Marino ctx->obuf_len); 251*f5b1c8a1SJohn Marino if (i <= 0) { 252*f5b1c8a1SJohn Marino BIO_copy_next_retry(b); 253*f5b1c8a1SJohn Marino 254*f5b1c8a1SJohn Marino if (i < 0) 255*f5b1c8a1SJohn Marino return ((num > 0) ? num : i); 256*f5b1c8a1SJohn Marino if (i == 0) 257*f5b1c8a1SJohn Marino return (num); 258*f5b1c8a1SJohn Marino } 259*f5b1c8a1SJohn Marino ctx->obuf_off += i; 260*f5b1c8a1SJohn Marino ctx->obuf_len -= i; 261*f5b1c8a1SJohn Marino if (ctx->obuf_len == 0) 262*f5b1c8a1SJohn Marino break; 263*f5b1c8a1SJohn Marino } 264*f5b1c8a1SJohn Marino } 265*f5b1c8a1SJohn Marino /* we only get here if the buffer has been flushed and we 266*f5b1c8a1SJohn Marino * still have stuff to write */ 267*f5b1c8a1SJohn Marino ctx->obuf_off = 0; 268*f5b1c8a1SJohn Marino 269*f5b1c8a1SJohn Marino /* we now have inl bytes to write */ 270*f5b1c8a1SJohn Marino while (inl >= ctx->obuf_size) { 271*f5b1c8a1SJohn Marino i = BIO_write(b->next_bio, in, inl); 272*f5b1c8a1SJohn Marino if (i <= 0) { 273*f5b1c8a1SJohn Marino BIO_copy_next_retry(b); 274*f5b1c8a1SJohn Marino if (i < 0) 275*f5b1c8a1SJohn Marino return ((num > 0) ? num : i); 276*f5b1c8a1SJohn Marino if (i == 0) 277*f5b1c8a1SJohn Marino return (num); 278*f5b1c8a1SJohn Marino } 279*f5b1c8a1SJohn Marino num += i; 280*f5b1c8a1SJohn Marino in += i; 281*f5b1c8a1SJohn Marino inl -= i; 282*f5b1c8a1SJohn Marino if (inl == 0) 283*f5b1c8a1SJohn Marino return (num); 284*f5b1c8a1SJohn Marino } 285*f5b1c8a1SJohn Marino 286*f5b1c8a1SJohn Marino /* copy the rest into the buffer since we have only a small 287*f5b1c8a1SJohn Marino * amount left */ 288*f5b1c8a1SJohn Marino goto start; 289*f5b1c8a1SJohn Marino } 290*f5b1c8a1SJohn Marino 291*f5b1c8a1SJohn Marino static long 292*f5b1c8a1SJohn Marino buffer_ctrl(BIO *b, int cmd, long num, void *ptr) 293*f5b1c8a1SJohn Marino { 294*f5b1c8a1SJohn Marino BIO *dbio; 295*f5b1c8a1SJohn Marino BIO_F_BUFFER_CTX *ctx; 296*f5b1c8a1SJohn Marino long ret = 1; 297*f5b1c8a1SJohn Marino char *p1, *p2; 298*f5b1c8a1SJohn Marino int r, i, *ip; 299*f5b1c8a1SJohn Marino int ibs, obs; 300*f5b1c8a1SJohn Marino 301*f5b1c8a1SJohn Marino ctx = (BIO_F_BUFFER_CTX *)b->ptr; 302*f5b1c8a1SJohn Marino 303*f5b1c8a1SJohn Marino switch (cmd) { 304*f5b1c8a1SJohn Marino case BIO_CTRL_RESET: 305*f5b1c8a1SJohn Marino ctx->ibuf_off = 0; 306*f5b1c8a1SJohn Marino ctx->ibuf_len = 0; 307*f5b1c8a1SJohn Marino ctx->obuf_off = 0; 308*f5b1c8a1SJohn Marino ctx->obuf_len = 0; 309*f5b1c8a1SJohn Marino if (b->next_bio == NULL) 310*f5b1c8a1SJohn Marino return (0); 311*f5b1c8a1SJohn Marino ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 312*f5b1c8a1SJohn Marino break; 313*f5b1c8a1SJohn Marino case BIO_CTRL_INFO: 314*f5b1c8a1SJohn Marino ret = (long)ctx->obuf_len; 315*f5b1c8a1SJohn Marino break; 316*f5b1c8a1SJohn Marino case BIO_C_GET_BUFF_NUM_LINES: 317*f5b1c8a1SJohn Marino ret = 0; 318*f5b1c8a1SJohn Marino p1 = ctx->ibuf; 319*f5b1c8a1SJohn Marino for (i = 0; i < ctx->ibuf_len; i++) { 320*f5b1c8a1SJohn Marino if (p1[ctx->ibuf_off + i] == '\n') 321*f5b1c8a1SJohn Marino ret++; 322*f5b1c8a1SJohn Marino } 323*f5b1c8a1SJohn Marino break; 324*f5b1c8a1SJohn Marino case BIO_CTRL_WPENDING: 325*f5b1c8a1SJohn Marino ret = (long)ctx->obuf_len; 326*f5b1c8a1SJohn Marino if (ret == 0) { 327*f5b1c8a1SJohn Marino if (b->next_bio == NULL) 328*f5b1c8a1SJohn Marino return (0); 329*f5b1c8a1SJohn Marino ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 330*f5b1c8a1SJohn Marino } 331*f5b1c8a1SJohn Marino break; 332*f5b1c8a1SJohn Marino case BIO_CTRL_PENDING: 333*f5b1c8a1SJohn Marino ret = (long)ctx->ibuf_len; 334*f5b1c8a1SJohn Marino if (ret == 0) { 335*f5b1c8a1SJohn Marino if (b->next_bio == NULL) 336*f5b1c8a1SJohn Marino return (0); 337*f5b1c8a1SJohn Marino ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 338*f5b1c8a1SJohn Marino } 339*f5b1c8a1SJohn Marino break; 340*f5b1c8a1SJohn Marino case BIO_C_SET_BUFF_READ_DATA: 341*f5b1c8a1SJohn Marino if (num > ctx->ibuf_size) { 342*f5b1c8a1SJohn Marino p1 = malloc(num); 343*f5b1c8a1SJohn Marino if (p1 == NULL) 344*f5b1c8a1SJohn Marino goto malloc_error; 345*f5b1c8a1SJohn Marino free(ctx->ibuf); 346*f5b1c8a1SJohn Marino ctx->ibuf = p1; 347*f5b1c8a1SJohn Marino } 348*f5b1c8a1SJohn Marino ctx->ibuf_off = 0; 349*f5b1c8a1SJohn Marino ctx->ibuf_len = (int)num; 350*f5b1c8a1SJohn Marino memcpy(ctx->ibuf, ptr, num); 351*f5b1c8a1SJohn Marino ret = 1; 352*f5b1c8a1SJohn Marino break; 353*f5b1c8a1SJohn Marino case BIO_C_SET_BUFF_SIZE: 354*f5b1c8a1SJohn Marino if (ptr != NULL) { 355*f5b1c8a1SJohn Marino ip = (int *)ptr; 356*f5b1c8a1SJohn Marino if (*ip == 0) { 357*f5b1c8a1SJohn Marino ibs = (int)num; 358*f5b1c8a1SJohn Marino obs = ctx->obuf_size; 359*f5b1c8a1SJohn Marino } 360*f5b1c8a1SJohn Marino else /* if (*ip == 1) */ 361*f5b1c8a1SJohn Marino { 362*f5b1c8a1SJohn Marino ibs = ctx->ibuf_size; 363*f5b1c8a1SJohn Marino obs = (int)num; 364*f5b1c8a1SJohn Marino } 365*f5b1c8a1SJohn Marino } else { 366*f5b1c8a1SJohn Marino ibs = (int)num; 367*f5b1c8a1SJohn Marino obs = (int)num; 368*f5b1c8a1SJohn Marino } 369*f5b1c8a1SJohn Marino p1 = ctx->ibuf; 370*f5b1c8a1SJohn Marino p2 = ctx->obuf; 371*f5b1c8a1SJohn Marino if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) { 372*f5b1c8a1SJohn Marino p1 = malloc(num); 373*f5b1c8a1SJohn Marino if (p1 == NULL) 374*f5b1c8a1SJohn Marino goto malloc_error; 375*f5b1c8a1SJohn Marino } 376*f5b1c8a1SJohn Marino if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) { 377*f5b1c8a1SJohn Marino p2 = malloc(num); 378*f5b1c8a1SJohn Marino if (p2 == NULL) { 379*f5b1c8a1SJohn Marino if (p1 != ctx->ibuf) 380*f5b1c8a1SJohn Marino free(p1); 381*f5b1c8a1SJohn Marino goto malloc_error; 382*f5b1c8a1SJohn Marino } 383*f5b1c8a1SJohn Marino } 384*f5b1c8a1SJohn Marino if (ctx->ibuf != p1) { 385*f5b1c8a1SJohn Marino free(ctx->ibuf); 386*f5b1c8a1SJohn Marino ctx->ibuf = p1; 387*f5b1c8a1SJohn Marino ctx->ibuf_off = 0; 388*f5b1c8a1SJohn Marino ctx->ibuf_len = 0; 389*f5b1c8a1SJohn Marino ctx->ibuf_size = ibs; 390*f5b1c8a1SJohn Marino } 391*f5b1c8a1SJohn Marino if (ctx->obuf != p2) { 392*f5b1c8a1SJohn Marino free(ctx->obuf); 393*f5b1c8a1SJohn Marino ctx->obuf = p2; 394*f5b1c8a1SJohn Marino ctx->obuf_off = 0; 395*f5b1c8a1SJohn Marino ctx->obuf_len = 0; 396*f5b1c8a1SJohn Marino ctx->obuf_size = obs; 397*f5b1c8a1SJohn Marino } 398*f5b1c8a1SJohn Marino break; 399*f5b1c8a1SJohn Marino case BIO_C_DO_STATE_MACHINE: 400*f5b1c8a1SJohn Marino if (b->next_bio == NULL) 401*f5b1c8a1SJohn Marino return (0); 402*f5b1c8a1SJohn Marino BIO_clear_retry_flags(b); 403*f5b1c8a1SJohn Marino ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 404*f5b1c8a1SJohn Marino BIO_copy_next_retry(b); 405*f5b1c8a1SJohn Marino break; 406*f5b1c8a1SJohn Marino 407*f5b1c8a1SJohn Marino case BIO_CTRL_FLUSH: 408*f5b1c8a1SJohn Marino if (b->next_bio == NULL) 409*f5b1c8a1SJohn Marino return (0); 410*f5b1c8a1SJohn Marino if (ctx->obuf_len <= 0) { 411*f5b1c8a1SJohn Marino ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 412*f5b1c8a1SJohn Marino break; 413*f5b1c8a1SJohn Marino } 414*f5b1c8a1SJohn Marino 415*f5b1c8a1SJohn Marino for (;;) { 416*f5b1c8a1SJohn Marino BIO_clear_retry_flags(b); 417*f5b1c8a1SJohn Marino if (ctx->obuf_len > 0) { 418*f5b1c8a1SJohn Marino r = BIO_write(b->next_bio, 419*f5b1c8a1SJohn Marino &(ctx->obuf[ctx->obuf_off]), 420*f5b1c8a1SJohn Marino ctx->obuf_len); 421*f5b1c8a1SJohn Marino BIO_copy_next_retry(b); 422*f5b1c8a1SJohn Marino if (r <= 0) 423*f5b1c8a1SJohn Marino return ((long)r); 424*f5b1c8a1SJohn Marino ctx->obuf_off += r; 425*f5b1c8a1SJohn Marino ctx->obuf_len -= r; 426*f5b1c8a1SJohn Marino } else { 427*f5b1c8a1SJohn Marino ctx->obuf_len = 0; 428*f5b1c8a1SJohn Marino ctx->obuf_off = 0; 429*f5b1c8a1SJohn Marino break; 430*f5b1c8a1SJohn Marino } 431*f5b1c8a1SJohn Marino } 432*f5b1c8a1SJohn Marino ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 433*f5b1c8a1SJohn Marino break; 434*f5b1c8a1SJohn Marino case BIO_CTRL_DUP: 435*f5b1c8a1SJohn Marino dbio = (BIO *)ptr; 436*f5b1c8a1SJohn Marino if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) || 437*f5b1c8a1SJohn Marino !BIO_set_write_buffer_size(dbio, ctx->obuf_size)) 438*f5b1c8a1SJohn Marino ret = 0; 439*f5b1c8a1SJohn Marino break; 440*f5b1c8a1SJohn Marino default: 441*f5b1c8a1SJohn Marino if (b->next_bio == NULL) 442*f5b1c8a1SJohn Marino return (0); 443*f5b1c8a1SJohn Marino ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 444*f5b1c8a1SJohn Marino break; 445*f5b1c8a1SJohn Marino } 446*f5b1c8a1SJohn Marino return (ret); 447*f5b1c8a1SJohn Marino malloc_error: 448*f5b1c8a1SJohn Marino BIOerr(BIO_F_BUFFER_CTRL, ERR_R_MALLOC_FAILURE); 449*f5b1c8a1SJohn Marino return (0); 450*f5b1c8a1SJohn Marino } 451*f5b1c8a1SJohn Marino 452*f5b1c8a1SJohn Marino static long 453*f5b1c8a1SJohn Marino buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 454*f5b1c8a1SJohn Marino { 455*f5b1c8a1SJohn Marino long ret = 1; 456*f5b1c8a1SJohn Marino 457*f5b1c8a1SJohn Marino if (b->next_bio == NULL) 458*f5b1c8a1SJohn Marino return (0); 459*f5b1c8a1SJohn Marino switch (cmd) { 460*f5b1c8a1SJohn Marino default: 461*f5b1c8a1SJohn Marino ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 462*f5b1c8a1SJohn Marino break; 463*f5b1c8a1SJohn Marino } 464*f5b1c8a1SJohn Marino return (ret); 465*f5b1c8a1SJohn Marino } 466*f5b1c8a1SJohn Marino 467*f5b1c8a1SJohn Marino static int 468*f5b1c8a1SJohn Marino buffer_gets(BIO *b, char *buf, int size) 469*f5b1c8a1SJohn Marino { 470*f5b1c8a1SJohn Marino BIO_F_BUFFER_CTX *ctx; 471*f5b1c8a1SJohn Marino int num = 0, i, flag; 472*f5b1c8a1SJohn Marino char *p; 473*f5b1c8a1SJohn Marino 474*f5b1c8a1SJohn Marino ctx = (BIO_F_BUFFER_CTX *)b->ptr; 475*f5b1c8a1SJohn Marino size--; /* reserve space for a '\0' */ 476*f5b1c8a1SJohn Marino BIO_clear_retry_flags(b); 477*f5b1c8a1SJohn Marino 478*f5b1c8a1SJohn Marino for (;;) { 479*f5b1c8a1SJohn Marino if (ctx->ibuf_len > 0) { 480*f5b1c8a1SJohn Marino p = &(ctx->ibuf[ctx->ibuf_off]); 481*f5b1c8a1SJohn Marino flag = 0; 482*f5b1c8a1SJohn Marino for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) { 483*f5b1c8a1SJohn Marino *(buf++) = p[i]; 484*f5b1c8a1SJohn Marino if (p[i] == '\n') { 485*f5b1c8a1SJohn Marino flag = 1; 486*f5b1c8a1SJohn Marino i++; 487*f5b1c8a1SJohn Marino break; 488*f5b1c8a1SJohn Marino } 489*f5b1c8a1SJohn Marino } 490*f5b1c8a1SJohn Marino num += i; 491*f5b1c8a1SJohn Marino size -= i; 492*f5b1c8a1SJohn Marino ctx->ibuf_len -= i; 493*f5b1c8a1SJohn Marino ctx->ibuf_off += i; 494*f5b1c8a1SJohn Marino if (flag || size == 0) { 495*f5b1c8a1SJohn Marino *buf = '\0'; 496*f5b1c8a1SJohn Marino return (num); 497*f5b1c8a1SJohn Marino } 498*f5b1c8a1SJohn Marino } 499*f5b1c8a1SJohn Marino else /* read another chunk */ 500*f5b1c8a1SJohn Marino { 501*f5b1c8a1SJohn Marino i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size); 502*f5b1c8a1SJohn Marino if (i <= 0) { 503*f5b1c8a1SJohn Marino BIO_copy_next_retry(b); 504*f5b1c8a1SJohn Marino *buf = '\0'; 505*f5b1c8a1SJohn Marino if (i < 0) 506*f5b1c8a1SJohn Marino return ((num > 0) ? num : i); 507*f5b1c8a1SJohn Marino if (i == 0) 508*f5b1c8a1SJohn Marino return (num); 509*f5b1c8a1SJohn Marino } 510*f5b1c8a1SJohn Marino ctx->ibuf_len = i; 511*f5b1c8a1SJohn Marino ctx->ibuf_off = 0; 512*f5b1c8a1SJohn Marino } 513*f5b1c8a1SJohn Marino } 514*f5b1c8a1SJohn Marino } 515*f5b1c8a1SJohn Marino 516*f5b1c8a1SJohn Marino static int 517*f5b1c8a1SJohn Marino buffer_puts(BIO *b, const char *str) 518*f5b1c8a1SJohn Marino { 519*f5b1c8a1SJohn Marino return (buffer_write(b, str, strlen(str))); 520*f5b1c8a1SJohn Marino } 521