2 7a554149 2024-02-18 op * This is free and unencumbered software released into the public domain.
4 7a554149 2024-02-18 op * Anyone is free to copy, modify, publish, use, compile, sell, or
5 7a554149 2024-02-18 op * distribute this software, either in source code form or as a compiled
6 7a554149 2024-02-18 op * binary, for any purpose, commercial or non-commercial, and by any
9 7a554149 2024-02-18 op * In jurisdictions that recognize copyright laws, the author or authors
10 7a554149 2024-02-18 op * of this software dedicate any and all copyright interest in the
11 7a554149 2024-02-18 op * software to the public domain. We make this dedication for the benefit
12 7a554149 2024-02-18 op * of the public at large and to the detriment of our heirs and
13 7a554149 2024-02-18 op * successors. We intend this dedication to be an overt act of
14 7a554149 2024-02-18 op * relinquishment in perpetuity of all present and future rights to this
15 7a554149 2024-02-18 op * software under copyright law.
17 7a554149 2024-02-18 op * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 7a554149 2024-02-18 op * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 7a554149 2024-02-18 op * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 7a554149 2024-02-18 op * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 7a554149 2024-02-18 op * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 7a554149 2024-02-18 op * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 7a554149 2024-02-18 op * OTHER DEALINGS IN THE SOFTWARE.
26 7a554149 2024-02-18 op #include "compat.h"
28 7a554149 2024-02-18 op #include <assert.h>
29 7a554149 2024-02-18 op #include <errno.h>
30 7a554149 2024-02-18 op #include <stdarg.h>
31 7a554149 2024-02-18 op #include <stdint.h>
32 7a554149 2024-02-18 op #include <stdio.h>
33 7a554149 2024-02-18 op #include <stdlib.h>
34 7a554149 2024-02-18 op #include <string.h>
35 7a554149 2024-02-18 op #include <tls.h>
36 7a554149 2024-02-18 op #include <unistd.h>
38 7a554149 2024-02-18 op #include "bufio.h"
41 7a554149 2024-02-18 op buf_init(struct buf *buf)
43 7a554149 2024-02-18 op const size_t cap = BIO_CHUNK;
45 7a554149 2024-02-18 op memset(buf, 0, sizeof(*buf));
46 7a554149 2024-02-18 op if ((buf->buf = malloc(cap)) == NULL)
48 7a554149 2024-02-18 op buf->cap = cap;
53 7a554149 2024-02-18 op buf_grow(struct buf *buf)
55 7a554149 2024-02-18 op size_t newcap;
58 7a554149 2024-02-18 op newcap = buf->cap + BIO_CHUNK;
59 7a554149 2024-02-18 op t = realloc(buf->buf, newcap);
60 7a554149 2024-02-18 op if (t == NULL)
63 7a554149 2024-02-18 op buf->cap = newcap;
68 7a554149 2024-02-18 op buf_has_line(struct buf *buf, const char *nl)
70 7a554149 2024-02-18 op return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
74 98f8e538 2024-03-22 op buf_getdelim(struct buf *buf, const char *nl, size_t *len)
76 98f8e538 2024-03-22 op uint8_t *endl;
81 98f8e538 2024-03-22 op nlen = strlen(nl);
82 98f8e538 2024-03-22 op if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
83 98f8e538 2024-03-22 op return (NULL);
84 98f8e538 2024-03-22 op *len = endl + nlen - buf->buf;
86 98f8e538 2024-03-22 op return (buf->buf);
90 7a554149 2024-02-18 op buf_drain(struct buf *buf, size_t l)
94 7a554149 2024-02-18 op if (l >= buf->len) {
99 7a554149 2024-02-18 op memmove(buf->buf, buf->buf + l, buf->len - l);
100 7a554149 2024-02-18 op buf->len -= l;
104 7a554149 2024-02-18 op buf_drain_line(struct buf *buf, const char *nl)
106 7a554149 2024-02-18 op uint8_t *endln;
109 7a554149 2024-02-18 op nlen = strlen(nl);
110 7a554149 2024-02-18 op if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
112 7a554149 2024-02-18 op buf_drain(buf, endln + nlen - buf->buf);
116 7a554149 2024-02-18 op buf_free(struct buf *buf)
118 7a554149 2024-02-18 op free(buf->buf);
119 7a554149 2024-02-18 op memset(buf, 0, sizeof(*buf));
123 7a554149 2024-02-18 op bufio_init(struct bufio *bio)
125 7a554149 2024-02-18 op memset(bio, 0, sizeof(*bio));
126 7a554149 2024-02-18 op bio->fd = -1;
128 7a554149 2024-02-18 op if (buf_init(&bio->wbuf) == -1)
130 7a554149 2024-02-18 op if (buf_init(&bio->rbuf) == -1) {
131 7a554149 2024-02-18 op buf_free(&bio->wbuf);
138 0d6af421 2024-02-18 op bufio_free(struct bufio *bio)
140 7a554149 2024-02-18 op if (bio->ctx)
141 0d6af421 2024-02-18 op tls_free(bio->ctx);
142 0d6af421 2024-02-18 op bio->ctx = NULL;
144 7a554149 2024-02-18 op if (bio->fd != -1)
145 7a554149 2024-02-18 op close(bio->fd);
146 0d6af421 2024-02-18 op bio->fd = -1;
148 7a554149 2024-02-18 op buf_free(&bio->rbuf);
149 7a554149 2024-02-18 op buf_free(&bio->wbuf);
153 8b00d570 2024-02-18 op bufio_close(struct bufio *bio)
155 8b00d570 2024-02-18 op if (bio->ctx == NULL)
158 8b00d570 2024-02-18 op switch (tls_close(bio->ctx)) {
161 8b00d570 2024-02-18 op case TLS_WANT_POLLIN:
162 ce023433 2024-02-22 op errno = EAGAIN;
163 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
165 8b00d570 2024-02-18 op case TLS_WANT_POLLOUT:
166 8b00d570 2024-02-18 op errno = EAGAIN;
167 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
175 0d6af421 2024-02-18 op bufio_reset(struct bufio *bio)
177 0d6af421 2024-02-18 op bufio_free(bio);
178 7a554149 2024-02-18 op return (bufio_init(bio));
182 7a554149 2024-02-18 op bufio_set_fd(struct bufio *bio, int fd)
184 7a554149 2024-02-18 op bio->fd = fd;
188 9c5586a7 2024-02-18 op bufio_starttls(struct bufio *bio, const char *host, int insecure,
189 9c5586a7 2024-02-18 op const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
191 7a554149 2024-02-18 op struct tls_config *conf;
193 7a554149 2024-02-18 op if ((conf = tls_config_new()) == NULL)
196 7a554149 2024-02-18 op if (insecure) {
197 7a554149 2024-02-18 op tls_config_insecure_noverifycert(conf);
198 7a554149 2024-02-18 op tls_config_insecure_noverifyname(conf);
199 7a554149 2024-02-18 op tls_config_insecure_noverifytime(conf);
202 9c5586a7 2024-02-18 op if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
203 9c5586a7 2024-02-18 op key, keylen) == -1) {
204 9c5586a7 2024-02-18 op tls_config_free(conf);
208 7a554149 2024-02-18 op if ((bio->ctx = tls_client()) == NULL) {
209 7a554149 2024-02-18 op tls_config_free(conf);
213 7a554149 2024-02-18 op if (tls_configure(bio->ctx, conf) == -1) {
214 7a554149 2024-02-18 op tls_config_free(conf);
218 7a554149 2024-02-18 op tls_config_free(conf);
220 7a554149 2024-02-18 op if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
227 e3693ed9 2024-02-18 op bufio_ev(struct bufio *bio)
231 c4d1f652 2024-03-25 op if (bio->wantev)
232 c4d1f652 2024-03-25 op return (bio->wantev);
234 ce023433 2024-02-22 op ev = BUFIO_WANT_READ;
235 7a554149 2024-02-18 op if (bio->wbuf.len != 0)
236 ce023433 2024-02-22 op ev |= BUFIO_WANT_WRITE;
242 0e0994b2 2024-02-18 op bufio_handshake(struct bufio *bio)
244 0e0994b2 2024-02-18 op if (bio->ctx == NULL) {
245 0e0994b2 2024-02-18 op errno = EINVAL;
249 0e0994b2 2024-02-18 op switch (tls_handshake(bio->ctx)) {
252 0e0994b2 2024-02-18 op case TLS_WANT_POLLIN:
253 ce023433 2024-02-22 op errno = EAGAIN;
254 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
256 0e0994b2 2024-02-18 op case TLS_WANT_POLLOUT:
257 0e0994b2 2024-02-18 op errno = EAGAIN;
258 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
266 7a554149 2024-02-18 op bufio_read(struct bufio *bio)
268 7a554149 2024-02-18 op struct buf *rbuf = &bio->rbuf;
271 7a554149 2024-02-18 op assert(rbuf->cap >= rbuf->len);
272 7a554149 2024-02-18 op if (rbuf->cap - rbuf->len < BIO_CHUNK) {
273 7a554149 2024-02-18 op if (buf_grow(rbuf) == -1)
277 7a554149 2024-02-18 op if (bio->ctx) {
278 7a554149 2024-02-18 op r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
279 e634cfa6 2024-02-18 op rbuf->cap - rbuf->len);
281 7a554149 2024-02-18 op case TLS_WANT_POLLIN:
282 ce023433 2024-02-22 op errno = EAGAIN;
283 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
285 7a554149 2024-02-18 op case TLS_WANT_POLLOUT:
286 7a554149 2024-02-18 op errno = EAGAIN;
287 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
292 c4d1f652 2024-03-25 op bio->wantev = 0;
293 7a554149 2024-02-18 op rbuf->len += r;
298 7a554149 2024-02-18 op r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
301 7a554149 2024-02-18 op rbuf->len += r;
306 b19b8dbc 2024-02-18 op bufio_drain(struct bufio *bio, void *d, size_t len)
308 b19b8dbc 2024-02-18 op struct buf *rbuf = &bio->rbuf;
310 b19b8dbc 2024-02-18 op if (len > rbuf->len)
311 b19b8dbc 2024-02-18 op len = rbuf->len;
312 b19b8dbc 2024-02-18 op memcpy(d, rbuf->buf, len);
313 b19b8dbc 2024-02-18 op buf_drain(rbuf, len);
314 b19b8dbc 2024-02-18 op return (len);
318 7a554149 2024-02-18 op bufio_write(struct bufio *bio)
320 7a554149 2024-02-18 op struct buf *wbuf = &bio->wbuf;
323 7a554149 2024-02-18 op if (bio->ctx) {
324 7a554149 2024-02-18 op switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
325 7a554149 2024-02-18 op case TLS_WANT_POLLIN:
326 ce023433 2024-02-22 op errno = EAGAIN;
327 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_READ;
329 7a554149 2024-02-18 op case TLS_WANT_POLLOUT:
330 7a554149 2024-02-18 op errno = EAGAIN;
331 c4d1f652 2024-03-25 op bio->wantev = BUFIO_WANT_WRITE;
336 c4d1f652 2024-03-25 op bio->wantev = 0;
337 7a554149 2024-02-18 op buf_drain(wbuf, w);
342 7a554149 2024-02-18 op w = write(bio->fd, wbuf->buf, wbuf->len);
345 7a554149 2024-02-18 op buf_drain(wbuf, w);
350 8b846311 2024-05-24 op bufio_io_err(struct bufio *bio)
352 8b846311 2024-05-24 op if (bio->ctx)
353 8b846311 2024-05-24 op return tls_error(bio->ctx);
355 8b846311 2024-05-24 op return strerror(errno);
359 7a554149 2024-02-18 op bufio_compose(struct bufio *bio, const void *d, size_t len)
361 7a554149 2024-02-18 op struct buf *wbuf = &bio->wbuf;
363 7a554149 2024-02-18 op while (wbuf->cap - wbuf->len < len) {
364 7a554149 2024-02-18 op if (buf_grow(wbuf) == -1)
368 7a554149 2024-02-18 op memcpy(wbuf->buf + wbuf->len, d, len);
369 7a554149 2024-02-18 op wbuf->len += len;
374 7a554149 2024-02-18 op bufio_compose_str(struct bufio *bio, const char *str)
376 7a554149 2024-02-18 op return (bufio_compose(bio, str, strlen(str)));
380 7a554149 2024-02-18 op bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
386 7a554149 2024-02-18 op va_start(ap, fmt);
387 7a554149 2024-02-18 op r = vasprintf(&str, fmt, ap);
392 7a554149 2024-02-18 op r = bufio_compose(bio, str, r);
398 7a554149 2024-02-18 op bufio_rewind_cursor(struct bufio *bio)
400 7a554149 2024-02-18 op bio->rbuf.cur = 0;
404 7a554149 2024-02-18 op bufio_get_cb(void *d)
406 7a554149 2024-02-18 op struct bufio *bio = d;
407 7a554149 2024-02-18 op struct buf *rbuf = &bio->rbuf;
409 7a554149 2024-02-18 op if (rbuf->cur >= rbuf->len)
410 7a554149 2024-02-18 op return (EOF);
411 7a554149 2024-02-18 op return (rbuf->buf[rbuf->cur++]);
415 7a554149 2024-02-18 op bufio_peek_cb(void *d)
417 7a554149 2024-02-18 op struct bufio *bio = d;
418 7a554149 2024-02-18 op struct buf *rbuf = &bio->rbuf;
420 7a554149 2024-02-18 op if (rbuf->cur >= rbuf->len)
421 7a554149 2024-02-18 op return (EOF);
422 7a554149 2024-02-18 op return (rbuf->buf[rbuf->cur]);