Blame


1 c8dba1e6 2021-07-24 op /*
2 5657662f 2024-01-16 op * Copyright (c) 2021, 2024 Omar Polo <op@omarpolo.com>
3 c8dba1e6 2021-07-24 op *
4 c8dba1e6 2021-07-24 op * Permission to use, copy, modify, and distribute this software for any
5 c8dba1e6 2021-07-24 op * purpose with or without fee is hereby granted, provided that the above
6 c8dba1e6 2021-07-24 op * copyright notice and this permission notice appear in all copies.
7 c8dba1e6 2021-07-24 op *
8 c8dba1e6 2021-07-24 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 c8dba1e6 2021-07-24 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 c8dba1e6 2021-07-24 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 c8dba1e6 2021-07-24 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 c8dba1e6 2021-07-24 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 c8dba1e6 2021-07-24 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 c8dba1e6 2021-07-24 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 c8dba1e6 2021-07-24 op */
16 c8dba1e6 2021-07-24 op
17 c8dba1e6 2021-07-24 op #include "compat.h"
18 c8dba1e6 2021-07-24 op
19 d35e18b3 2024-02-04 op #include <sys/mman.h>
20 c8dba1e6 2021-07-24 op #include <sys/types.h>
21 c8dba1e6 2021-07-24 op #include <sys/socket.h>
22 d35e18b3 2024-02-04 op #include <sys/stat.h>
23 c8dba1e6 2021-07-24 op
24 c8dba1e6 2021-07-24 op #include <netinet/in.h>
25 c8dba1e6 2021-07-24 op
26 c8dba1e6 2021-07-24 op #include <assert.h>
27 c8dba1e6 2021-07-24 op #include <ctype.h>
28 c8dba1e6 2021-07-24 op #include <errno.h>
29 c8dba1e6 2021-07-24 op #include <netdb.h>
30 c8dba1e6 2021-07-24 op #include <stdarg.h>
31 c8dba1e6 2021-07-24 op #include <stdio.h>
32 c8dba1e6 2021-07-24 op #include <stdlib.h>
33 c8dba1e6 2021-07-24 op #include <string.h>
34 c8dba1e6 2021-07-24 op #include <tls.h>
35 c8dba1e6 2021-07-24 op #include <unistd.h>
36 c8dba1e6 2021-07-24 op
37 c8dba1e6 2021-07-24 op #if HAVE_ASR_RUN
38 c8dba1e6 2021-07-24 op # include <asr.h>
39 c8dba1e6 2021-07-24 op #endif
40 c8dba1e6 2021-07-24 op
41 98d3e6c1 2024-02-18 op #include "bufio.h"
42 98d3e6c1 2024-02-18 op #include "ev.h"
43 87d297d1 2024-02-22 op #include "imsgev.h"
44 c8dba1e6 2021-07-24 op #include "telescope.h"
45 9d65b1d9 2022-01-11 op #include "utils.h"
46 c8dba1e6 2021-07-24 op
47 c8dba1e6 2021-07-24 op static struct imsgev *iev_ui;
48 c8dba1e6 2021-07-24 op
49 98d3e6c1 2024-02-18 op enum conn_state {
50 98d3e6c1 2024-02-18 op CONN_CONNECTING,
51 98d3e6c1 2024-02-18 op CONN_HANDSHAKE,
52 98d3e6c1 2024-02-18 op CONN_HEADER,
53 98d3e6c1 2024-02-18 op CONN_BODY,
54 98d3e6c1 2024-02-18 op CONN_CLOSE,
55 98d3e6c1 2024-02-18 op CONN_ERROR,
56 98d3e6c1 2024-02-18 op };
57 98d3e6c1 2024-02-18 op
58 edfe87be 2021-07-24 op /* a pending request */
59 edfe87be 2021-07-24 op struct req {
60 edfe87be 2021-07-24 op uint32_t id;
61 98d3e6c1 2024-02-18 op enum conn_state state;
62 5fb52fc0 2021-07-25 op int proto;
63 edfe87be 2021-07-24 op int fd;
64 5657662f 2024-01-16 op char *host;
65 5657662f 2024-01-16 op char *port;
66 5657662f 2024-01-16 op char *req;
67 edfe87be 2021-07-24 op size_t len;
68 d35e18b3 2024-02-04 op void *ccert;
69 d35e18b3 2024-02-04 op size_t ccert_len;
70 d35e18b3 2024-02-04 op int ccert_fd;
71 c8dba1e6 2021-07-24 op
72 98d3e6c1 2024-02-18 op int eof;
73 62d3cd29 2024-02-22 op unsigned int timer;
74 98d3e6c1 2024-02-18 op struct bufio bio;
75 98d3e6c1 2024-02-18 op
76 c6287992 2024-02-13 op int conn_error;
77 c6287992 2024-02-13 op const char *cause;
78 c6287992 2024-02-13 op
79 edfe87be 2021-07-24 op struct addrinfo *servinfo, *p;
80 edfe87be 2021-07-24 op #if HAVE_ASR_RUN
81 10884685 2024-02-22 op struct asr_query *q;
82 10884685 2024-02-22 op int ar_fd;
83 edfe87be 2021-07-24 op #endif
84 edfe87be 2021-07-24 op
85 edfe87be 2021-07-24 op TAILQ_ENTRY(req) reqs;
86 edfe87be 2021-07-24 op };
87 edfe87be 2021-07-24 op
88 e2a349f7 2021-07-24 op static struct req *req_by_id(uint32_t);
89 e2a349f7 2021-07-24 op
90 77ae5e91 2021-07-24 op static void die(void) __attribute__((__noreturn__));
91 c8dba1e6 2021-07-24 op
92 77ae5e91 2021-07-24 op static void close_with_err(struct req*, const char*);
93 77ae5e91 2021-07-24 op static void close_with_errf(struct req*, const char*, ...)
94 bfb9acb0 2021-07-24 op __attribute__((format(printf, 2, 3)));
95 c8dba1e6 2021-07-24 op
96 98d3e6c1 2024-02-18 op static int try_to_connect(struct req *);
97 77ae5e91 2021-07-24 op static int gemini_parse_reply(struct req *, const char *, size_t);
98 98d3e6c1 2024-02-18 op static void net_ev(int, int, void *);
99 98d3e6c1 2024-02-18 op static void handle_dispatch_imsg(int, int, void*);
100 5b762f01 2021-07-24 op
101 77ae5e91 2021-07-24 op static int net_send_ui(int, uint32_t, const void *, uint16_t);
102 c8dba1e6 2021-07-24 op
103 c8dba1e6 2021-07-24 op /* TODO: making this customizable */
104 c8dba1e6 2021-07-24 op struct timeval timeout_for_handshake = { 5, 0 };
105 c8dba1e6 2021-07-24 op
106 c8dba1e6 2021-07-24 op TAILQ_HEAD(, req) reqhead;
107 c8dba1e6 2021-07-24 op
108 e2a349f7 2021-07-24 op static struct req *
109 e2a349f7 2021-07-24 op req_by_id(uint32_t id)
110 e2a349f7 2021-07-24 op {
111 e2a349f7 2021-07-24 op struct req *r;
112 e2a349f7 2021-07-24 op
113 e2a349f7 2021-07-24 op TAILQ_FOREACH(r, &reqhead, reqs) {
114 e2a349f7 2021-07-24 op if (r->id == id)
115 e2a349f7 2021-07-24 op return r;
116 e2a349f7 2021-07-24 op }
117 e2a349f7 2021-07-24 op
118 e2a349f7 2021-07-24 op return NULL;
119 e2a349f7 2021-07-24 op }
120 e2a349f7 2021-07-24 op
121 c8dba1e6 2021-07-24 op static void __attribute__((__noreturn__))
122 c8dba1e6 2021-07-24 op die(void)
123 c8dba1e6 2021-07-24 op {
124 c8dba1e6 2021-07-24 op abort(); /* TODO */
125 c8dba1e6 2021-07-24 op }
126 c8dba1e6 2021-07-24 op
127 ce023433 2024-02-22 op static inline int
128 ce023433 2024-02-22 op req_bio_ev(struct req *req)
129 ce023433 2024-02-22 op {
130 ce023433 2024-02-22 op int ret, ev;
131 ce023433 2024-02-22 op
132 ce023433 2024-02-22 op ret = 0;
133 ce023433 2024-02-22 op ev = bufio_ev(&req->bio);
134 ce023433 2024-02-22 op if (ev & BUFIO_WANT_READ)
135 ce023433 2024-02-22 op ret |= EV_READ;
136 ce023433 2024-02-22 op if (ev & BUFIO_WANT_WRITE)
137 ce023433 2024-02-22 op ret |= EV_WRITE;
138 ce023433 2024-02-22 op return (ret);
139 ce023433 2024-02-22 op }
140 ce023433 2024-02-22 op
141 c8dba1e6 2021-07-24 op static void
142 98d3e6c1 2024-02-18 op close_conn(int fd, int ev, void *d)
143 c8dba1e6 2021-07-24 op {
144 c8dba1e6 2021-07-24 op struct req *req = d;
145 c8dba1e6 2021-07-24 op
146 98d3e6c1 2024-02-18 op if (req->state != CONN_ERROR)
147 98d3e6c1 2024-02-18 op req->state = CONN_CLOSE;
148 98d3e6c1 2024-02-18 op
149 c8dba1e6 2021-07-24 op #if HAVE_ASR_RUN
150 10884685 2024-02-22 op if (req->q) {
151 10884685 2024-02-22 op asr_abort(req->q);
152 10884685 2024-02-22 op ev_del(req->ar_fd);
153 10884685 2024-02-22 op }
154 c8dba1e6 2021-07-24 op #endif
155 c8dba1e6 2021-07-24 op
156 62d3cd29 2024-02-22 op if (req->timer != 0) {
157 62d3cd29 2024-02-22 op ev_timer_cancel(req->timer);
158 62d3cd29 2024-02-22 op req->timer = 0;
159 5b762f01 2021-07-24 op }
160 5b762f01 2021-07-24 op
161 98d3e6c1 2024-02-18 op if (req->state == CONN_CLOSE &&
162 99ebdacb 2024-02-18 op req->fd != -1 &&
163 98d3e6c1 2024-02-18 op bufio_close(&req->bio) == -1 &&
164 98d3e6c1 2024-02-18 op errno == EAGAIN) {
165 ce023433 2024-02-22 op ev_add(req->fd, req_bio_ev(req), close_conn, req);
166 98d3e6c1 2024-02-18 op return;
167 d35e18b3 2024-02-04 op }
168 d35e18b3 2024-02-04 op
169 98d3e6c1 2024-02-18 op if (req->servinfo)
170 98d3e6c1 2024-02-18 op freeaddrinfo(req->servinfo);
171 98d3e6c1 2024-02-18 op
172 98d3e6c1 2024-02-18 op bufio_free(&req->bio);
173 98d3e6c1 2024-02-18 op
174 d35e18b3 2024-02-04 op if (req->ccert != NULL) {
175 d35e18b3 2024-02-04 op munmap(req->ccert, req->ccert_len);
176 d35e18b3 2024-02-04 op close(req->ccert_fd);
177 c8dba1e6 2021-07-24 op }
178 c8dba1e6 2021-07-24 op
179 5657662f 2024-01-16 op free(req->host);
180 5657662f 2024-01-16 op free(req->port);
181 5657662f 2024-01-16 op free(req->req);
182 5657662f 2024-01-16 op
183 c8dba1e6 2021-07-24 op TAILQ_REMOVE(&reqhead, req, reqs);
184 98d3e6c1 2024-02-18 op if (req->fd != -1) {
185 98d3e6c1 2024-02-18 op ev_del(req->fd);
186 c8dba1e6 2021-07-24 op close(req->fd);
187 98d3e6c1 2024-02-18 op }
188 c8dba1e6 2021-07-24 op free(req);
189 c8dba1e6 2021-07-24 op }
190 c8dba1e6 2021-07-24 op
191 c8dba1e6 2021-07-24 op static void
192 c8dba1e6 2021-07-24 op close_with_err(struct req *req, const char *err)
193 c8dba1e6 2021-07-24 op {
194 98d3e6c1 2024-02-18 op req->state = CONN_ERROR;
195 c8dba1e6 2021-07-24 op net_send_ui(IMSG_ERR, req->id, err, strlen(err)+1);
196 c8dba1e6 2021-07-24 op close_conn(0, 0, req);
197 c8dba1e6 2021-07-24 op }
198 c8dba1e6 2021-07-24 op
199 c8dba1e6 2021-07-24 op static void
200 c8dba1e6 2021-07-24 op close_with_errf(struct req *req, const char *fmt, ...)
201 c8dba1e6 2021-07-24 op {
202 c8dba1e6 2021-07-24 op va_list ap;
203 c8dba1e6 2021-07-24 op char *s;
204 c8dba1e6 2021-07-24 op
205 c8dba1e6 2021-07-24 op va_start(ap, fmt);
206 c8dba1e6 2021-07-24 op if (vasprintf(&s, fmt, ap) == -1)
207 c8dba1e6 2021-07-24 op abort();
208 c8dba1e6 2021-07-24 op va_end(ap);
209 c8dba1e6 2021-07-24 op
210 c8dba1e6 2021-07-24 op close_with_err(req, s);
211 c8dba1e6 2021-07-24 op free(s);
212 c8dba1e6 2021-07-24 op }
213 c8dba1e6 2021-07-24 op
214 10884685 2024-02-22 op #if HAVE_ASR_RUN
215 10884685 2024-02-22 op static void
216 10884685 2024-02-22 op req_resolve(int fd, int ev, void *d)
217 10884685 2024-02-22 op {
218 10884685 2024-02-22 op struct req *req = d;
219 10884685 2024-02-22 op struct addrinfo hints;
220 10884685 2024-02-22 op struct asr_result ar;
221 10884685 2024-02-22 op struct timeval tv;
222 10884685 2024-02-22 op
223 10884685 2024-02-22 op if (req->q == NULL) {
224 10884685 2024-02-22 op memset(&hints, 0, sizeof(hints));
225 10884685 2024-02-22 op hints.ai_family = AF_UNSPEC;
226 10884685 2024-02-22 op hints.ai_socktype = SOCK_STREAM;
227 10884685 2024-02-22 op
228 10884685 2024-02-22 op req->q = getaddrinfo_async(req->host, req->port, &hints, NULL);
229 10884685 2024-02-22 op if (req->q == NULL) {
230 10884685 2024-02-22 op close_with_errf(req, "getaddrinfo_async: %s",
231 10884685 2024-02-22 op strerror(errno));
232 10884685 2024-02-22 op return;
233 10884685 2024-02-22 op }
234 10884685 2024-02-22 op }
235 10884685 2024-02-22 op
236 10884685 2024-02-22 op if (fd != -1)
237 10884685 2024-02-22 op ev_del(fd);
238 62d3cd29 2024-02-22 op if (req->timer) {
239 62d3cd29 2024-02-22 op ev_timer_cancel(req->timer);
240 62d3cd29 2024-02-22 op req->timer = 0;
241 10884685 2024-02-22 op }
242 10884685 2024-02-22 op
243 10884685 2024-02-22 op if (asr_run(req->q, &ar) == 0) {
244 10884685 2024-02-22 op ev = 0;
245 10884685 2024-02-22 op if (ar.ar_cond & ASR_WANT_READ)
246 10884685 2024-02-22 op ev |= EV_READ;
247 10884685 2024-02-22 op if (ar.ar_cond & ASR_WANT_WRITE)
248 10884685 2024-02-22 op ev |= EV_WRITE;
249 10884685 2024-02-22 op
250 10884685 2024-02-22 op req->ar_fd = ar.ar_fd;
251 10884685 2024-02-22 op if (ev_add(req->ar_fd, ev, req_resolve, req) == -1) {
252 10884685 2024-02-22 op close_with_errf(req, "ev_add failure: %s",
253 10884685 2024-02-22 op strerror(errno));
254 10884685 2024-02-22 op return;
255 10884685 2024-02-22 op }
256 10884685 2024-02-22 op
257 10884685 2024-02-22 op tv.tv_sec = ar.ar_timeout / 1000;
258 10884685 2024-02-22 op tv.tv_usec = (ar.ar_timeout % 1000) * 1000;
259 62d3cd29 2024-02-22 op req->timer = ev_timer(&tv, req_resolve, req);
260 62d3cd29 2024-02-22 op if (req->timer == 0)
261 10884685 2024-02-22 op close_with_errf(req, "ev_timer failure: %s",
262 10884685 2024-02-22 op strerror(errno));
263 10884685 2024-02-22 op return;
264 10884685 2024-02-22 op }
265 10884685 2024-02-22 op
266 10884685 2024-02-22 op req->ar_fd = -1;
267 10884685 2024-02-22 op req->q = NULL;
268 10884685 2024-02-22 op
269 10884685 2024-02-22 op if (ar.ar_gai_errno) {
270 10884685 2024-02-22 op close_with_errf(req, "failed to resolve %s: %s",
271 10884685 2024-02-22 op req->host, gai_strerror(ar.ar_gai_errno));
272 10884685 2024-02-22 op return;
273 10884685 2024-02-22 op }
274 10884685 2024-02-22 op
275 10884685 2024-02-22 op req->servinfo = ar.ar_addrinfo;
276 10884685 2024-02-22 op
277 10884685 2024-02-22 op req->p = req->servinfo;
278 10884685 2024-02-22 op net_ev(-1, EV_READ, req);
279 10884685 2024-02-22 op }
280 10884685 2024-02-22 op #else
281 10884685 2024-02-22 op static void
282 10884685 2024-02-22 op req_resolve(int fd, int ev, struct req *req)
283 10884685 2024-02-22 op {
284 10884685 2024-02-22 op struct addrinfo hints;
285 10884685 2024-02-22 op int s;
286 10884685 2024-02-22 op
287 10884685 2024-02-22 op memset(&hints, 0, sizeof(hints));
288 10884685 2024-02-22 op hints.ai_family = AF_UNSPEC;
289 10884685 2024-02-22 op hints.ai_socktype = SOCK_STREAM;
290 10884685 2024-02-22 op
291 10884685 2024-02-22 op s = getaddrinfo(req->host, req->port, &hints, &req->servinfo);
292 10884685 2024-02-22 op if (s != 0) {
293 10884685 2024-02-22 op close_with_errf(req, "failed to resolve %s: %s",
294 10884685 2024-02-22 op req->host, gai_strerror(s));
295 10884685 2024-02-22 op return;
296 10884685 2024-02-22 op }
297 10884685 2024-02-22 op
298 10884685 2024-02-22 op req->fd = -1;
299 10884685 2024-02-22 op req->p = req->servinfo;
300 10884685 2024-02-22 op net_ev(-1, EV_READ, req);
301 10884685 2024-02-22 op }
302 10884685 2024-02-22 op #endif
303 10884685 2024-02-22 op
304 98d3e6c1 2024-02-18 op static int
305 98d3e6c1 2024-02-18 op try_to_connect(struct req *req)
306 c8dba1e6 2021-07-24 op {
307 98d3e6c1 2024-02-18 op int error;
308 98d3e6c1 2024-02-18 op socklen_t len = sizeof(error);
309 c8dba1e6 2021-07-24 op
310 98d3e6c1 2024-02-18 op again:
311 98d3e6c1 2024-02-18 op if (req->p == NULL)
312 98d3e6c1 2024-02-18 op return (-1);
313 c8dba1e6 2021-07-24 op
314 98d3e6c1 2024-02-18 op if (req->fd != -1) {
315 98d3e6c1 2024-02-18 op if (getsockopt(req->fd, SOL_SOCKET, SO_ERROR, &error,
316 98d3e6c1 2024-02-18 op &len) == -1) {
317 98d3e6c1 2024-02-18 op req->conn_error = errno;
318 98d3e6c1 2024-02-18 op req->cause = "getsockopt";
319 98d3e6c1 2024-02-18 op return (-1);
320 98d3e6c1 2024-02-18 op }
321 c8dba1e6 2021-07-24 op
322 98d3e6c1 2024-02-18 op if (error == 0) /* connected */
323 98d3e6c1 2024-02-18 op return (0);
324 c8dba1e6 2021-07-24 op
325 98d3e6c1 2024-02-18 op req->conn_error = error;
326 98d3e6c1 2024-02-18 op req->cause = "connect";
327 98d3e6c1 2024-02-18 op close(req->fd);
328 98d3e6c1 2024-02-18 op req->fd = -1;
329 98d3e6c1 2024-02-18 op req->p = req->p->ai_next;
330 98d3e6c1 2024-02-18 op goto again;
331 5b762f01 2021-07-24 op }
332 5b762f01 2021-07-24 op
333 98d3e6c1 2024-02-18 op req->fd = socket(req->p->ai_family, req->p->ai_socktype,
334 98d3e6c1 2024-02-18 op req->p->ai_protocol);
335 98d3e6c1 2024-02-18 op if (req->fd == -1) {
336 98d3e6c1 2024-02-18 op req->conn_error = errno;
337 98d3e6c1 2024-02-18 op req->cause = "socket";
338 98d3e6c1 2024-02-18 op req->p = req->p->ai_next;
339 98d3e6c1 2024-02-18 op goto again;
340 5b762f01 2021-07-24 op }
341 c8dba1e6 2021-07-24 op
342 98d3e6c1 2024-02-18 op if (!mark_nonblock_cloexec(req->fd)) {
343 98d3e6c1 2024-02-18 op req->conn_error = errno;
344 98d3e6c1 2024-02-18 op req->cause = "setsockopt";
345 98d3e6c1 2024-02-18 op return (-1);
346 5b762f01 2021-07-24 op }
347 c8dba1e6 2021-07-24 op
348 98d3e6c1 2024-02-18 op if (connect(req->fd, req->p->ai_addr, req->p->ai_addrlen) == 0)
349 98d3e6c1 2024-02-18 op return (0);
350 98d3e6c1 2024-02-18 op errno = EAGAIN;
351 98d3e6c1 2024-02-18 op return (-1);
352 5b762f01 2021-07-24 op }
353 5b762f01 2021-07-24 op
354 5b762f01 2021-07-24 op static int
355 5b762f01 2021-07-24 op gemini_parse_reply(struct req *req, const char *header, size_t len)
356 5b762f01 2021-07-24 op {
357 54764e41 2024-02-02 op struct ibuf *ibuf;
358 5b762f01 2021-07-24 op int code;
359 5b762f01 2021-07-24 op const char *t;
360 5b762f01 2021-07-24 op
361 5b762f01 2021-07-24 op if (len < 4)
362 5b762f01 2021-07-24 op return 0;
363 5b762f01 2021-07-24 op
364 5b762f01 2021-07-24 op if (!isdigit(header[0]) || !isdigit(header[1]))
365 5b762f01 2021-07-24 op return 0;
366 5b762f01 2021-07-24 op
367 5b762f01 2021-07-24 op code = (header[0] - '0')*10 + (header[1] - '0');
368 5b762f01 2021-07-24 op if (header[2] != ' ')
369 5b762f01 2021-07-24 op return 0;
370 5b762f01 2021-07-24 op
371 5b762f01 2021-07-24 op t = header + 3;
372 54764e41 2024-02-02 op len = strlen(t) + 1;
373 5b762f01 2021-07-24 op
374 54764e41 2024-02-02 op if ((ibuf = imsg_create(&iev_ui->ibuf, IMSG_REPLY, req->id, 0,
375 54764e41 2024-02-02 op sizeof(code) + len)) == NULL)
376 54764e41 2024-02-02 op die();
377 54764e41 2024-02-02 op if (imsg_add(ibuf, &code, sizeof(code)) == -1 ||
378 54764e41 2024-02-02 op imsg_add(ibuf, t, len) == -1)
379 54764e41 2024-02-02 op die();
380 54764e41 2024-02-02 op imsg_close(&iev_ui->ibuf, ibuf);
381 54764e41 2024-02-02 op imsg_event_add(iev_ui);
382 5b762f01 2021-07-24 op
383 98d3e6c1 2024-02-18 op /* pause until we've told go go ahead */
384 98d3e6c1 2024-02-18 op ev_del(req->fd);
385 5b762f01 2021-07-24 op
386 0e49c9bb 2022-01-21 op return code;
387 5b762f01 2021-07-24 op }
388 c8dba1e6 2021-07-24 op
389 98d3e6c1 2024-02-18 op static inline int
390 98d3e6c1 2024-02-18 op net_send_req(struct req *req)
391 5b762f01 2021-07-24 op {
392 98d3e6c1 2024-02-18 op return (bufio_compose(&req->bio, req->req, req->len));
393 5b762f01 2021-07-24 op }
394 5b762f01 2021-07-24 op
395 5b762f01 2021-07-24 op static void
396 98d3e6c1 2024-02-18 op net_ev(int fd, int ev, void *d)
397 5b762f01 2021-07-24 op {
398 b07d2757 2024-01-31 op static char buf[4096];
399 5b762f01 2021-07-24 op struct req *req = d;
400 98d3e6c1 2024-02-18 op const char *hash;
401 98d3e6c1 2024-02-18 op ssize_t read;
402 b07d2757 2024-01-31 op size_t len;
403 98d3e6c1 2024-02-18 op char *header, *endl;
404 5b762f01 2021-07-24 op int r;
405 5b762f01 2021-07-24 op
406 98d3e6c1 2024-02-18 op if (ev == EV_TIMEOUT) {
407 98d3e6c1 2024-02-18 op close_with_err(req, "Timeout loading page");
408 98d3e6c1 2024-02-18 op return;
409 98d3e6c1 2024-02-18 op }
410 98d3e6c1 2024-02-18 op
411 98d3e6c1 2024-02-18 op if (req->state == CONN_CONNECTING) {
412 98d3e6c1 2024-02-18 op ev_del(req->fd);
413 98d3e6c1 2024-02-18 op if (try_to_connect(req) == -1) {
414 98d3e6c1 2024-02-18 op if (req->fd != -1 && errno == EAGAIN) {
415 98d3e6c1 2024-02-18 op ev_add(req->fd, EV_WRITE, net_ev, req);
416 98d3e6c1 2024-02-18 op return;
417 98d3e6c1 2024-02-18 op }
418 98d3e6c1 2024-02-18 op close_with_errf(req, "failed to connect to %s"
419 98d3e6c1 2024-02-18 op " (%s: %s)", req->host, req->cause,
420 98d3e6c1 2024-02-18 op strerror(req->conn_error));
421 186a1eec 2024-01-31 op return;
422 186a1eec 2024-01-31 op }
423 98d3e6c1 2024-02-18 op
424 98d3e6c1 2024-02-18 op bufio_set_fd(&req->bio, req->fd);
425 98d3e6c1 2024-02-18 op
426 98d3e6c1 2024-02-18 op switch (req->proto) {
427 98d3e6c1 2024-02-18 op case PROTO_FINGER:
428 98d3e6c1 2024-02-18 op case PROTO_GOPHER:
429 98d3e6c1 2024-02-18 op /* finger and gopher don't have a header nor TLS */
430 98d3e6c1 2024-02-18 op req->state = CONN_BODY;
431 98d3e6c1 2024-02-18 op if (net_send_req(req) == -1) {
432 98d3e6c1 2024-02-18 op close_with_err(req, "failed to send request");
433 98d3e6c1 2024-02-18 op return;
434 98d3e6c1 2024-02-18 op }
435 98d3e6c1 2024-02-18 op break;
436 98d3e6c1 2024-02-18 op case PROTO_GEMINI:
437 98d3e6c1 2024-02-18 op req->state = CONN_HANDSHAKE;
438 98d3e6c1 2024-02-18 op if (bufio_starttls(&req->bio, req->host, 1,
439 98d3e6c1 2024-02-18 op req->ccert, req->ccert_len,
440 98d3e6c1 2024-02-18 op req->ccert, req->ccert_len) == -1) {
441 98d3e6c1 2024-02-18 op close_with_err(req, "failed to setup TLS");
442 98d3e6c1 2024-02-18 op return;
443 98d3e6c1 2024-02-18 op }
444 62d3cd29 2024-02-22 op req->timer = ev_timer(&timeout_for_handshake,
445 98d3e6c1 2024-02-18 op net_ev, req);
446 62d3cd29 2024-02-22 op if (req->timer == 0) {
447 98d3e6c1 2024-02-18 op close_with_err(req, "failed to setup"
448 98d3e6c1 2024-02-18 op " handshake timer");
449 98d3e6c1 2024-02-18 op return;
450 98d3e6c1 2024-02-18 op }
451 98d3e6c1 2024-02-18 op break;
452 98d3e6c1 2024-02-18 op }
453 98d3e6c1 2024-02-18 op }
454 98d3e6c1 2024-02-18 op
455 98d3e6c1 2024-02-18 op if (req->state == CONN_HANDSHAKE) {
456 98d3e6c1 2024-02-18 op if (bufio_handshake(&req->bio) == -1 && errno == EAGAIN) {
457 ce023433 2024-02-22 op ev_add(req->fd, req_bio_ev(req), net_ev, req);
458 5b762f01 2021-07-24 op return;
459 186a1eec 2024-01-31 op }
460 98d3e6c1 2024-02-18 op
461 62d3cd29 2024-02-22 op ev_timer_cancel(req->timer);
462 62d3cd29 2024-02-22 op req->timer = 0;
463 98d3e6c1 2024-02-18 op
464 98d3e6c1 2024-02-18 op req->state = CONN_HEADER;
465 98d3e6c1 2024-02-18 op
466 98d3e6c1 2024-02-18 op /* pause until we've told the certificate is OK */
467 98d3e6c1 2024-02-18 op ev_del(req->fd);
468 98d3e6c1 2024-02-18 op
469 98d3e6c1 2024-02-18 op hash = tls_peer_cert_hash(req->bio.ctx);
470 98d3e6c1 2024-02-18 op if (hash == NULL) {
471 98d3e6c1 2024-02-18 op close_with_errf(req, "handshake failed: %s",
472 98d3e6c1 2024-02-18 op tls_error(req->bio.ctx));
473 b07d2757 2024-01-31 op return;
474 b07d2757 2024-01-31 op }
475 0e8f22ed 2021-09-12 op
476 98d3e6c1 2024-02-18 op net_send_ui(IMSG_CHECK_CERT, req->id, hash, strlen(hash)+1);
477 98d3e6c1 2024-02-18 op return;
478 0e8f22ed 2021-09-12 op }
479 c8dba1e6 2021-07-24 op
480 98d3e6c1 2024-02-18 op if (ev & EV_READ) {
481 98d3e6c1 2024-02-18 op read = bufio_read(&req->bio);
482 98d3e6c1 2024-02-18 op if (read == -1 && errno != EAGAIN) {
483 98d3e6c1 2024-02-18 op close_with_errf(req, "Read error");
484 98d3e6c1 2024-02-18 op return;
485 98d3e6c1 2024-02-18 op }
486 98d3e6c1 2024-02-18 op if (read == 0)
487 98d3e6c1 2024-02-18 op req->eof = 1;
488 5b762f01 2021-07-24 op }
489 c8dba1e6 2021-07-24 op
490 98d3e6c1 2024-02-18 op if ((ev & EV_WRITE) && bufio_write(&req->bio) == -1 &&
491 98d3e6c1 2024-02-18 op errno != EAGAIN) {
492 98d3e6c1 2024-02-18 op close_with_errf(req, "bufio_write: %s", strerror(errno));
493 5b762f01 2021-07-24 op return;
494 c8dba1e6 2021-07-24 op }
495 5b762f01 2021-07-24 op
496 98d3e6c1 2024-02-18 op if (req->state == CONN_HEADER) {
497 98d3e6c1 2024-02-18 op header = req->bio.rbuf.buf;
498 98d3e6c1 2024-02-18 op endl = memmem(header, req->bio.rbuf.len, "\r\n", 2);
499 98d3e6c1 2024-02-18 op if (endl == NULL && req->bio.rbuf.len >= 1024) {
500 98d3e6c1 2024-02-18 op close_with_err(req, "Invalid gemini reply (too long)");
501 98cba69e 2021-11-10 op return;
502 98cba69e 2021-11-10 op }
503 98d3e6c1 2024-02-18 op if (endl == NULL && req->eof) {
504 98d3e6c1 2024-02-18 op close_with_err(req, "Invalid gemini reply.");
505 98d3e6c1 2024-02-18 op return;
506 98d3e6c1 2024-02-18 op }
507 98d3e6c1 2024-02-18 op if (endl == NULL) {
508 ce023433 2024-02-22 op ev_add(req->fd, req_bio_ev(req), net_ev, req);
509 98d3e6c1 2024-02-18 op return;
510 98d3e6c1 2024-02-18 op }
511 98d3e6c1 2024-02-18 op *endl = '\0';
512 98d3e6c1 2024-02-18 op req->state = CONN_BODY;
513 98d3e6c1 2024-02-18 op r = gemini_parse_reply(req, header, strlen(header));
514 98d3e6c1 2024-02-18 op buf_drain(&req->bio.rbuf, endl - header + 2);
515 98d3e6c1 2024-02-18 op if (r == 0) {
516 98d3e6c1 2024-02-18 op close_with_err(req, "Malformed gemini reply");
517 98d3e6c1 2024-02-18 op return;
518 98d3e6c1 2024-02-18 op }
519 98d3e6c1 2024-02-18 op if (r < 20 || r >= 30)
520 98d3e6c1 2024-02-18 op close_conn(0, 0, req);
521 5b762f01 2021-07-24 op return;
522 5b762f01 2021-07-24 op }
523 98d3e6c1 2024-02-18 op
524 98d3e6c1 2024-02-18 op /*
525 98d3e6c1 2024-02-18 op * Split data into chunks before sending. imsg can't handle
526 98d3e6c1 2024-02-18 op * message that are "too big".
527 98d3e6c1 2024-02-18 op */
528 98d3e6c1 2024-02-18 op for (;;) {
529 98d3e6c1 2024-02-18 op if ((len = bufio_drain(&req->bio, buf, sizeof(buf))) == 0)
530 98d3e6c1 2024-02-18 op break;
531 98d3e6c1 2024-02-18 op net_send_ui(IMSG_BUF, req->id, buf, len);
532 5b762f01 2021-07-24 op }
533 5b762f01 2021-07-24 op
534 98d3e6c1 2024-02-18 op if (req->eof) {
535 98d3e6c1 2024-02-18 op net_send_ui(IMSG_EOF, req->id, NULL, 0);
536 98d3e6c1 2024-02-18 op close_conn(0, 0, req);
537 cc300b25 2024-02-18 op return;
538 5b762f01 2021-07-24 op }
539 5b762f01 2021-07-24 op
540 ce023433 2024-02-22 op ev_add(req->fd, req_bio_ev(req), net_ev, req);
541 d35e18b3 2024-02-04 op }
542 d35e18b3 2024-02-04 op
543 d35e18b3 2024-02-04 op static int
544 d35e18b3 2024-02-04 op load_cert(struct imsg *imsg, struct req *req)
545 d35e18b3 2024-02-04 op {
546 d35e18b3 2024-02-04 op struct stat sb;
547 d35e18b3 2024-02-04 op int fd;
548 d35e18b3 2024-02-04 op
549 d35e18b3 2024-02-04 op if ((fd = imsg_get_fd(imsg)) == -1)
550 d35e18b3 2024-02-04 op return (0);
551 d35e18b3 2024-02-04 op
552 d35e18b3 2024-02-04 op if (fstat(fd, &sb) == -1)
553 d35e18b3 2024-02-04 op return (-1);
554 d35e18b3 2024-02-04 op
555 d35e18b3 2024-02-04 op #if 0
556 d35e18b3 2024-02-04 op if (sb.st_size >= (off_t)SIZE_MAX) {
557 d35e18b3 2024-02-04 op close(fd);
558 d35e18b3 2024-02-04 op return (-1);
559 d35e18b3 2024-02-04 op }
560 d35e18b3 2024-02-04 op #endif
561 d35e18b3 2024-02-04 op
562 d35e18b3 2024-02-04 op req->ccert = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
563 d35e18b3 2024-02-04 op if (req->ccert == MAP_FAILED) {
564 d35e18b3 2024-02-04 op req->ccert = NULL;
565 d35e18b3 2024-02-04 op close(fd);
566 d35e18b3 2024-02-04 op return (-1);
567 d35e18b3 2024-02-04 op }
568 d35e18b3 2024-02-04 op
569 d35e18b3 2024-02-04 op req->ccert_len = sb.st_size;
570 d35e18b3 2024-02-04 op req->ccert_fd = fd;
571 d35e18b3 2024-02-04 op
572 d35e18b3 2024-02-04 op return (0);
573 c8dba1e6 2021-07-24 op }
574 c8dba1e6 2021-07-24 op
575 c8dba1e6 2021-07-24 op static void
576 98d3e6c1 2024-02-18 op handle_dispatch_imsg(int fd, int event, void *d)
577 c8dba1e6 2021-07-24 op {
578 0640b555 2022-05-27 op struct imsgev *iev = d;
579 0640b555 2022-05-27 op struct imsgbuf *ibuf = &iev->ibuf;
580 0640b555 2022-05-27 op struct imsg imsg;
581 c8dba1e6 2021-07-24 op struct req *req;
582 0388b56b 2024-01-31 op struct get_req r;
583 0640b555 2022-05-27 op ssize_t n;
584 0640b555 2022-05-27 op int certok;
585 c8dba1e6 2021-07-24 op
586 0640b555 2022-05-27 op if (event & EV_READ) {
587 0640b555 2022-05-27 op if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
588 0640b555 2022-05-27 op err(1, "imsg_read");
589 0640b555 2022-05-27 op if (n == 0)
590 0640b555 2022-05-27 op err(1, "connection closed");
591 0640b555 2022-05-27 op }
592 0640b555 2022-05-27 op if (event & EV_WRITE) {
593 0640b555 2022-05-27 op if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
594 0640b555 2022-05-27 op err(1, "msgbuf_write");
595 0640b555 2022-05-27 op if (n == 0)
596 0640b555 2022-05-27 op err(1, "connection closed");
597 0640b555 2022-05-27 op }
598 c8dba1e6 2021-07-24 op
599 0640b555 2022-05-27 op for (;;) {
600 0640b555 2022-05-27 op if ((n = imsg_get(ibuf, &imsg)) == -1)
601 0640b555 2022-05-27 op err(1, "imsg_get");
602 0640b555 2022-05-27 op if (n == 0)
603 0640b555 2022-05-27 op break;
604 0388b56b 2024-01-31 op switch (imsg_get_type(&imsg)) {
605 c6e37ffd 2022-05-27 op case IMSG_GET:
606 0388b56b 2024-01-31 op if (imsg_get_data(&imsg, &r, sizeof(r)) == -1 ||
607 0388b56b 2024-01-31 op r.host[sizeof(r.host) - 1] != '\0' ||
608 0388b56b 2024-01-31 op r.port[sizeof(r.port) - 1] != '\0' ||
609 0388b56b 2024-01-31 op r.req[sizeof(r.req) - 1] != '\0')
610 0640b555 2022-05-27 op die();
611 0388b56b 2024-01-31 op if (r.proto != PROTO_FINGER &&
612 0388b56b 2024-01-31 op r.proto != PROTO_GEMINI &&
613 0388b56b 2024-01-31 op r.proto != PROTO_GOPHER)
614 0640b555 2022-05-27 op die();
615 c8dba1e6 2021-07-24 op
616 0640b555 2022-05-27 op if ((req = calloc(1, sizeof(*req))) == NULL)
617 0640b555 2022-05-27 op die();
618 5b762f01 2021-07-24 op
619 51ea137b 2024-02-22 op req->fd = -1;
620 51ea137b 2024-02-22 op #if HAVE_ASR_RUN
621 51ea137b 2024-02-22 op req->ar_fd = -1;
622 51ea137b 2024-02-22 op #endif
623 d35e18b3 2024-02-04 op req->ccert_fd = -1;
624 0388b56b 2024-01-31 op req->id = imsg_get_id(&imsg);
625 0640b555 2022-05-27 op TAILQ_INSERT_HEAD(&reqhead, req, reqs);
626 5fb52fc0 2021-07-25 op
627 0388b56b 2024-01-31 op if ((req->host = strdup(r.host)) == NULL)
628 5657662f 2024-01-16 op die();
629 0388b56b 2024-01-31 op if ((req->port = strdup(r.port)) == NULL)
630 5657662f 2024-01-16 op die();
631 0388b56b 2024-01-31 op if ((req->req = strdup(r.req)) == NULL)
632 5657662f 2024-01-16 op die();
633 d35e18b3 2024-02-04 op if (load_cert(&imsg, req) == -1)
634 d35e18b3 2024-02-04 op die();
635 98d3e6c1 2024-02-18 op if (bufio_init(&req->bio) == -1)
636 98d3e6c1 2024-02-18 op die();
637 5657662f 2024-01-16 op
638 5657662f 2024-01-16 op req->len = strlen(req->req);
639 0388b56b 2024-01-31 op req->proto = r.proto;
640 10884685 2024-02-22 op req_resolve(-1, 0, req);
641 0640b555 2022-05-27 op break;
642 0640b555 2022-05-27 op
643 0640b555 2022-05-27 op case IMSG_CERT_STATUS:
644 0388b56b 2024-01-31 op if ((req = req_by_id(imsg_get_id(&imsg))) == NULL)
645 0640b555 2022-05-27 op break;
646 0640b555 2022-05-27 op
647 c24b14ad 2024-01-22 op if (imsg_get_data(&imsg, &certok, sizeof(certok)) ==
648 c24b14ad 2024-01-22 op -1)
649 0640b555 2022-05-27 op die();
650 98d3e6c1 2024-02-18 op if (!certok) {
651 0640b555 2022-05-27 op close_conn(0, 0, req);
652 98d3e6c1 2024-02-18 op break;
653 98d3e6c1 2024-02-18 op }
654 98d3e6c1 2024-02-18 op
655 98d3e6c1 2024-02-18 op if (net_send_req(req) == -1) {
656 98d3e6c1 2024-02-18 op close_with_err(req, "failed to send request");
657 98d3e6c1 2024-02-18 op break;
658 98d3e6c1 2024-02-18 op }
659 98d3e6c1 2024-02-18 op
660 98d3e6c1 2024-02-18 op if (ev_add(req->fd, EV_WRITE, net_ev, req) == -1) {
661 98d3e6c1 2024-02-18 op close_with_err(req,
662 98d3e6c1 2024-02-18 op "failed to register event.");
663 98d3e6c1 2024-02-18 op break;
664 98d3e6c1 2024-02-18 op }
665 0640b555 2022-05-27 op break;
666 c8dba1e6 2021-07-24 op
667 0640b555 2022-05-27 op case IMSG_PROCEED:
668 0388b56b 2024-01-31 op if ((req = req_by_id(imsg_get_id(&imsg))) == NULL)
669 0640b555 2022-05-27 op break;
670 98d3e6c1 2024-02-18 op ev_add(req->fd, EV_READ, net_ev, req);
671 98d3e6c1 2024-02-18 op net_ev(req->fd, 0, req);
672 0640b555 2022-05-27 op break;
673 c8dba1e6 2021-07-24 op
674 0640b555 2022-05-27 op case IMSG_STOP:
675 0388b56b 2024-01-31 op if ((req = req_by_id(imsg_get_id(&imsg))) == NULL)
676 0640b555 2022-05-27 op break;
677 0640b555 2022-05-27 op close_conn(0, 0, req);
678 0640b555 2022-05-27 op break;
679 c8dba1e6 2021-07-24 op
680 0640b555 2022-05-27 op case IMSG_QUIT:
681 98d3e6c1 2024-02-18 op ev_break();
682 0640b555 2022-05-27 op imsg_free(&imsg);
683 0640b555 2022-05-27 op return;
684 c8dba1e6 2021-07-24 op
685 0640b555 2022-05-27 op default:
686 0388b56b 2024-01-31 op errx(1, "got unknown imsg %d", imsg_get_type(&imsg));
687 0640b555 2022-05-27 op }
688 c8dba1e6 2021-07-24 op
689 0640b555 2022-05-27 op imsg_free(&imsg);
690 0640b555 2022-05-27 op }
691 5b762f01 2021-07-24 op
692 0640b555 2022-05-27 op imsg_event_add(iev);
693 c8dba1e6 2021-07-24 op }
694 c8dba1e6 2021-07-24 op
695 c8dba1e6 2021-07-24 op static int
696 c8dba1e6 2021-07-24 op net_send_ui(int type, uint32_t peerid, const void *data,
697 c8dba1e6 2021-07-24 op uint16_t datalen)
698 c8dba1e6 2021-07-24 op {
699 c8dba1e6 2021-07-24 op return imsg_compose_event(iev_ui, type, peerid, 0, -1,
700 c8dba1e6 2021-07-24 op data, datalen);
701 c8dba1e6 2021-07-24 op }
702 c8dba1e6 2021-07-24 op
703 c8dba1e6 2021-07-24 op int
704 f45bd2e3 2021-07-24 op net_main(void)
705 c8dba1e6 2021-07-24 op {
706 c8dba1e6 2021-07-24 op setproctitle("net");
707 c8dba1e6 2021-07-24 op
708 c8dba1e6 2021-07-24 op TAILQ_INIT(&reqhead);
709 c8dba1e6 2021-07-24 op
710 98d3e6c1 2024-02-18 op if (ev_init() == -1)
711 98d3e6c1 2024-02-18 op exit(1);
712 c8dba1e6 2021-07-24 op
713 c8dba1e6 2021-07-24 op /* Setup pipe and event handler to the main process */
714 c8dba1e6 2021-07-24 op if ((iev_ui = malloc(sizeof(*iev_ui))) == NULL)
715 c8dba1e6 2021-07-24 op die();
716 c8dba1e6 2021-07-24 op imsg_init(&iev_ui->ibuf, 3);
717 c8dba1e6 2021-07-24 op iev_ui->handler = handle_dispatch_imsg;
718 c8dba1e6 2021-07-24 op iev_ui->events = EV_READ;
719 98d3e6c1 2024-02-18 op ev_add(iev_ui->ibuf.fd, iev_ui->events, iev_ui->handler, iev_ui);
720 c8dba1e6 2021-07-24 op
721 c8dba1e6 2021-07-24 op sandbox_net_process();
722 c8dba1e6 2021-07-24 op
723 98d3e6c1 2024-02-18 op ev_loop();
724 74c0f6ba 2021-07-24 op
725 74c0f6ba 2021-07-24 op msgbuf_clear(&iev_ui->ibuf.w);
726 74c0f6ba 2021-07-24 op close(iev_ui->ibuf.fd);
727 74c0f6ba 2021-07-24 op free(iev_ui);
728 74c0f6ba 2021-07-24 op
729 c8dba1e6 2021-07-24 op return 0;
730 c8dba1e6 2021-07-24 op }