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
= {
33 /* TODO: Convert to new style write function */
36 /* TODO: Convert to new style read function */
44 linebuffer_callback_ctrl
,
47 const BIO_METHOD
*BIO_f_linebuffer(void)
49 return (&methods_linebuffer
);
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 */
58 static int linebuffer_new(BIO
*bi
)
60 BIO_LINEBUFFER_CTX
*ctx
;
62 ctx
= OPENSSL_malloc(sizeof(*ctx
));
65 ctx
->obuf
= OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE
);
66 if (ctx
->obuf
== NULL
) {
70 ctx
->obuf_size
= DEFAULT_LINEBUFFER_SIZE
;
74 bi
->ptr
= (char *)ctx
;
79 static int linebuffer_free(BIO
*a
)
81 BIO_LINEBUFFER_CTX
*b
;
85 b
= (BIO_LINEBUFFER_CTX
*)a
->ptr
;
86 OPENSSL_free(b
->obuf
);
94 static int linebuffer_read(BIO
*b
, char *out
, int outl
)
100 if (b
->next_bio
== NULL
)
102 ret
= BIO_read(b
->next_bio
, out
, outl
);
103 BIO_clear_retry_flags(b
);
104 BIO_copy_next_retry(b
);
108 static int linebuffer_write(BIO
*b
, const char *in
, int inl
)
110 int i
, num
= 0, foundnl
;
111 BIO_LINEBUFFER_CTX
*ctx
;
113 if ((in
== NULL
) || (inl
<= 0))
115 ctx
= (BIO_LINEBUFFER_CTX
*)b
->ptr
;
116 if ((ctx
== NULL
) || (b
->next_bio
== NULL
))
119 BIO_clear_retry_flags(b
);
124 for (p
= in
; p
< in
+ inl
&& *p
!= '\n'; p
++) ;
132 * If a NL was found and we already have text in the save buffer,
133 * concatenate them and write
135 while ((foundnl
|| p
- in
> ctx
->obuf_size
- ctx
->obuf_len
)
136 && ctx
->obuf_len
> 0) {
137 int orig_olen
= ctx
->obuf_len
;
139 i
= ctx
->obuf_size
- ctx
->obuf_len
;
142 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, p
- in
);
143 ctx
->obuf_len
+= p
- in
;
148 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, i
);
155 i
= BIO_write(b
->next_bio
, ctx
->obuf
, ctx
->obuf_len
);
157 ctx
->obuf_len
= orig_olen
;
158 BIO_copy_next_retry(b
);
161 return ((num
> 0) ? num
: i
);
165 if (i
< ctx
->obuf_len
)
166 memmove(ctx
->obuf
, ctx
->obuf
+ i
, ctx
->obuf_len
- i
);
171 * Now that the save buffer is emptied, let's write the input buffer
172 * if a NL was found and there is anything to write.
174 if ((foundnl
|| p
- in
> ctx
->obuf_size
) && p
- in
> 0) {
175 i
= BIO_write(b
->next_bio
, in
, p
- in
);
177 BIO_copy_next_retry(b
);
179 return ((num
> 0) ? num
: i
);
188 while (foundnl
&& inl
> 0);
190 * We've written as much as we can. The rest of the input buffer, if
191 * any, is text that doesn't and with a NL and therefore needs to be
192 * saved for the next trip.
195 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, inl
);
196 ctx
->obuf_len
+= inl
;
202 static long linebuffer_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
205 BIO_LINEBUFFER_CTX
*ctx
;
211 ctx
= (BIO_LINEBUFFER_CTX
*)b
->ptr
;
216 if (b
->next_bio
== NULL
)
218 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
221 ret
= (long)ctx
->obuf_len
;
223 case BIO_CTRL_WPENDING
:
224 ret
= (long)ctx
->obuf_len
;
226 if (b
->next_bio
== NULL
)
228 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
231 case BIO_C_SET_BUFF_SIZE
:
234 if ((obs
> DEFAULT_LINEBUFFER_SIZE
) && (obs
!= ctx
->obuf_size
)) {
235 p
= OPENSSL_malloc((int)num
);
239 if (ctx
->obuf
!= p
) {
240 if (ctx
->obuf_len
> obs
) {
243 memcpy(p
, ctx
->obuf
, ctx
->obuf_len
);
244 OPENSSL_free(ctx
->obuf
);
246 ctx
->obuf_size
= obs
;
249 case BIO_C_DO_STATE_MACHINE
:
250 if (b
->next_bio
== NULL
)
252 BIO_clear_retry_flags(b
);
253 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
254 BIO_copy_next_retry(b
);
258 if (b
->next_bio
== NULL
)
260 if (ctx
->obuf_len
<= 0) {
261 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
266 BIO_clear_retry_flags(b
);
267 if (ctx
->obuf_len
> 0) {
268 r
= BIO_write(b
->next_bio
, ctx
->obuf
, ctx
->obuf_len
);
269 BIO_copy_next_retry(b
);
272 if (r
< ctx
->obuf_len
)
273 memmove(ctx
->obuf
, ctx
->obuf
+ r
, ctx
->obuf_len
- r
);
280 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
284 if (!BIO_set_write_buffer_size(dbio
, ctx
->obuf_size
))
288 if (b
->next_bio
== NULL
)
290 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
295 BIOerr(BIO_F_LINEBUFFER_CTRL
, ERR_R_MALLOC_FAILURE
);
299 static long linebuffer_callback_ctrl(BIO
*b
, int cmd
, bio_info_cb
*fp
)
303 if (b
->next_bio
== NULL
)
307 ret
= BIO_callback_ctrl(b
->next_bio
, cmd
, fp
);
313 static int linebuffer_gets(BIO
*b
, char *buf
, int size
)
315 if (b
->next_bio
== NULL
)
317 return (BIO_gets(b
->next_bio
, buf
, size
));
320 static int linebuffer_puts(BIO
*b
, const char *str
)
322 return (linebuffer_write(b
, str
, strlen(str
)));