Blob


1 /*
2 * This is free and unencumbered software released into the public domain.
3 *
4 * Anyone is free to copy, modify, publish, use, compile, sell, or
5 * distribute this software, either in source code form or as a compiled
6 * binary, for any purpose, commercial or non-commercial, and by any
7 * means.
8 *
9 * In jurisdictions that recognize copyright laws, the author or authors
10 * of this software dedicate any and all copyright interest in the
11 * software to the public domain. We make this dedication for the benefit
12 * of the public at large and to the detriment of our heirs and
13 * successors. We intend this dedication to be an overt act of
14 * relinquishment in perpetuity of all present and future rights to this
15 * software under copyright law.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
26 #include "compat.h"
28 #include <assert.h>
29 #include <errno.h>
30 #include <stdarg.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <tls.h>
36 #include <unistd.h>
38 #include "bufio.h"
40 int
41 buf_init(struct buf *buf)
42 {
43 const size_t cap = BIO_CHUNK;
45 memset(buf, 0, sizeof(*buf));
46 if ((buf->buf = malloc(cap)) == NULL)
47 return (-1);
48 buf->cap = cap;
49 return (0);
50 }
52 static int
53 buf_grow(struct buf *buf)
54 {
55 size_t newcap;
56 void *t;
58 newcap = buf->cap + BIO_CHUNK;
59 t = realloc(buf->buf, newcap);
60 if (t == NULL)
61 return (-1);
62 buf->buf = t;
63 buf->cap = newcap;
64 return (0);
65 }
67 int
68 buf_has_line(struct buf *buf, const char *nl)
69 {
70 return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
71 }
73 void
74 buf_drain(struct buf *buf, size_t l)
75 {
76 buf->cur = 0;
78 if (l >= buf->len) {
79 buf->len = 0;
80 return;
81 }
83 memmove(buf->buf, buf->buf + l, buf->len - l);
84 buf->len -= l;
85 }
87 void
88 buf_drain_line(struct buf *buf, const char *nl)
89 {
90 uint8_t *endln;
91 size_t nlen;
93 nlen = strlen(nl);
94 if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
95 return;
96 buf_drain(buf, endln + nlen - buf->buf);
97 }
99 void
100 buf_free(struct buf *buf)
102 free(buf->buf);
103 memset(buf, 0, sizeof(*buf));
106 int
107 bufio_init(struct bufio *bio)
109 memset(bio, 0, sizeof(*bio));
110 bio->fd = -1;
112 if (buf_init(&bio->wbuf) == -1)
113 return (-1);
114 if (buf_init(&bio->rbuf) == -1) {
115 buf_free(&bio->wbuf);
116 return (-1);
118 return (0);
121 void
122 bufio_free(struct bufio *bio)
124 if (bio->ctx)
125 tls_free(bio->ctx);
126 bio->ctx = NULL;
128 if (bio->fd != -1)
129 close(bio->fd);
130 bio->fd = -1;
132 buf_free(&bio->rbuf);
133 buf_free(&bio->wbuf);
136 int
137 bufio_close(struct bufio *bio)
139 if (bio->ctx == NULL)
140 return (0);
142 switch (tls_close(bio->ctx)) {
143 case 0:
144 return 0;
145 case TLS_WANT_POLLIN:
146 errno = EAGAIN;
147 bio->pflags = BUFIO_WANT_READ;
148 return (-1);
149 case TLS_WANT_POLLOUT:
150 errno = EAGAIN;
151 bio->pflags = BUFIO_WANT_WRITE;
152 return (-1);
153 default:
154 return (-1);
158 int
159 bufio_reset(struct bufio *bio)
161 bufio_free(bio);
162 return (bufio_init(bio));
165 void
166 bufio_set_fd(struct bufio *bio, int fd)
168 bio->fd = fd;
171 int
172 bufio_starttls(struct bufio *bio, const char *host, int insecure,
173 const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
175 struct tls_config *conf;
177 if ((conf = tls_config_new()) == NULL)
178 return (-1);
180 if (insecure) {
181 tls_config_insecure_noverifycert(conf);
182 tls_config_insecure_noverifyname(conf);
183 tls_config_insecure_noverifytime(conf);
186 if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
187 key, keylen) == -1) {
188 tls_config_free(conf);
189 return (-1);
192 if ((bio->ctx = tls_client()) == NULL) {
193 tls_config_free(conf);
194 return (-1);
197 if (tls_configure(bio->ctx, conf) == -1) {
198 tls_config_free(conf);
199 return (-1);
202 tls_config_free(conf);
204 if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
205 return (-1);
207 return (0);
210 int
211 bufio_ev(struct bufio *bio)
213 short ev;
215 if (bio->pflags)
216 return (bio->pflags);
218 ev = BUFIO_WANT_READ;
219 if (bio->wbuf.len != 0)
220 ev |= BUFIO_WANT_WRITE;
222 return (ev);
225 int
226 bufio_handshake(struct bufio *bio)
228 if (bio->ctx == NULL) {
229 errno = EINVAL;
230 return (-1);
233 switch (tls_handshake(bio->ctx)) {
234 case 0:
235 return (0);
236 case TLS_WANT_POLLIN:
237 errno = EAGAIN;
238 bio->pflags = BUFIO_WANT_READ;
239 return (-1);
240 case TLS_WANT_POLLOUT:
241 errno = EAGAIN;
242 bio->pflags = BUFIO_WANT_WRITE;
243 return (-1);
244 default:
245 return (-1);
249 ssize_t
250 bufio_read(struct bufio *bio)
252 struct buf *rbuf = &bio->rbuf;
253 ssize_t r;
255 assert(rbuf->cap >= rbuf->len);
256 if (rbuf->cap - rbuf->len < BIO_CHUNK) {
257 if (buf_grow(rbuf) == -1)
258 return (-1);
261 if (bio->ctx) {
262 r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
263 rbuf->cap - rbuf->len);
264 switch (r) {
265 case TLS_WANT_POLLIN:
266 errno = EAGAIN;
267 bio->pflags = BUFIO_WANT_READ;
268 return (-1);
269 case TLS_WANT_POLLOUT:
270 errno = EAGAIN;
271 bio->pflags = BUFIO_WANT_WRITE;
272 return (-1);
273 case -1:
274 return (-1);
275 default:
276 bio->pflags = 0;
277 rbuf->len += r;
278 return (r);
282 r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
283 if (r == -1)
284 return (-1);
285 rbuf->len += r;
286 return (r);
289 size_t
290 bufio_drain(struct bufio *bio, void *d, size_t len)
292 struct buf *rbuf = &bio->rbuf;
294 if (len > rbuf->len)
295 len = rbuf->len;
296 memcpy(d, rbuf->buf, len);
297 buf_drain(rbuf, len);
298 return (len);
301 ssize_t
302 bufio_write(struct bufio *bio)
304 struct buf *wbuf = &bio->wbuf;
305 ssize_t w;
307 if (bio->ctx) {
308 switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
309 case TLS_WANT_POLLIN:
310 errno = EAGAIN;
311 bio->pflags = BUFIO_WANT_READ;
312 return (-1);
313 case TLS_WANT_POLLOUT:
314 errno = EAGAIN;
315 bio->pflags = BUFIO_WANT_WRITE;
316 return (-1);
317 case -1:
318 return (-1);
319 default:
320 bio->pflags = 0;
321 buf_drain(wbuf, w);
322 return (w);
326 w = write(bio->fd, wbuf->buf, wbuf->len);
327 if (w == -1)
328 return (-1);
329 buf_drain(wbuf, w);
330 return (w);
333 int
334 bufio_compose(struct bufio *bio, const void *d, size_t len)
336 struct buf *wbuf = &bio->wbuf;
338 while (wbuf->cap - wbuf->len < len) {
339 if (buf_grow(wbuf) == -1)
340 return (-1);
343 memcpy(wbuf->buf + wbuf->len, d, len);
344 wbuf->len += len;
345 return (0);
348 int
349 bufio_compose_str(struct bufio *bio, const char *str)
351 return (bufio_compose(bio, str, strlen(str)));
354 int
355 bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
357 va_list ap;
358 char *str;
359 int r;
361 va_start(ap, fmt);
362 r = vasprintf(&str, fmt, ap);
363 va_end(ap);
365 if (r == -1)
366 return (-1);
367 r = bufio_compose(bio, str, r);
368 free(str);
369 return (r);
372 void
373 bufio_rewind_cursor(struct bufio *bio)
375 bio->rbuf.cur = 0;
378 int
379 bufio_get_cb(void *d)
381 struct bufio *bio = d;
382 struct buf *rbuf = &bio->rbuf;
384 if (rbuf->cur >= rbuf->len)
385 return (EOF);
386 return (rbuf->buf[rbuf->cur++]);
389 int
390 bufio_peek_cb(void *d)
392 struct bufio *bio = d;
393 struct buf *rbuf = &bio->rbuf;
395 if (rbuf->cur >= rbuf->len)
396 return (EOF);
397 return (rbuf->buf[rbuf->cur]);