1 /* 2 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <errno.h> 12 #include "bio_local.h" 13 #include "internal/cryptlib.h" 14 #include <openssl/evp.h> 15 16 static int linebuffer_write(BIO *h, const char *buf, int num); 17 static int linebuffer_read(BIO *h, char *buf, int size); 18 static int linebuffer_puts(BIO *h, const char *str); 19 static int linebuffer_gets(BIO *h, char *str, int size); 20 static long linebuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); 21 static int linebuffer_new(BIO *h); 22 static int linebuffer_free(BIO *data); 23 static long linebuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); 24 25 /* A 10k maximum should be enough for most purposes */ 26 #define DEFAULT_LINEBUFFER_SIZE 1024*10 27 28 /* #define DEBUG */ 29 30 static const BIO_METHOD methods_linebuffer = { 31 BIO_TYPE_LINEBUFFER, 32 "linebuffer", 33 /* TODO: Convert to new style write function */ 34 bwrite_conv, 35 linebuffer_write, 36 /* TODO: Convert to new style read function */ 37 bread_conv, 38 linebuffer_read, 39 linebuffer_puts, 40 linebuffer_gets, 41 linebuffer_ctrl, 42 linebuffer_new, 43 linebuffer_free, 44 linebuffer_callback_ctrl, 45 }; 46 47 const BIO_METHOD *BIO_f_linebuffer(void) 48 { 49 return &methods_linebuffer; 50 } 51 52 typedef struct bio_linebuffer_ctx_struct { 53 char *obuf; /* the output char array */ 54 int obuf_size; /* how big is the output buffer */ 55 int obuf_len; /* how many bytes are in it */ 56 } BIO_LINEBUFFER_CTX; 57 58 static int linebuffer_new(BIO *bi) 59 { 60 BIO_LINEBUFFER_CTX *ctx; 61 62 if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { 63 BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); 64 return 0; 65 } 66 ctx->obuf = OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE); 67 if (ctx->obuf == NULL) { 68 BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); 69 OPENSSL_free(ctx); 70 return 0; 71 } 72 ctx->obuf_size = DEFAULT_LINEBUFFER_SIZE; 73 ctx->obuf_len = 0; 74 75 bi->init = 1; 76 bi->ptr = (char *)ctx; 77 bi->flags = 0; 78 return 1; 79 } 80 81 static int linebuffer_free(BIO *a) 82 { 83 BIO_LINEBUFFER_CTX *b; 84 85 if (a == NULL) 86 return 0; 87 b = (BIO_LINEBUFFER_CTX *)a->ptr; 88 OPENSSL_free(b->obuf); 89 OPENSSL_free(a->ptr); 90 a->ptr = NULL; 91 a->init = 0; 92 a->flags = 0; 93 return 1; 94 } 95 96 static int linebuffer_read(BIO *b, char *out, int outl) 97 { 98 int ret = 0; 99 100 if (out == NULL) 101 return 0; 102 if (b->next_bio == NULL) 103 return 0; 104 ret = BIO_read(b->next_bio, out, outl); 105 BIO_clear_retry_flags(b); 106 BIO_copy_next_retry(b); 107 return ret; 108 } 109 110 static int linebuffer_write(BIO *b, const char *in, int inl) 111 { 112 int i, num = 0, foundnl; 113 BIO_LINEBUFFER_CTX *ctx; 114 115 if ((in == NULL) || (inl <= 0)) 116 return 0; 117 ctx = (BIO_LINEBUFFER_CTX *)b->ptr; 118 if ((ctx == NULL) || (b->next_bio == NULL)) 119 return 0; 120 121 BIO_clear_retry_flags(b); 122 123 do { 124 const char *p; 125 char c; 126 127 for (p = in, c = '\0'; p < in + inl && (c = *p) != '\n'; p++) ; 128 if (c == '\n') { 129 p++; 130 foundnl = 1; 131 } else 132 foundnl = 0; 133 134 /* 135 * If a NL was found and we already have text in the save buffer, 136 * concatenate them and write 137 */ 138 while ((foundnl || p - in > ctx->obuf_size - ctx->obuf_len) 139 && ctx->obuf_len > 0) { 140 int orig_olen = ctx->obuf_len; 141 142 i = ctx->obuf_size - ctx->obuf_len; 143 if (p - in > 0) { 144 if (i >= p - in) { 145 memcpy(&(ctx->obuf[ctx->obuf_len]), in, p - in); 146 ctx->obuf_len += p - in; 147 inl -= p - in; 148 num += p - in; 149 in = p; 150 } else { 151 memcpy(&(ctx->obuf[ctx->obuf_len]), in, i); 152 ctx->obuf_len += i; 153 inl -= i; 154 in += i; 155 num += i; 156 } 157 } 158 i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); 159 if (i <= 0) { 160 ctx->obuf_len = orig_olen; 161 BIO_copy_next_retry(b); 162 163 if (i < 0) 164 return ((num > 0) ? num : i); 165 if (i == 0) 166 return num; 167 } 168 if (i < ctx->obuf_len) 169 memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i); 170 ctx->obuf_len -= i; 171 } 172 173 /* 174 * Now that the save buffer is emptied, let's write the input buffer 175 * if a NL was found and there is anything to write. 176 */ 177 if ((foundnl || p - in > ctx->obuf_size) && p - in > 0) { 178 i = BIO_write(b->next_bio, in, p - in); 179 if (i <= 0) { 180 BIO_copy_next_retry(b); 181 if (i < 0) 182 return ((num > 0) ? num : i); 183 if (i == 0) 184 return num; 185 } 186 num += i; 187 in += i; 188 inl -= i; 189 } 190 } 191 while (foundnl && inl > 0); 192 /* 193 * We've written as much as we can. The rest of the input buffer, if 194 * any, is text that doesn't and with a NL and therefore needs to be 195 * saved for the next trip. 196 */ 197 if (inl > 0) { 198 memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl); 199 ctx->obuf_len += inl; 200 num += inl; 201 } 202 return num; 203 } 204 205 static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) 206 { 207 BIO *dbio; 208 BIO_LINEBUFFER_CTX *ctx; 209 long ret = 1; 210 char *p; 211 int r; 212 int obs; 213 214 ctx = (BIO_LINEBUFFER_CTX *)b->ptr; 215 216 switch (cmd) { 217 case BIO_CTRL_RESET: 218 ctx->obuf_len = 0; 219 if (b->next_bio == NULL) 220 return 0; 221 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 222 break; 223 case BIO_CTRL_INFO: 224 ret = (long)ctx->obuf_len; 225 break; 226 case BIO_CTRL_WPENDING: 227 ret = (long)ctx->obuf_len; 228 if (ret == 0) { 229 if (b->next_bio == NULL) 230 return 0; 231 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 232 } 233 break; 234 case BIO_C_SET_BUFF_SIZE: 235 obs = (int)num; 236 p = ctx->obuf; 237 if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) { 238 p = OPENSSL_malloc((int)num); 239 if (p == NULL) 240 goto malloc_error; 241 } 242 if (ctx->obuf != p) { 243 if (ctx->obuf_len > obs) { 244 ctx->obuf_len = obs; 245 } 246 memcpy(p, ctx->obuf, ctx->obuf_len); 247 OPENSSL_free(ctx->obuf); 248 ctx->obuf = p; 249 ctx->obuf_size = obs; 250 } 251 break; 252 case BIO_C_DO_STATE_MACHINE: 253 if (b->next_bio == NULL) 254 return 0; 255 BIO_clear_retry_flags(b); 256 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 257 BIO_copy_next_retry(b); 258 break; 259 260 case BIO_CTRL_FLUSH: 261 if (b->next_bio == NULL) 262 return 0; 263 if (ctx->obuf_len <= 0) { 264 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 265 break; 266 } 267 268 for (;;) { 269 BIO_clear_retry_flags(b); 270 if (ctx->obuf_len > 0) { 271 r = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); 272 BIO_copy_next_retry(b); 273 if (r <= 0) 274 return (long)r; 275 if (r < ctx->obuf_len) 276 memmove(ctx->obuf, ctx->obuf + r, ctx->obuf_len - r); 277 ctx->obuf_len -= r; 278 } else { 279 ctx->obuf_len = 0; 280 break; 281 } 282 } 283 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 284 break; 285 case BIO_CTRL_DUP: 286 dbio = (BIO *)ptr; 287 if (!BIO_set_write_buffer_size(dbio, ctx->obuf_size)) 288 ret = 0; 289 break; 290 default: 291 if (b->next_bio == NULL) 292 return 0; 293 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 294 break; 295 } 296 return ret; 297 malloc_error: 298 BIOerr(BIO_F_LINEBUFFER_CTRL, ERR_R_MALLOC_FAILURE); 299 return 0; 300 } 301 302 static long linebuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 303 { 304 long ret = 1; 305 306 if (b->next_bio == NULL) 307 return 0; 308 switch (cmd) { 309 default: 310 ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 311 break; 312 } 313 return ret; 314 } 315 316 static int linebuffer_gets(BIO *b, char *buf, int size) 317 { 318 if (b->next_bio == NULL) 319 return 0; 320 return BIO_gets(b->next_bio, buf, size); 321 } 322 323 static int linebuffer_puts(BIO *b, const char *str) 324 { 325 return linebuffer_write(b, str, strlen(str)); 326 } 327