2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
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
13 #include "internal/cryptlib.h"
14 #include <openssl/evp.h>
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
);
25 /* A 10k maximum should be enough for most purposes */
26 #define DEFAULT_LINEBUFFER_SIZE 1024*10
30 static const BIO_METHOD methods_linebuffer
= {
40 linebuffer_callback_ctrl
,
43 const BIO_METHOD
*BIO_f_linebuffer(void)
45 return (&methods_linebuffer
);
48 typedef struct bio_linebuffer_ctx_struct
{
49 char *obuf
; /* the output char array */
50 int obuf_size
; /* how big is the output buffer */
51 int obuf_len
; /* how many bytes are in it */
54 static int linebuffer_new(BIO
*bi
)
56 BIO_LINEBUFFER_CTX
*ctx
;
58 ctx
= OPENSSL_malloc(sizeof(*ctx
));
61 ctx
->obuf
= OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE
);
62 if (ctx
->obuf
== NULL
) {
66 ctx
->obuf_size
= DEFAULT_LINEBUFFER_SIZE
;
70 bi
->ptr
= (char *)ctx
;
75 static int linebuffer_free(BIO
*a
)
77 BIO_LINEBUFFER_CTX
*b
;
81 b
= (BIO_LINEBUFFER_CTX
*)a
->ptr
;
82 OPENSSL_free(b
->obuf
);
90 static int linebuffer_read(BIO
*b
, char *out
, int outl
)
96 if (b
->next_bio
== NULL
)
98 ret
= BIO_read(b
->next_bio
, out
, outl
);
99 BIO_clear_retry_flags(b
);
100 BIO_copy_next_retry(b
);
104 static int linebuffer_write(BIO
*b
, const char *in
, int inl
)
106 int i
, num
= 0, foundnl
;
107 BIO_LINEBUFFER_CTX
*ctx
;
109 if ((in
== NULL
) || (inl
<= 0))
111 ctx
= (BIO_LINEBUFFER_CTX
*)b
->ptr
;
112 if ((ctx
== NULL
) || (b
->next_bio
== NULL
))
115 BIO_clear_retry_flags(b
);
120 for (p
= in
; p
< in
+ inl
&& *p
!= '\n'; p
++) ;
128 * If a NL was found and we already have text in the save buffer,
129 * concatenate them and write
131 while ((foundnl
|| p
- in
> ctx
->obuf_size
- ctx
->obuf_len
)
132 && ctx
->obuf_len
> 0) {
133 int orig_olen
= ctx
->obuf_len
;
135 i
= ctx
->obuf_size
- ctx
->obuf_len
;
138 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, p
- in
);
139 ctx
->obuf_len
+= p
- in
;
144 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, i
);
151 i
= BIO_write(b
->next_bio
, ctx
->obuf
, ctx
->obuf_len
);
153 ctx
->obuf_len
= orig_olen
;
154 BIO_copy_next_retry(b
);
157 return ((num
> 0) ? num
: i
);
161 if (i
< ctx
->obuf_len
)
162 memmove(ctx
->obuf
, ctx
->obuf
+ i
, ctx
->obuf_len
- i
);
167 * Now that the save buffer is emptied, let's write the input buffer
168 * if a NL was found and there is anything to write.
170 if ((foundnl
|| p
- in
> ctx
->obuf_size
) && p
- in
> 0) {
171 i
= BIO_write(b
->next_bio
, in
, p
- in
);
173 BIO_copy_next_retry(b
);
175 return ((num
> 0) ? num
: i
);
184 while (foundnl
&& inl
> 0);
186 * We've written as much as we can. The rest of the input buffer, if
187 * any, is text that doesn't and with a NL and therefore needs to be
188 * saved for the next trip.
191 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, inl
);
192 ctx
->obuf_len
+= inl
;
198 static long linebuffer_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
201 BIO_LINEBUFFER_CTX
*ctx
;
207 ctx
= (BIO_LINEBUFFER_CTX
*)b
->ptr
;
212 if (b
->next_bio
== NULL
)
214 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
217 ret
= (long)ctx
->obuf_len
;
219 case BIO_CTRL_WPENDING
:
220 ret
= (long)ctx
->obuf_len
;
222 if (b
->next_bio
== NULL
)
224 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
227 case BIO_C_SET_BUFF_SIZE
:
230 if ((obs
> DEFAULT_LINEBUFFER_SIZE
) && (obs
!= ctx
->obuf_size
)) {
231 p
= OPENSSL_malloc((int)num
);
235 if (ctx
->obuf
!= p
) {
236 if (ctx
->obuf_len
> obs
) {
239 memcpy(p
, ctx
->obuf
, ctx
->obuf_len
);
240 OPENSSL_free(ctx
->obuf
);
242 ctx
->obuf_size
= obs
;
245 case BIO_C_DO_STATE_MACHINE
:
246 if (b
->next_bio
== NULL
)
248 BIO_clear_retry_flags(b
);
249 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
250 BIO_copy_next_retry(b
);
254 if (b
->next_bio
== NULL
)
256 if (ctx
->obuf_len
<= 0) {
257 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
262 BIO_clear_retry_flags(b
);
263 if (ctx
->obuf_len
> 0) {
264 r
= BIO_write(b
->next_bio
, ctx
->obuf
, ctx
->obuf_len
);
265 BIO_copy_next_retry(b
);
268 if (r
< ctx
->obuf_len
)
269 memmove(ctx
->obuf
, ctx
->obuf
+ r
, ctx
->obuf_len
- r
);
276 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
280 if (!BIO_set_write_buffer_size(dbio
, ctx
->obuf_size
))
284 if (b
->next_bio
== NULL
)
286 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
291 BIOerr(BIO_F_LINEBUFFER_CTRL
, ERR_R_MALLOC_FAILURE
);
295 static long linebuffer_callback_ctrl(BIO
*b
, int cmd
, bio_info_cb
*fp
)
299 if (b
->next_bio
== NULL
)
303 ret
= BIO_callback_ctrl(b
->next_bio
, cmd
, fp
);
309 static int linebuffer_gets(BIO
*b
, char *buf
, int size
)
311 if (b
->next_bio
== NULL
)
313 return (BIO_gets(b
->next_bio
, buf
, size
));
316 static int linebuffer_puts(BIO
*b
, const char *str
)
318 return (linebuffer_write(b
, str
, strlen(str
)));