2 2403c80c 2024-03-30 thomas * bufio.c was written by Omar Polo <op@omarpolo.com>
4 94a3f4e9 2024-03-30 thomas * This is free and unencumbered software released into the public domain.
6 94a3f4e9 2024-03-30 thomas * Anyone is free to copy, modify, publish, use, compile, sell, or
7 94a3f4e9 2024-03-30 thomas * distribute this software, either in source code form or as a compiled
8 94a3f4e9 2024-03-30 thomas * binary, for any purpose, commercial or non-commercial, and by any
11 94a3f4e9 2024-03-30 thomas * In jurisdictions that recognize copyright laws, the author or authors
12 94a3f4e9 2024-03-30 thomas * of this software dedicate any and all copyright interest in the
13 94a3f4e9 2024-03-30 thomas * software to the public domain. We make this dedication for the benefit
14 94a3f4e9 2024-03-30 thomas * of the public at large and to the detriment of our heirs and
15 94a3f4e9 2024-03-30 thomas * successors. We intend this dedication to be an overt act of
16 94a3f4e9 2024-03-30 thomas * relinquishment in perpetuity of all present and future rights to this
17 94a3f4e9 2024-03-30 thomas * software under copyright law.
19 94a3f4e9 2024-03-30 thomas * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 94a3f4e9 2024-03-30 thomas * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 94a3f4e9 2024-03-30 thomas * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 94a3f4e9 2024-03-30 thomas * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 94a3f4e9 2024-03-30 thomas * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 94a3f4e9 2024-03-30 thomas * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 94a3f4e9 2024-03-30 thomas * OTHER DEALINGS IN THE SOFTWARE.
28 a58e44b0 2024-03-30 thomas #include "got_compat.h"
30 94a3f4e9 2024-03-30 thomas #include <assert.h>
31 94a3f4e9 2024-03-30 thomas #include <errno.h>
32 94a3f4e9 2024-03-30 thomas #include <stdarg.h>
33 94a3f4e9 2024-03-30 thomas #include <stdint.h>
34 94a3f4e9 2024-03-30 thomas #include <stdio.h>
35 94a3f4e9 2024-03-30 thomas #include <stdlib.h>
36 94a3f4e9 2024-03-30 thomas #include <tls.h>
37 a58e44b0 2024-03-30 thomas #include <string.h>
38 94a3f4e9 2024-03-30 thomas #include <unistd.h>
40 94a3f4e9 2024-03-30 thomas #include "bufio.h"
43 94a3f4e9 2024-03-30 thomas buf_init(struct buf *buf)
45 94a3f4e9 2024-03-30 thomas const size_t cap = BIO_CHUNK;
47 94a3f4e9 2024-03-30 thomas memset(buf, 0, sizeof(*buf));
48 94a3f4e9 2024-03-30 thomas if ((buf->buf = malloc(cap)) == NULL)
49 94a3f4e9 2024-03-30 thomas return (-1);
50 94a3f4e9 2024-03-30 thomas buf->cap = cap;
51 94a3f4e9 2024-03-30 thomas return (0);
54 94a3f4e9 2024-03-30 thomas static int
55 94a3f4e9 2024-03-30 thomas buf_grow(struct buf *buf)
57 94a3f4e9 2024-03-30 thomas size_t newcap;
60 94a3f4e9 2024-03-30 thomas newcap = buf->cap + BIO_CHUNK;
61 94a3f4e9 2024-03-30 thomas t = realloc(buf->buf, newcap);
62 94a3f4e9 2024-03-30 thomas if (t == NULL)
63 94a3f4e9 2024-03-30 thomas return (-1);
64 94a3f4e9 2024-03-30 thomas buf->buf = t;
65 94a3f4e9 2024-03-30 thomas buf->cap = newcap;
66 94a3f4e9 2024-03-30 thomas return (0);
70 94a3f4e9 2024-03-30 thomas buf_has_line(struct buf *buf, const char *nl)
72 94a3f4e9 2024-03-30 thomas return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
76 94a3f4e9 2024-03-30 thomas buf_getdelim(struct buf *buf, const char *nl, size_t *len)
78 94a3f4e9 2024-03-30 thomas uint8_t *endl;
79 94a3f4e9 2024-03-30 thomas size_t nlen;
83 94a3f4e9 2024-03-30 thomas nlen = strlen(nl);
84 94a3f4e9 2024-03-30 thomas if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
85 94a3f4e9 2024-03-30 thomas return (NULL);
86 94a3f4e9 2024-03-30 thomas *len = endl + nlen - buf->buf;
87 94a3f4e9 2024-03-30 thomas *endl = '\0';
88 94a3f4e9 2024-03-30 thomas return (buf->buf);
92 94a3f4e9 2024-03-30 thomas buf_drain(struct buf *buf, size_t l)
94 94a3f4e9 2024-03-30 thomas buf->cur = 0;
96 94a3f4e9 2024-03-30 thomas if (l >= buf->len) {
97 94a3f4e9 2024-03-30 thomas buf->len = 0;
101 94a3f4e9 2024-03-30 thomas memmove(buf->buf, buf->buf + l, buf->len - l);
102 94a3f4e9 2024-03-30 thomas buf->len -= l;
106 94a3f4e9 2024-03-30 thomas buf_drain_line(struct buf *buf, const char *nl)
108 94a3f4e9 2024-03-30 thomas uint8_t *endln;
109 94a3f4e9 2024-03-30 thomas size_t nlen;
111 94a3f4e9 2024-03-30 thomas nlen = strlen(nl);
112 94a3f4e9 2024-03-30 thomas if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
114 94a3f4e9 2024-03-30 thomas buf_drain(buf, endln + nlen - buf->buf);
118 94a3f4e9 2024-03-30 thomas buf_free(struct buf *buf)
120 94a3f4e9 2024-03-30 thomas free(buf->buf);
121 94a3f4e9 2024-03-30 thomas memset(buf, 0, sizeof(*buf));
125 94a3f4e9 2024-03-30 thomas bufio_init(struct bufio *bio)
127 94a3f4e9 2024-03-30 thomas memset(bio, 0, sizeof(*bio));
128 94a3f4e9 2024-03-30 thomas bio->fd = -1;
130 94a3f4e9 2024-03-30 thomas if (buf_init(&bio->wbuf) == -1)
131 94a3f4e9 2024-03-30 thomas return (-1);
132 94a3f4e9 2024-03-30 thomas if (buf_init(&bio->rbuf) == -1) {
133 94a3f4e9 2024-03-30 thomas buf_free(&bio->wbuf);
134 94a3f4e9 2024-03-30 thomas return (-1);
136 94a3f4e9 2024-03-30 thomas return (0);
140 94a3f4e9 2024-03-30 thomas bufio_free(struct bufio *bio)
142 94a3f4e9 2024-03-30 thomas if (bio->ctx)
143 94a3f4e9 2024-03-30 thomas tls_free(bio->ctx);
144 94a3f4e9 2024-03-30 thomas bio->ctx = NULL;
146 94a3f4e9 2024-03-30 thomas if (bio->fd != -1)
147 94a3f4e9 2024-03-30 thomas close(bio->fd);
148 94a3f4e9 2024-03-30 thomas bio->fd = -1;
150 94a3f4e9 2024-03-30 thomas buf_free(&bio->rbuf);
151 94a3f4e9 2024-03-30 thomas buf_free(&bio->wbuf);
155 94a3f4e9 2024-03-30 thomas bufio_close(struct bufio *bio)
157 94a3f4e9 2024-03-30 thomas if (bio->ctx == NULL)
158 94a3f4e9 2024-03-30 thomas return (0);
160 94a3f4e9 2024-03-30 thomas switch (tls_close(bio->ctx)) {
162 94a3f4e9 2024-03-30 thomas return 0;
163 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLIN:
164 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
165 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_READ;
166 94a3f4e9 2024-03-30 thomas return (-1);
167 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLOUT:
168 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
169 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_WRITE;
170 94a3f4e9 2024-03-30 thomas return (-1);
172 94a3f4e9 2024-03-30 thomas return (-1);
177 94a3f4e9 2024-03-30 thomas bufio_reset(struct bufio *bio)
179 94a3f4e9 2024-03-30 thomas bufio_free(bio);
180 94a3f4e9 2024-03-30 thomas return (bufio_init(bio));
184 94a3f4e9 2024-03-30 thomas bufio_set_fd(struct bufio *bio, int fd)
186 94a3f4e9 2024-03-30 thomas bio->fd = fd;
190 94a3f4e9 2024-03-30 thomas bufio_starttls(struct bufio *bio, const char *host, int insecure,
191 94a3f4e9 2024-03-30 thomas const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
193 94a3f4e9 2024-03-30 thomas struct tls_config *conf;
195 94a3f4e9 2024-03-30 thomas if ((conf = tls_config_new()) == NULL)
196 94a3f4e9 2024-03-30 thomas return (-1);
198 94a3f4e9 2024-03-30 thomas if (insecure) {
199 94a3f4e9 2024-03-30 thomas tls_config_insecure_noverifycert(conf);
200 94a3f4e9 2024-03-30 thomas tls_config_insecure_noverifyname(conf);
201 94a3f4e9 2024-03-30 thomas tls_config_insecure_noverifytime(conf);
204 94a3f4e9 2024-03-30 thomas if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
205 94a3f4e9 2024-03-30 thomas key, keylen) == -1) {
206 94a3f4e9 2024-03-30 thomas tls_config_free(conf);
207 94a3f4e9 2024-03-30 thomas return (-1);
210 94a3f4e9 2024-03-30 thomas if ((bio->ctx = tls_client()) == NULL) {
211 94a3f4e9 2024-03-30 thomas tls_config_free(conf);
212 94a3f4e9 2024-03-30 thomas return (-1);
215 94a3f4e9 2024-03-30 thomas if (tls_configure(bio->ctx, conf) == -1) {
216 94a3f4e9 2024-03-30 thomas tls_config_free(conf);
217 94a3f4e9 2024-03-30 thomas return (-1);
220 94a3f4e9 2024-03-30 thomas tls_config_free(conf);
222 94a3f4e9 2024-03-30 thomas if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
223 94a3f4e9 2024-03-30 thomas return (-1);
225 94a3f4e9 2024-03-30 thomas return (0);
229 94a3f4e9 2024-03-30 thomas bufio_ev(struct bufio *bio)
231 94a3f4e9 2024-03-30 thomas short ev;
233 94a3f4e9 2024-03-30 thomas if (bio->wantev)
234 94a3f4e9 2024-03-30 thomas return (bio->wantev);
236 94a3f4e9 2024-03-30 thomas ev = BUFIO_WANT_READ;
237 94a3f4e9 2024-03-30 thomas if (bio->wbuf.len != 0)
238 94a3f4e9 2024-03-30 thomas ev |= BUFIO_WANT_WRITE;
240 94a3f4e9 2024-03-30 thomas return (ev);
244 94a3f4e9 2024-03-30 thomas bufio_handshake(struct bufio *bio)
246 94a3f4e9 2024-03-30 thomas if (bio->ctx == NULL) {
247 94a3f4e9 2024-03-30 thomas errno = EINVAL;
248 94a3f4e9 2024-03-30 thomas return (-1);
251 94a3f4e9 2024-03-30 thomas switch (tls_handshake(bio->ctx)) {
253 94a3f4e9 2024-03-30 thomas return (0);
254 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLIN:
255 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
256 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_READ;
257 94a3f4e9 2024-03-30 thomas return (-1);
258 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLOUT:
259 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
260 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_WRITE;
261 94a3f4e9 2024-03-30 thomas return (-1);
263 94a3f4e9 2024-03-30 thomas return (-1);
268 94a3f4e9 2024-03-30 thomas bufio_read(struct bufio *bio)
270 94a3f4e9 2024-03-30 thomas struct buf *rbuf = &bio->rbuf;
271 94a3f4e9 2024-03-30 thomas ssize_t r;
273 94a3f4e9 2024-03-30 thomas assert(rbuf->cap >= rbuf->len);
274 94a3f4e9 2024-03-30 thomas if (rbuf->cap - rbuf->len < BIO_CHUNK) {
275 94a3f4e9 2024-03-30 thomas if (buf_grow(rbuf) == -1)
276 94a3f4e9 2024-03-30 thomas return (-1);
279 94a3f4e9 2024-03-30 thomas if (bio->ctx) {
280 94a3f4e9 2024-03-30 thomas r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
281 94a3f4e9 2024-03-30 thomas rbuf->cap - rbuf->len);
282 94a3f4e9 2024-03-30 thomas switch (r) {
283 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLIN:
284 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
285 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_READ;
286 94a3f4e9 2024-03-30 thomas return (-1);
287 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLOUT:
288 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
289 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_WRITE;
290 94a3f4e9 2024-03-30 thomas return (-1);
292 8ec83e5b 2024-04-25 thomas.ad bio->wantev = 0;
293 8ec83e5b 2024-04-25 thomas.ad errno = 0;
294 94a3f4e9 2024-03-30 thomas return (-1);
296 94a3f4e9 2024-03-30 thomas bio->wantev = 0;
297 94a3f4e9 2024-03-30 thomas rbuf->len += r;
298 94a3f4e9 2024-03-30 thomas return (r);
302 94a3f4e9 2024-03-30 thomas r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
303 94a3f4e9 2024-03-30 thomas if (r == -1)
304 94a3f4e9 2024-03-30 thomas return (-1);
305 94a3f4e9 2024-03-30 thomas rbuf->len += r;
306 94a3f4e9 2024-03-30 thomas return (r);
310 94a3f4e9 2024-03-30 thomas bufio_drain(struct bufio *bio, void *d, size_t len)
312 94a3f4e9 2024-03-30 thomas struct buf *rbuf = &bio->rbuf;
314 94a3f4e9 2024-03-30 thomas if (len > rbuf->len)
315 94a3f4e9 2024-03-30 thomas len = rbuf->len;
316 94a3f4e9 2024-03-30 thomas memcpy(d, rbuf->buf, len);
317 94a3f4e9 2024-03-30 thomas buf_drain(rbuf, len);
318 94a3f4e9 2024-03-30 thomas return (len);
322 94a3f4e9 2024-03-30 thomas bufio_write(struct bufio *bio)
324 94a3f4e9 2024-03-30 thomas struct buf *wbuf = &bio->wbuf;
325 94a3f4e9 2024-03-30 thomas ssize_t w;
327 94a3f4e9 2024-03-30 thomas if (bio->ctx) {
328 94a3f4e9 2024-03-30 thomas switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
329 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLIN:
330 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
331 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_READ;
332 94a3f4e9 2024-03-30 thomas return (-1);
333 94a3f4e9 2024-03-30 thomas case TLS_WANT_POLLOUT:
334 94a3f4e9 2024-03-30 thomas errno = EAGAIN;
335 94a3f4e9 2024-03-30 thomas bio->wantev = BUFIO_WANT_WRITE;
336 94a3f4e9 2024-03-30 thomas return (-1);
338 94a3f4e9 2024-03-30 thomas return (-1);
340 94a3f4e9 2024-03-30 thomas bio->wantev = 0;
341 94a3f4e9 2024-03-30 thomas buf_drain(wbuf, w);
342 94a3f4e9 2024-03-30 thomas return (w);
346 94a3f4e9 2024-03-30 thomas w = write(bio->fd, wbuf->buf, wbuf->len);
347 94a3f4e9 2024-03-30 thomas if (w == -1)
348 94a3f4e9 2024-03-30 thomas return (-1);
349 94a3f4e9 2024-03-30 thomas buf_drain(wbuf, w);
350 94a3f4e9 2024-03-30 thomas return (w);
353 94a3f4e9 2024-03-30 thomas const char *
354 94a3f4e9 2024-03-30 thomas bufio_io_err(struct bufio *bio)
356 94a3f4e9 2024-03-30 thomas if (bio->ctx)
357 94a3f4e9 2024-03-30 thomas return tls_error(bio->ctx);
359 94a3f4e9 2024-03-30 thomas return strerror(errno);
363 94a3f4e9 2024-03-30 thomas bufio_compose(struct bufio *bio, const void *d, size_t len)
365 94a3f4e9 2024-03-30 thomas struct buf *wbuf = &bio->wbuf;
367 94a3f4e9 2024-03-30 thomas while (wbuf->cap - wbuf->len < len) {
368 94a3f4e9 2024-03-30 thomas if (buf_grow(wbuf) == -1)
369 94a3f4e9 2024-03-30 thomas return (-1);
372 94a3f4e9 2024-03-30 thomas memcpy(wbuf->buf + wbuf->len, d, len);
373 94a3f4e9 2024-03-30 thomas wbuf->len += len;
374 94a3f4e9 2024-03-30 thomas return (0);
378 94a3f4e9 2024-03-30 thomas bufio_compose_str(struct bufio *bio, const char *str)
380 94a3f4e9 2024-03-30 thomas return (bufio_compose(bio, str, strlen(str)));
384 94a3f4e9 2024-03-30 thomas bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
386 94a3f4e9 2024-03-30 thomas va_list ap;
387 94a3f4e9 2024-03-30 thomas char *str;
390 94a3f4e9 2024-03-30 thomas va_start(ap, fmt);
391 94a3f4e9 2024-03-30 thomas r = vasprintf(&str, fmt, ap);
392 94a3f4e9 2024-03-30 thomas va_end(ap);
394 94a3f4e9 2024-03-30 thomas if (r == -1)
395 94a3f4e9 2024-03-30 thomas return (-1);
396 94a3f4e9 2024-03-30 thomas r = bufio_compose(bio, str, r);
397 94a3f4e9 2024-03-30 thomas free(str);
398 94a3f4e9 2024-03-30 thomas return (r);
402 94a3f4e9 2024-03-30 thomas bufio_rewind_cursor(struct bufio *bio)
404 94a3f4e9 2024-03-30 thomas bio->rbuf.cur = 0;
408 94a3f4e9 2024-03-30 thomas bufio_get_cb(void *d)
410 94a3f4e9 2024-03-30 thomas struct bufio *bio = d;
411 94a3f4e9 2024-03-30 thomas struct buf *rbuf = &bio->rbuf;
413 94a3f4e9 2024-03-30 thomas if (rbuf->cur >= rbuf->len)
414 94a3f4e9 2024-03-30 thomas return (EOF);
415 94a3f4e9 2024-03-30 thomas return (rbuf->buf[rbuf->cur++]);
419 94a3f4e9 2024-03-30 thomas bufio_peek_cb(void *d)
421 94a3f4e9 2024-03-30 thomas struct bufio *bio = d;
422 94a3f4e9 2024-03-30 thomas struct buf *rbuf = &bio->rbuf;
424 94a3f4e9 2024-03-30 thomas if (rbuf->cur >= rbuf->len)
425 94a3f4e9 2024-03-30 thomas return (EOF);
426 94a3f4e9 2024-03-30 thomas return (rbuf->buf[rbuf->cur]);