2 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (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
12 #include "bio_local.h"
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 if ((ctx
= OPENSSL_malloc(sizeof(*ctx
))) == NULL
) {
63 BIOerr(BIO_F_LINEBUFFER_NEW
, ERR_R_MALLOC_FAILURE
);
66 ctx
->obuf
= OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE
);
67 if (ctx
->obuf
== NULL
) {
68 BIOerr(BIO_F_LINEBUFFER_NEW
, ERR_R_MALLOC_FAILURE
);
72 ctx
->obuf_size
= DEFAULT_LINEBUFFER_SIZE
;
76 bi
->ptr
= (char *)ctx
;
81 static int linebuffer_free(BIO
*a
)
83 BIO_LINEBUFFER_CTX
*b
;
87 b
= (BIO_LINEBUFFER_CTX
*)a
->ptr
;
88 OPENSSL_free(b
->obuf
);
96 static int linebuffer_read(BIO
*b
, char *out
, int outl
)
102 if (b
->next_bio
== NULL
)
104 ret
= BIO_read(b
->next_bio
, out
, outl
);
105 BIO_clear_retry_flags(b
);
106 BIO_copy_next_retry(b
);
110 static int linebuffer_write(BIO
*b
, const char *in
, int inl
)
112 int i
, num
= 0, foundnl
;
113 BIO_LINEBUFFER_CTX
*ctx
;
115 if ((in
== NULL
) || (inl
<= 0))
117 ctx
= (BIO_LINEBUFFER_CTX
*)b
->ptr
;
118 if ((ctx
== NULL
) || (b
->next_bio
== NULL
))
121 BIO_clear_retry_flags(b
);
127 for (p
= in
, c
= '\0'; p
< in
+ inl
&& (c
= *p
) != '\n'; p
++) ;
135 * If a NL was found and we already have text in the save buffer,
136 * concatenate them and write
138 while ((foundnl
|| p
- in
> ctx
->obuf_size
- ctx
->obuf_len
)
139 && ctx
->obuf_len
> 0) {
140 int orig_olen
= ctx
->obuf_len
;
142 i
= ctx
->obuf_size
- ctx
->obuf_len
;
145 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, p
- in
);
146 ctx
->obuf_len
+= p
- in
;
151 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, i
);
158 i
= BIO_write(b
->next_bio
, ctx
->obuf
, ctx
->obuf_len
);
160 ctx
->obuf_len
= orig_olen
;
161 BIO_copy_next_retry(b
);
164 return ((num
> 0) ? num
: i
);
168 if (i
< ctx
->obuf_len
)
169 memmove(ctx
->obuf
, ctx
->obuf
+ i
, ctx
->obuf_len
- i
);
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.
177 if ((foundnl
|| p
- in
> ctx
->obuf_size
) && p
- in
> 0) {
178 i
= BIO_write(b
->next_bio
, in
, p
- in
);
180 BIO_copy_next_retry(b
);
182 return ((num
> 0) ? num
: i
);
191 while (foundnl
&& inl
> 0);
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.
198 memcpy(&(ctx
->obuf
[ctx
->obuf_len
]), in
, inl
);
199 ctx
->obuf_len
+= inl
;
205 static long linebuffer_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
208 BIO_LINEBUFFER_CTX
*ctx
;
214 ctx
= (BIO_LINEBUFFER_CTX
*)b
->ptr
;
219 if (b
->next_bio
== NULL
)
221 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
224 ret
= (long)ctx
->obuf_len
;
226 case BIO_CTRL_WPENDING
:
227 ret
= (long)ctx
->obuf_len
;
229 if (b
->next_bio
== NULL
)
231 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
234 case BIO_C_SET_BUFF_SIZE
:
237 if ((obs
> DEFAULT_LINEBUFFER_SIZE
) && (obs
!= ctx
->obuf_size
)) {
238 p
= OPENSSL_malloc((int)num
);
242 if (ctx
->obuf
!= p
) {
243 if (ctx
->obuf_len
> obs
) {
246 memcpy(p
, ctx
->obuf
, ctx
->obuf_len
);
247 OPENSSL_free(ctx
->obuf
);
249 ctx
->obuf_size
= obs
;
252 case BIO_C_DO_STATE_MACHINE
:
253 if (b
->next_bio
== NULL
)
255 BIO_clear_retry_flags(b
);
256 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
257 BIO_copy_next_retry(b
);
261 if (b
->next_bio
== NULL
)
263 if (ctx
->obuf_len
<= 0) {
264 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
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
);
275 if (r
< ctx
->obuf_len
)
276 memmove(ctx
->obuf
, ctx
->obuf
+ r
, ctx
->obuf_len
- r
);
283 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
287 if (!BIO_set_write_buffer_size(dbio
, ctx
->obuf_size
))
291 if (b
->next_bio
== NULL
)
293 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
298 BIOerr(BIO_F_LINEBUFFER_CTRL
, ERR_R_MALLOC_FAILURE
);
302 static long linebuffer_callback_ctrl(BIO
*b
, int cmd
, BIO_info_cb
*fp
)
306 if (b
->next_bio
== NULL
)
310 ret
= BIO_callback_ctrl(b
->next_bio
, cmd
, fp
);
316 static int linebuffer_gets(BIO
*b
, char *buf
, int size
)
318 if (b
->next_bio
== NULL
)
320 return BIO_gets(b
->next_bio
, buf
, size
);
323 static int linebuffer_puts(BIO
*b
, const char *str
)
325 return linebuffer_write(b
, str
, strlen(str
));