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 char *
74 buf_getdelim(struct buf *buf, const char *nl, size_t *len)
75 {
76 uint8_t *endl;
77 size_t nlen;
79 *len = 0;
81 nlen = strlen(nl);
82 if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
83 return (NULL);
84 *len = endl + nlen - buf->buf;
85 *endl = '\0';
86 return (buf->buf);
87 }
89 void
90 buf_drain(struct buf *buf, size_t l)
91 {
92 buf->cur = 0;
94 if (l >= buf->len) {
95 buf->len = 0;
96 return;
97 }
99 memmove(buf->buf, buf->buf + l, buf->len - l);
100 buf->len -= l;
103 void
104 buf_drain_line(struct buf *buf, const char *nl)
106 uint8_t *endln;
107 size_t nlen;
109 nlen = strlen(nl);
110 if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
111 return;
112 buf_drain(buf, endln + nlen - buf->buf);
115 void
116 buf_free(struct buf *buf)
118 free(buf->buf);
119 memset(buf, 0, sizeof(*buf));
122 int
123 bufio_init(struct bufio *bio)
125 memset(bio, 0, sizeof(*bio));
126 bio->fd = -1;
128 if (buf_init(&bio->wbuf) == -1)
129 return (-1);
130 if (buf_init(&bio->rbuf) == -1) {
131 buf_free(&bio->wbuf);
132 return (-1);
134 return (0);
137 void
138 bufio_free(struct bufio *bio)
140 if (bio->ctx)
141 tls_free(bio->ctx);
142 bio->ctx = NULL;
144 if (bio->fd != -1)
145 close(bio->fd);
146 bio->fd = -1;
148 buf_free(&bio->rbuf);
149 buf_free(&bio->wbuf);
152 int
153 bufio_close(struct bufio *bio)
155 if (bio->ctx == NULL)
156 return (0);
158 switch (tls_close(bio->ctx)) {
159 case 0:
160 return 0;
161 case TLS_WANT_POLLIN:
162 errno = EAGAIN;
163 bio->wantev = BUFIO_WANT_READ;
164 return (-1);
165 case TLS_WANT_POLLOUT:
166 errno = EAGAIN;
167 bio->wantev = BUFIO_WANT_WRITE;
168 return (-1);
169 default:
170 return (-1);
174 int
175 bufio_reset(struct bufio *bio)
177 bufio_free(bio);
178 return (bufio_init(bio));
181 void
182 bufio_set_fd(struct bufio *bio, int fd)
184 bio->fd = fd;
187 int
188 bufio_starttls(struct bufio *bio, const char *host, int insecure,
189 const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
191 struct tls_config *conf;
193 if ((conf = tls_config_new()) == NULL)
194 return (-1);
196 if (insecure) {
197 tls_config_insecure_noverifycert(conf);
198 tls_config_insecure_noverifyname(conf);
199 tls_config_insecure_noverifytime(conf);
202 if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
203 key, keylen) == -1) {
204 tls_config_free(conf);
205 return (-1);
208 if ((bio->ctx = tls_client()) == NULL) {
209 tls_config_free(conf);
210 return (-1);
213 if (tls_configure(bio->ctx, conf) == -1) {
214 tls_config_free(conf);
215 return (-1);
218 tls_config_free(conf);
220 if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
221 return (-1);
223 return (0);
226 int
227 bufio_ev(struct bufio *bio)
229 short ev;
231 if (bio->wantev)
232 return (bio->wantev);
234 ev = BUFIO_WANT_READ;
235 if (bio->wbuf.len != 0)
236 ev |= BUFIO_WANT_WRITE;
238 return (ev);
241 int
242 bufio_handshake(struct bufio *bio)
244 if (bio->ctx == NULL) {
245 errno = EINVAL;
246 return (-1);
249 switch (tls_handshake(bio->ctx)) {
250 case 0:
251 return (0);
252 case TLS_WANT_POLLIN:
253 errno = EAGAIN;
254 bio->wantev = BUFIO_WANT_READ;
255 return (-1);
256 case TLS_WANT_POLLOUT:
257 errno = EAGAIN;
258 bio->wantev = BUFIO_WANT_WRITE;
259 return (-1);
260 default:
261 return (-1);
265 ssize_t
266 bufio_read(struct bufio *bio)
268 struct buf *rbuf = &bio->rbuf;
269 ssize_t r;
271 assert(rbuf->cap >= rbuf->len);
272 if (rbuf->cap - rbuf->len < BIO_CHUNK) {
273 if (buf_grow(rbuf) == -1)
274 return (-1);
277 if (bio->ctx) {
278 r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
279 rbuf->cap - rbuf->len);
280 switch (r) {
281 case TLS_WANT_POLLIN:
282 errno = EAGAIN;
283 bio->wantev = BUFIO_WANT_READ;
284 return (-1);
285 case TLS_WANT_POLLOUT:
286 errno = EAGAIN;
287 bio->wantev = BUFIO_WANT_WRITE;
288 return (-1);
289 case -1:
290 return (-1);
291 default:
292 bio->wantev = 0;
293 rbuf->len += r;
294 return (r);
298 r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
299 if (r == -1)
300 return (-1);
301 rbuf->len += r;
302 return (r);
305 size_t
306 bufio_drain(struct bufio *bio, void *d, size_t len)
308 struct buf *rbuf = &bio->rbuf;
310 if (len > rbuf->len)
311 len = rbuf->len;
312 memcpy(d, rbuf->buf, len);
313 buf_drain(rbuf, len);
314 return (len);
317 ssize_t
318 bufio_write(struct bufio *bio)
320 struct buf *wbuf = &bio->wbuf;
321 ssize_t w;
323 if (bio->ctx) {
324 switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
325 case TLS_WANT_POLLIN:
326 errno = EAGAIN;
327 bio->wantev = BUFIO_WANT_READ;
328 return (-1);
329 case TLS_WANT_POLLOUT:
330 errno = EAGAIN;
331 bio->wantev = BUFIO_WANT_WRITE;
332 return (-1);
333 case -1:
334 return (-1);
335 default:
336 bio->wantev = 0;
337 buf_drain(wbuf, w);
338 return (w);
342 w = write(bio->fd, wbuf->buf, wbuf->len);
343 if (w == -1)
344 return (-1);
345 buf_drain(wbuf, w);
346 return (w);
349 int
350 bufio_compose(struct bufio *bio, const void *d, size_t len)
352 struct buf *wbuf = &bio->wbuf;
354 while (wbuf->cap - wbuf->len < len) {
355 if (buf_grow(wbuf) == -1)
356 return (-1);
359 memcpy(wbuf->buf + wbuf->len, d, len);
360 wbuf->len += len;
361 return (0);
364 int
365 bufio_compose_str(struct bufio *bio, const char *str)
367 return (bufio_compose(bio, str, strlen(str)));
370 int
371 bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
373 va_list ap;
374 char *str;
375 int r;
377 va_start(ap, fmt);
378 r = vasprintf(&str, fmt, ap);
379 va_end(ap);
381 if (r == -1)
382 return (-1);
383 r = bufio_compose(bio, str, r);
384 free(str);
385 return (r);
388 void
389 bufio_rewind_cursor(struct bufio *bio)
391 bio->rbuf.cur = 0;
394 int
395 bufio_get_cb(void *d)
397 struct bufio *bio = d;
398 struct buf *rbuf = &bio->rbuf;
400 if (rbuf->cur >= rbuf->len)
401 return (EOF);
402 return (rbuf->buf[rbuf->cur++]);
405 int
406 bufio_peek_cb(void *d)
408 struct bufio *bio = d;
409 struct buf *rbuf = &bio->rbuf;
411 if (rbuf->cur >= rbuf->len)
412 return (EOF);
413 return (rbuf->buf[rbuf->cur]);