xref: /openbsd/usr.sbin/relayd/relay.c (revision 92388dee)
1 /*	$OpenBSD: relay.c,v 1.260 2024/10/28 19:56:18 tb Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/time.h>
22 #include <sys/socket.h>
23 #include <sys/tree.h>
24 
25 #include <netinet/in.h>
26 #include <netinet/tcp.h>
27 #include <arpa/inet.h>
28 
29 #include <limits.h>
30 #include <netdb.h>
31 #include <poll.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <event.h>
39 #include <siphash.h>
40 #include <imsg.h>
41 
42 #include <tls.h>
43 
44 #include "relayd.h"
45 
46 #define MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
47 
48 void		 relay_statistics(int, short, void *);
49 int		 relay_dispatch_parent(int, struct privsep_proc *,
50 		    struct imsg *);
51 int		 relay_dispatch_pfe(int, struct privsep_proc *,
52 		    struct imsg *);
53 int		 relay_dispatch_ca(int, struct privsep_proc *,
54 		    struct imsg *);
55 int		 relay_dispatch_hce(int, struct privsep_proc *,
56 		    struct imsg *);
57 void		 relay_shutdown(void);
58 
59 void		 relay_protodebug(struct relay *);
60 void		 relay_ruledebug(struct relay_rule *);
61 void		 relay_init(struct privsep *, struct privsep_proc *p, void *);
62 void		 relay_launch(void);
63 int		 relay_socket(struct sockaddr_storage *, in_port_t,
64 		    struct protocol *, int, int);
65 int		 relay_socket_listen(struct sockaddr_storage *, in_port_t,
66 		    struct protocol *);
67 int		 relay_socket_connect(struct sockaddr_storage *, in_port_t,
68 		    struct protocol *, int);
69 
70 void		 relay_accept(int, short, void *);
71 void		 relay_input(struct rsession *);
72 
73 void		 relay_hash_addr(SIPHASH_CTX *, struct sockaddr_storage *, int);
74 
75 int		 relay_tls_ctx_create(struct relay *);
76 void		 relay_tls_transaction(struct rsession *,
77 		    struct ctl_relay_event *);
78 void		 relay_tls_handshake(int, short, void *);
79 void		 relay_tls_connected(struct ctl_relay_event *);
80 void		 relay_tls_readcb(int, short, void *);
81 void		 relay_tls_writecb(int, short, void *);
82 
83 void		 relay_connect_retry(int, short, void *);
84 void		 relay_connect_state(struct rsession *,
85 		    struct ctl_relay_event *, enum relay_state);
86 
87 extern void	 bufferevent_read_pressure_cb(struct evbuffer *, size_t,
88 		    size_t, void *);
89 
90 volatile int relay_sessions;
91 volatile int relay_inflight = 0;
92 objid_t relay_conid;
93 
94 static struct relayd		*env = NULL;
95 
96 static struct privsep_proc procs[] = {
97 	{ "parent",	PROC_PARENT,	relay_dispatch_parent },
98 	{ "pfe",	PROC_PFE,	relay_dispatch_pfe },
99 	{ "ca",		PROC_CA,	relay_dispatch_ca },
100 	{ "hce",	PROC_HCE,	relay_dispatch_hce },
101 };
102 
103 void
relay(struct privsep * ps,struct privsep_proc * p)104 relay(struct privsep *ps, struct privsep_proc *p)
105 {
106 	env = ps->ps_env;
107 	proc_run(ps, p, procs, nitems(procs), relay_init, NULL);
108 	relay_http(env);
109 }
110 
111 void
relay_shutdown(void)112 relay_shutdown(void)
113 {
114 	config_purge(env, CONFIG_ALL);
115 	usleep(200);	/* XXX relay needs to shutdown last */
116 }
117 
118 void
relay_ruledebug(struct relay_rule * rule)119 relay_ruledebug(struct relay_rule *rule)
120 {
121 	struct kv	*kv = NULL;
122 	u_int		 i;
123 	char		 buf[NI_MAXHOST];
124 
125 	fprintf(stderr, "\t\t");
126 
127 	switch (rule->rule_action) {
128 	case RULE_ACTION_MATCH:
129 		fprintf(stderr, "match ");
130 		break;
131 	case RULE_ACTION_BLOCK:
132 		fprintf(stderr, "block ");
133 		break;
134 	case RULE_ACTION_PASS:
135 		fprintf(stderr, "pass ");
136 		break;
137 	}
138 
139 	switch (rule->rule_dir) {
140 	case RELAY_DIR_ANY:
141 		break;
142 	case RELAY_DIR_REQUEST:
143 		fprintf(stderr, "request ");
144 		break;
145 	case RELAY_DIR_RESPONSE:
146 		fprintf(stderr, "response ");
147 		break;
148 	default:
149 		return;
150 		/* NOTREACHED */
151 		break;
152 	}
153 
154 	if (rule->rule_flags & RULE_FLAG_QUICK)
155 		fprintf(stderr, "quick ");
156 
157 	switch (rule->rule_af) {
158 	case AF_INET:
159 		fprintf(stderr, "inet ");
160 		break;
161 	case AF_INET6:
162 		fprintf(stderr, "inet6 ");
163 		break;
164 	}
165 
166 	if (rule->rule_src.addr.ss_family != AF_UNSPEC)
167 		fprintf(stderr, "from %s/%d ",
168 		    print_host(&rule->rule_src.addr, buf, sizeof(buf)),
169 		    rule->rule_src.addr_mask);
170 
171 	if (rule->rule_dst.addr.ss_family != AF_UNSPEC)
172 		fprintf(stderr, "to %s/%d ",
173 		    print_host(&rule->rule_dst.addr, buf, sizeof(buf)),
174 		    rule->rule_dst.addr_mask);
175 
176 	for (i = 1; i < KEY_TYPE_MAX; i++) {
177 		kv = &rule->rule_kv[i];
178 		if (kv->kv_type != i)
179 			continue;
180 
181 		switch (kv->kv_type) {
182 		case KEY_TYPE_COOKIE:
183 			fprintf(stderr, "cookie ");
184 			break;
185 		case KEY_TYPE_HEADER:
186 			fprintf(stderr, "header ");
187 			break;
188 		case KEY_TYPE_PATH:
189 			fprintf(stderr, "path ");
190 			break;
191 		case KEY_TYPE_QUERY:
192 			fprintf(stderr, "query ");
193 			break;
194 		case KEY_TYPE_URL:
195 			fprintf(stderr, "url ");
196 			break;
197 		default:
198 			continue;
199 		}
200 
201 		switch (kv->kv_option) {
202 		case KEY_OPTION_APPEND:
203 			fprintf(stderr, "append ");
204 			break;
205 		case KEY_OPTION_SET:
206 			fprintf(stderr, "set ");
207 			break;
208 		case KEY_OPTION_REMOVE:
209 			fprintf(stderr, "remove ");
210 			break;
211 		case KEY_OPTION_HASH:
212 			fprintf(stderr, "hash ");
213 			break;
214 		case KEY_OPTION_LOG:
215 			fprintf(stderr, "log ");
216 			break;
217 		case KEY_OPTION_STRIP:
218 			fprintf(stderr, "strip ");
219 			break;
220 		case KEY_OPTION_NONE:
221 			break;
222 		}
223 
224 		switch (kv->kv_digest) {
225 		case DIGEST_SHA1:
226 		case DIGEST_MD5:
227 			fprintf(stderr, "digest ");
228 			break;
229 		default:
230 			break;
231 		}
232 
233 		int kvv = (kv->kv_option == KEY_OPTION_STRIP ||
234 		     kv->kv_value == NULL);
235 		fprintf(stderr, "%s%s%s%s%s%s ",
236 		    kv->kv_key == NULL ? "" : "\"",
237 		    kv->kv_key == NULL ? "" : kv->kv_key,
238 		    kv->kv_key == NULL ? "" : "\"",
239 		    kvv ? "" : " value \"",
240 		    kv->kv_value == NULL ? "" : kv->kv_value,
241 		    kvv ? "" : "\"");
242 	}
243 
244 	if (rule->rule_tablename[0])
245 		fprintf(stderr, "forward to <%s> ", rule->rule_tablename);
246 
247 	if (rule->rule_tag == -1)
248 		fprintf(stderr, "no tag ");
249 	else if (rule->rule_tag && rule->rule_tagname[0])
250 		fprintf(stderr, "tag \"%s\" ",
251 		    rule->rule_tagname);
252 
253 	if (rule->rule_tagged && rule->rule_taggedname[0])
254 		fprintf(stderr, "tagged \"%s\" ",
255 		    rule->rule_taggedname);
256 
257 	if (rule->rule_label == -1)
258 		fprintf(stderr, "no label ");
259 	else if (rule->rule_label && rule->rule_labelname[0])
260 		fprintf(stderr, "label \"%s\" ",
261 		    rule->rule_labelname);
262 
263 	fprintf(stderr, "\n");
264 }
265 
266 void
relay_protodebug(struct relay * rlay)267 relay_protodebug(struct relay *rlay)
268 {
269 	struct protocol		*proto = rlay->rl_proto;
270 	struct relay_rule	*rule = NULL;
271 
272 	fprintf(stderr, "protocol %d: name %s\n",
273 	    proto->id, proto->name);
274 	fprintf(stderr, "\tflags: %s, relay flags: %s\n",
275 	    printb_flags(proto->flags, F_BITS),
276 	    printb_flags(rlay->rl_conf.flags, F_BITS));
277 	if (proto->tcpflags)
278 		fprintf(stderr, "\ttcp flags: %s\n",
279 		    printb_flags(proto->tcpflags, TCPFLAG_BITS));
280 	if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) && proto->tlsflags)
281 		fprintf(stderr, "\ttls flags: %s\n",
282 		    printb_flags(proto->tlsflags, TLSFLAG_BITS));
283 	fprintf(stderr, "\ttls session tickets: %s\n",
284 	    (proto->tickets == 1) ? "enabled" : "disabled");
285 	fprintf(stderr, "\ttype: ");
286 	switch (proto->type) {
287 	case RELAY_PROTO_TCP:
288 		fprintf(stderr, "tcp\n");
289 		break;
290 	case RELAY_PROTO_HTTP:
291 		fprintf(stderr, "http\n");
292 		break;
293 	case RELAY_PROTO_DNS:
294 		fprintf(stderr, "dns\n");
295 		break;
296 	}
297 
298 	rule = TAILQ_FIRST(&proto->rules);
299 	while (rule != NULL) {
300 		relay_ruledebug(rule);
301 		rule = TAILQ_NEXT(rule, rule_entry);
302 	}
303 }
304 
305 int
relay_privinit(struct relay * rlay)306 relay_privinit(struct relay *rlay)
307 {
308 	log_debug("%s: adding relay %s", __func__, rlay->rl_conf.name);
309 
310 	if (log_getverbose() > 1)
311 		relay_protodebug(rlay);
312 
313 	switch (rlay->rl_proto->type) {
314 	case RELAY_PROTO_DNS:
315 		relay_udp_privinit(rlay);
316 		break;
317 	case RELAY_PROTO_TCP:
318 		break;
319 	case RELAY_PROTO_HTTP:
320 		break;
321 	}
322 
323 	if (rlay->rl_conf.flags & F_UDP)
324 		rlay->rl_s = relay_udp_bind(&rlay->rl_conf.ss,
325 		    rlay->rl_conf.port, rlay->rl_proto);
326 	else
327 		rlay->rl_s = relay_socket_listen(&rlay->rl_conf.ss,
328 		    rlay->rl_conf.port, rlay->rl_proto);
329 	if (rlay->rl_s == -1)
330 		return (-1);
331 
332 	return (0);
333 }
334 
335 void
relay_init(struct privsep * ps,struct privsep_proc * p,void * arg)336 relay_init(struct privsep *ps, struct privsep_proc *p, void *arg)
337 {
338 	struct timeval	 tv;
339 
340 	if (config_init(ps->ps_env) == -1)
341 		fatal("failed to initialize configuration");
342 
343 	/* We use a custom shutdown callback */
344 	p->p_shutdown = relay_shutdown;
345 
346 	/* Unlimited file descriptors (use system limits) */
347 	socket_rlimit(-1);
348 
349 	if (pledge("stdio recvfd inet", NULL) == -1)
350 		fatal("pledge");
351 
352 	/* Schedule statistics timer */
353 	evtimer_set(&env->sc_statev, relay_statistics, ps);
354 	bcopy(&env->sc_conf.statinterval, &tv, sizeof(tv));
355 	evtimer_add(&env->sc_statev, &tv);
356 }
357 
358 void
relay_session_publish(struct rsession * s)359 relay_session_publish(struct rsession *s)
360 {
361 	proc_compose(env->sc_ps, PROC_PFE, IMSG_SESS_PUBLISH, s, sizeof(*s));
362 }
363 
364 void
relay_session_unpublish(struct rsession * s)365 relay_session_unpublish(struct rsession *s)
366 {
367 	proc_compose(env->sc_ps, PROC_PFE, IMSG_SESS_UNPUBLISH,
368 	    &s->se_id, sizeof(s->se_id));
369 }
370 
371 void
relay_statistics(int fd,short events,void * arg)372 relay_statistics(int fd, short events, void *arg)
373 {
374 	struct privsep		*ps = arg;
375 	struct relay		*rlay;
376 	struct ctl_stats	 crs, *cur;
377 	struct timeval		 tv, tv_now;
378 	int			 resethour = 0, resetday = 0;
379 	struct rsession		*con, *next_con;
380 
381 	/*
382 	 * This is a hack to calculate some average statistics.
383 	 * It doesn't try to be very accurate, but could be improved...
384 	 */
385 
386 	timerclear(&tv);
387 	getmonotime(&tv_now);
388 
389 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
390 		bzero(&crs, sizeof(crs));
391 		resethour = resetday = 0;
392 
393 		cur = &rlay->rl_stats[ps->ps_instance];
394 		cur->cnt += cur->last;
395 		cur->tick++;
396 		cur->avg = (cur->last + cur->avg) / 2;
397 		cur->last_hour += cur->last;
398 		if ((cur->tick %
399 		    (3600 / env->sc_conf.statinterval.tv_sec)) == 0) {
400 			cur->avg_hour = (cur->last_hour + cur->avg_hour) / 2;
401 			resethour++;
402 		}
403 		cur->last_day += cur->last;
404 		if ((cur->tick %
405 		    (86400 / env->sc_conf.statinterval.tv_sec)) == 0) {
406 			cur->avg_day = (cur->last_day + cur->avg_day) / 2;
407 			resethour++;
408 		}
409 		bcopy(cur, &crs, sizeof(crs));
410 
411 		cur->last = 0;
412 		if (resethour)
413 			cur->last_hour = 0;
414 		if (resetday)
415 			cur->last_day = 0;
416 
417 		crs.id = rlay->rl_conf.id;
418 		crs.proc = ps->ps_instance;
419 		proc_compose(env->sc_ps, PROC_PFE, IMSG_STATISTICS,
420 		    &crs, sizeof(crs));
421 
422 		for (con = SPLAY_ROOT(&rlay->rl_sessions);
423 		    con != NULL; con = next_con) {
424 			next_con = SPLAY_NEXT(session_tree,
425 			    &rlay->rl_sessions, con);
426 			timersub(&tv_now, &con->se_tv_last, &tv);
427 			if (timercmp(&tv, &rlay->rl_conf.timeout, >=))
428 				relay_close(con, "hard timeout", 1);
429 		}
430 	}
431 
432 	/* Schedule statistics timer */
433 	evtimer_set(&env->sc_statev, relay_statistics, ps);
434 	bcopy(&env->sc_conf.statinterval, &tv, sizeof(tv));
435 	evtimer_add(&env->sc_statev, &tv);
436 }
437 
438 void
relay_launch(void)439 relay_launch(void)
440 {
441 	void			(*callback)(int, short, void *);
442 	struct relay		*rlay;
443 	struct host		*host;
444 	struct relay_table	*rlt;
445 
446 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
447 		if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) &&
448 		    relay_tls_ctx_create(rlay) == -1)
449 			fatalx("%s: failed to create TLS context", __func__);
450 
451 		TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
452 			/*
453 			 * set rule->rule_table in advance and save time
454 			 * looking up for this later on rule/connection
455 			 * evalution
456 			 */
457 			rule_settable(&rlay->rl_proto->rules, rlt);
458 
459 			rlt->rlt_index = 0;
460 			rlt->rlt_nhosts = 0;
461 			TAILQ_FOREACH(host, &rlt->rlt_table->hosts, entry) {
462 				if (rlt->rlt_nhosts >= RELAY_MAXHOSTS)
463 					fatal("%s: too many hosts in table",
464 					    __func__);
465 				host->idx = rlt->rlt_nhosts;
466 				rlt->rlt_host[rlt->rlt_nhosts++] = host;
467 			}
468 			log_info("adding %d hosts from table %s%s",
469 			    rlt->rlt_nhosts, rlt->rlt_table->conf.name,
470 			    rlt->rlt_table->conf.check ? "" : " (no check)");
471 		}
472 
473 		switch (rlay->rl_proto->type) {
474 		case RELAY_PROTO_DNS:
475 			relay_udp_init(env, rlay);
476 			break;
477 		case RELAY_PROTO_TCP:
478 		case RELAY_PROTO_HTTP:
479 			relay_http_init(rlay);
480 			/* Use defaults */
481 			break;
482 		}
483 
484 		log_debug("%s: running relay %s", __func__,
485 		    rlay->rl_conf.name);
486 
487 		rlay->rl_up = HOST_UP;
488 
489 		if (rlay->rl_conf.flags & F_UDP)
490 			callback = relay_udp_server;
491 		else
492 			callback = relay_accept;
493 
494 		event_set(&rlay->rl_ev, rlay->rl_s, EV_READ,
495 		    callback, rlay);
496 		event_add(&rlay->rl_ev, NULL);
497 		evtimer_set(&rlay->rl_evt, callback, rlay);
498 	}
499 }
500 
501 int
relay_socket_af(struct sockaddr_storage * ss,in_port_t port)502 relay_socket_af(struct sockaddr_storage *ss, in_port_t port)
503 {
504 	switch (ss->ss_family) {
505 	case AF_INET:
506 		((struct sockaddr_in *)ss)->sin_port = port;
507 		((struct sockaddr_in *)ss)->sin_len =
508 		    sizeof(struct sockaddr_in);
509 		break;
510 	case AF_INET6:
511 		((struct sockaddr_in6 *)ss)->sin6_port = port;
512 		((struct sockaddr_in6 *)ss)->sin6_len =
513 		    sizeof(struct sockaddr_in6);
514 		break;
515 	default:
516 		return (-1);
517 	}
518 
519 	return (0);
520 }
521 
522 in_port_t
relay_socket_getport(struct sockaddr_storage * ss)523 relay_socket_getport(struct sockaddr_storage *ss)
524 {
525 	switch (ss->ss_family) {
526 	case AF_INET:
527 		return (((struct sockaddr_in *)ss)->sin_port);
528 	case AF_INET6:
529 		return (((struct sockaddr_in6 *)ss)->sin6_port);
530 	default:
531 		return (0);
532 	}
533 
534 	/* NOTREACHED */
535 	return (0);
536 }
537 
538 int
relay_socket(struct sockaddr_storage * ss,in_port_t port,struct protocol * proto,int fd,int reuseport)539 relay_socket(struct sockaddr_storage *ss, in_port_t port,
540     struct protocol *proto, int fd, int reuseport)
541 {
542 	struct linger	lng;
543 	int		s = -1, val;
544 
545 	if (relay_socket_af(ss, port) == -1)
546 		goto bad;
547 
548 	s = fd == -1 ? socket(ss->ss_family,
549 	    SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP) : fd;
550 	if (s == -1)
551 		goto bad;
552 
553 	/*
554 	 * Socket options
555 	 */
556 	bzero(&lng, sizeof(lng));
557 	if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1)
558 		goto bad;
559 	if (reuseport) {
560 		val = 1;
561 		if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val,
562 			sizeof(int)) == -1)
563 			goto bad;
564 	}
565 	if (proto->tcpflags & TCPFLAG_BUFSIZ) {
566 		val = proto->tcpbufsiz;
567 		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
568 		    &val, sizeof(val)) == -1)
569 			goto bad;
570 		val = proto->tcpbufsiz;
571 		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
572 		    &val, sizeof(val)) == -1)
573 			goto bad;
574 	}
575 
576 	/*
577 	 * IP options
578 	 */
579 	if (proto->tcpflags & TCPFLAG_IPTTL) {
580 		val = (int)proto->tcpipttl;
581 		switch (ss->ss_family) {
582 		case AF_INET:
583 			if (setsockopt(s, IPPROTO_IP, IP_TTL,
584 			    &val, sizeof(val)) == -1)
585 				goto bad;
586 			break;
587 		case AF_INET6:
588 			if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
589 			    &val, sizeof(val)) == -1)
590 				goto bad;
591 			break;
592 		}
593 	}
594 	if (proto->tcpflags & TCPFLAG_IPMINTTL) {
595 		val = (int)proto->tcpipminttl;
596 		switch (ss->ss_family) {
597 		case AF_INET:
598 			if (setsockopt(s, IPPROTO_IP, IP_MINTTL,
599 			    &val, sizeof(val)) == -1)
600 				goto bad;
601 			break;
602 		case AF_INET6:
603 			if (setsockopt(s, IPPROTO_IPV6, IPV6_MINHOPCOUNT,
604 			    &val, sizeof(val)) == -1)
605 				goto bad;
606 			break;
607 		}
608 	}
609 
610 	/*
611 	 * TCP options
612 	 */
613 	if (proto->tcpflags & (TCPFLAG_NODELAY|TCPFLAG_NNODELAY)) {
614 		if (proto->tcpflags & TCPFLAG_NNODELAY)
615 			val = 0;
616 		else
617 			val = 1;
618 		if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
619 		    &val, sizeof(val)) == -1)
620 			goto bad;
621 	}
622 	if (proto->tcpflags & (TCPFLAG_SACK|TCPFLAG_NSACK)) {
623 		if (proto->tcpflags & TCPFLAG_NSACK)
624 			val = 0;
625 		else
626 			val = 1;
627 		if (setsockopt(s, IPPROTO_TCP, TCP_SACK_ENABLE,
628 		    &val, sizeof(val)) == -1)
629 			goto bad;
630 	}
631 
632 	return (s);
633 
634  bad:
635 	if (s != -1)
636 		close(s);
637 	return (-1);
638 }
639 
640 int
relay_socket_connect(struct sockaddr_storage * ss,in_port_t port,struct protocol * proto,int fd)641 relay_socket_connect(struct sockaddr_storage *ss, in_port_t port,
642     struct protocol *proto, int fd)
643 {
644 	int	s;
645 
646 	if ((s = relay_socket(ss, port, proto, fd, 0)) == -1)
647 		return (-1);
648 
649 	if (connect(s, (struct sockaddr *)ss, ss->ss_len) == -1) {
650 		if (errno != EINPROGRESS)
651 			goto bad;
652 	}
653 
654 	return (s);
655 
656  bad:
657 	close(s);
658 	return (-1);
659 }
660 
661 int
relay_socket_listen(struct sockaddr_storage * ss,in_port_t port,struct protocol * proto)662 relay_socket_listen(struct sockaddr_storage *ss, in_port_t port,
663     struct protocol *proto)
664 {
665 	int s;
666 
667 	if ((s = relay_socket(ss, port, proto, -1, 1)) == -1)
668 		return (-1);
669 
670 	if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1)
671 		goto bad;
672 	if (listen(s, proto->tcpbacklog) == -1)
673 		goto bad;
674 
675 	return (s);
676 
677  bad:
678 	close(s);
679 	return (-1);
680 }
681 
682 void
relay_connected(int fd,short sig,void * arg)683 relay_connected(int fd, short sig, void *arg)
684 {
685 	char			 obuf[128];
686 	struct rsession		*con = arg;
687 	struct relay		*rlay = con->se_relay;
688 	struct protocol		*proto = rlay->rl_proto;
689 	evbuffercb		 outrd = relay_read;
690 	evbuffercb		 outwr = relay_write;
691 	struct bufferevent	*bev;
692 	struct ctl_relay_event	*out = &con->se_out;
693 	char			*msg;
694 	socklen_t		 len;
695 	int			 error;
696 
697 	if (sig == EV_TIMEOUT) {
698 		relay_abort_http(con, 504, "connect timeout", 0);
699 		return;
700 	}
701 
702 	len = sizeof(error);
703 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
704 		relay_abort_http(con, 500, "getsockopt failed", 0);
705 		return;
706 	}
707 	if (error) {
708 		errno = error;
709 		if (asprintf(&msg, "socket error: %s",
710 		    strerror(error)) >= 0) {
711 			relay_abort_http(con, 500, msg, 0);
712 			free(msg);
713 			return;
714 		} else {
715 			relay_abort_http(con, 500,
716 			    "socket error and asprintf failed", 0);
717 			return;
718 		}
719 	}
720 
721 	if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->tls == NULL)) {
722 		relay_tls_transaction(con, out);
723 		return;
724 	}
725 
726 	DPRINTF("%s: session %d: successful", __func__, con->se_id);
727 
728 	/* Log destination if it was changed in a keep-alive connection */
729 	if ((con->se_table != con->se_table0) &&
730 	    (env->sc_conf.opts & (RELAYD_OPT_LOGCON|RELAYD_OPT_LOGCONERR))) {
731 		con->se_table0 = con->se_table;
732 		memset(&obuf, 0, sizeof(obuf));
733 		(void)print_host(&con->se_out.ss, obuf, sizeof(obuf));
734 		if (asprintf(&msg, " -> %s:%d",
735 		    obuf, ntohs(con->se_out.port)) == -1) {
736 			relay_abort_http(con, 500,
737 			    "connection changed and asprintf failed", 0);
738 			return;
739 		}
740 		relay_log(con, msg);
741 		free(msg);
742 	}
743 
744 	switch (rlay->rl_proto->type) {
745 	case RELAY_PROTO_HTTP:
746 		if (relay_httpdesc_init(out) == -1) {
747 			relay_close(con,
748 			    "failed to allocate http descriptor", 1);
749 			return;
750 		}
751 		con->se_out.toread = TOREAD_HTTP_HEADER;
752 		outrd = relay_read_http;
753 		break;
754 	case RELAY_PROTO_TCP:
755 		/* Use defaults */
756 		break;
757 	default:
758 		fatalx("%s: unknown protocol", __func__);
759 	}
760 
761 	/*
762 	 * Relay <-> Server
763 	 */
764 	bev = bufferevent_new(fd, outrd, outwr, relay_error, &con->se_out);
765 	if (bev == NULL) {
766 		relay_abort_http(con, 500,
767 		    "failed to allocate output buffer event", 0);
768 		return;
769 	}
770 	/* write pending output buffer now */
771 	if (bufferevent_write_buffer(bev, con->se_out.output)) {
772 		relay_abort_http(con, 500, strerror(errno), 0);
773 		return;
774 	}
775 	con->se_out.bev = bev;
776 
777 	/* Initialize the TLS wrapper */
778 	if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->tls != NULL))
779 		relay_tls_connected(out);
780 
781 	bufferevent_settimeout(bev,
782 	    rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec);
783 	bufferevent_setwatermark(bev, EV_WRITE,
784 		RELAY_MIN_PREFETCHED * proto->tcpbufsiz, 0);
785 	bufferevent_enable(bev, EV_READ|EV_WRITE);
786 	if (con->se_in.bev)
787 		bufferevent_enable(con->se_in.bev, EV_READ);
788 
789 	if (relay_splice(&con->se_out) == -1)
790 		relay_close(con, strerror(errno), 1);
791 }
792 
793 void
relay_input(struct rsession * con)794 relay_input(struct rsession *con)
795 {
796 	struct relay	*rlay = con->se_relay;
797 	struct protocol	*proto = rlay->rl_proto;
798 	evbuffercb	 inrd = relay_read;
799 	evbuffercb	 inwr = relay_write;
800 
801 	switch (rlay->rl_proto->type) {
802 	case RELAY_PROTO_HTTP:
803 		if (relay_http_priv_init(con) == -1) {
804 			relay_close(con,
805 			    "failed to allocate http descriptor", 1);
806 			return;
807 		}
808 		con->se_in.toread = TOREAD_HTTP_HEADER;
809 		inrd = relay_read_http;
810 		break;
811 	case RELAY_PROTO_TCP:
812 		/* Use defaults */
813 		break;
814 	default:
815 		fatalx("%s: unknown protocol", __func__);
816 	}
817 
818 	/*
819 	 * Client <-> Relay
820 	 */
821 	con->se_in.bev = bufferevent_new(con->se_in.s, inrd, inwr,
822 	    relay_error, &con->se_in);
823 	if (con->se_in.bev == NULL) {
824 		relay_close(con, "failed to allocate input buffer event", 1);
825 		return;
826 	}
827 
828 	/* Initialize the TLS wrapper */
829 	if ((rlay->rl_conf.flags & F_TLS) && con->se_in.tls != NULL)
830 		relay_tls_connected(&con->se_in);
831 
832 	bufferevent_settimeout(con->se_in.bev,
833 	    rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec);
834 	bufferevent_setwatermark(con->se_in.bev, EV_WRITE,
835 		RELAY_MIN_PREFETCHED * proto->tcpbufsiz, 0);
836 	bufferevent_enable(con->se_in.bev, EV_READ|EV_WRITE);
837 
838 	if (relay_splice(&con->se_in) == -1)
839 		relay_close(con, strerror(errno), 1);
840 }
841 
842 void
relay_write(struct bufferevent * bev,void * arg)843 relay_write(struct bufferevent *bev, void *arg)
844 {
845 	struct ctl_relay_event	*cre = arg;
846 	struct rsession		*con = cre->con;
847 
848 	getmonotime(&con->se_tv_last);
849 
850 	if (con->se_done && EVBUFFER_LENGTH(EVBUFFER_OUTPUT(bev)) == 0)
851 		goto done;
852 	if (cre->dst->bev)
853 		bufferevent_enable(cre->dst->bev, EV_READ);
854 	if (relay_splice(cre->dst) == -1)
855 		goto fail;
856 
857 	return;
858  done:
859 	relay_close(con, "last write (done)", 0);
860 	return;
861  fail:
862 	relay_close(con, strerror(errno), 1);
863 }
864 
865 void
relay_dump(struct ctl_relay_event * cre,const void * buf,size_t len)866 relay_dump(struct ctl_relay_event *cre, const void *buf, size_t len)
867 {
868 	if (!len)
869 		return;
870 
871 	/*
872 	 * This function will dump the specified message directly
873 	 * to the underlying session, without waiting for success
874 	 * of non-blocking events etc. This is useful to print an
875 	 * error message before gracefully closing the session.
876 	 */
877 	if (cre->tls != NULL)
878 		(void)tls_write(cre->tls, buf, len);
879 	else
880 		(void)write(cre->s, buf, len);
881 }
882 
883 void
relay_read(struct bufferevent * bev,void * arg)884 relay_read(struct bufferevent *bev, void *arg)
885 {
886 	struct ctl_relay_event	*cre = arg;
887 	struct rsession		*con = cre->con;
888 	struct protocol		*proto = con->se_relay->rl_proto;
889 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
890 
891 	getmonotime(&con->se_tv_last);
892 	cre->timedout = 0;
893 
894 	if (!EVBUFFER_LENGTH(src))
895 		return;
896 	if (relay_bufferevent_write_buffer(cre->dst, src) == -1)
897 		goto fail;
898 	if (con->se_done)
899 		goto done;
900 	if (cre->dst->bev)
901 		bufferevent_enable(cre->dst->bev, EV_READ);
902 	if (cre->dst->bev && EVBUFFER_LENGTH(EVBUFFER_OUTPUT(cre->dst->bev)) >
903 	    (size_t)RELAY_MAX_PREFETCH * proto->tcpbufsiz)
904 		bufferevent_disable(bev, EV_READ);
905 
906 	return;
907  done:
908 	relay_close(con, "last read (done)", 0);
909 	return;
910  fail:
911 	relay_close(con, strerror(errno), 1);
912 }
913 
914 /*
915  * Splice sockets from cre to cre->dst if applicable.  Returns:
916  * -1 socket splicing has failed
917  * 0 socket splicing is currently not possible
918  * 1 socket splicing was successful
919  */
920 int
relay_splice(struct ctl_relay_event * cre)921 relay_splice(struct ctl_relay_event *cre)
922 {
923 	struct rsession		*con = cre->con;
924 	struct relay		*rlay = con->se_relay;
925 	struct protocol		*proto = rlay->rl_proto;
926 	struct splice		 sp;
927 
928 	if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) ||
929 	    (proto->tcpflags & TCPFLAG_NSPLICE))
930 		return (0);
931 
932 	if (cre->splicelen >= 0)
933 		return (0);
934 
935 	/* still not connected */
936 	if (cre->bev == NULL || cre->dst->bev == NULL)
937 		return (0);
938 
939 	if (!(cre->toread == TOREAD_UNLIMITED || cre->toread > 0)) {
940 		DPRINTF("%s: session %d: splice dir %d, nothing to read %lld",
941 		    __func__, con->se_id, cre->dir, cre->toread);
942 		return (0);
943 	}
944 
945 	/* do not splice before buffers have not been completely flushed */
946 	if (EVBUFFER_LENGTH(cre->bev->input) ||
947 	    EVBUFFER_LENGTH(cre->dst->bev->output)) {
948 		DPRINTF("%s: session %d: splice dir %d, dirty buffer",
949 		    __func__, con->se_id, cre->dir);
950 		bufferevent_disable(cre->bev, EV_READ);
951 		return (0);
952 	}
953 
954 	bzero(&sp, sizeof(sp));
955 	sp.sp_fd = cre->dst->s;
956 	sp.sp_max = cre->toread > 0 ? cre->toread : 0;
957 	bcopy(&rlay->rl_conf.timeout, &sp.sp_idle, sizeof(sp.sp_idle));
958 	if (setsockopt(cre->s, SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp)) == -1) {
959 		log_debug("%s: session %d: splice dir %d failed: %s",
960 		    __func__, con->se_id, cre->dir, strerror(errno));
961 		return (-1);
962 	}
963 	cre->splicelen = 0;
964 	bufferevent_enable(cre->bev, EV_READ);
965 
966 	DPRINTF("%s: session %d: splice dir %d, maximum %lld, successful",
967 	    __func__, con->se_id, cre->dir, cre->toread);
968 
969 	return (1);
970 }
971 
972 int
relay_splicelen(struct ctl_relay_event * cre)973 relay_splicelen(struct ctl_relay_event *cre)
974 {
975 	struct rsession		*con = cre->con;
976 	off_t			 len;
977 	socklen_t		 optlen;
978 
979 	if (cre->splicelen < 0)
980 		return (0);
981 
982 	optlen = sizeof(len);
983 	if (getsockopt(cre->s, SOL_SOCKET, SO_SPLICE, &len, &optlen) == -1) {
984 		log_debug("%s: session %d: splice dir %d get length failed: %s",
985 		    __func__, con->se_id, cre->dir, strerror(errno));
986 		return (-1);
987 	}
988 
989 	DPRINTF("%s: session %d: splice dir %d, length %lld",
990 	    __func__, con->se_id, cre->dir, len);
991 
992 	if (len > cre->splicelen) {
993 		getmonotime(&con->se_tv_last);
994 
995 		cre->splicelen = len;
996 		return (1);
997 	}
998 
999 	return (0);
1000 }
1001 
1002 int
relay_spliceadjust(struct ctl_relay_event * cre)1003 relay_spliceadjust(struct ctl_relay_event *cre)
1004 {
1005 	if (cre->splicelen < 0)
1006 		return (0);
1007 	if (relay_splicelen(cre) == -1)
1008 		return (-1);
1009 	if (cre->splicelen > 0 && cre->toread > 0)
1010 		cre->toread -= cre->splicelen;
1011 	cre->splicelen = -1;
1012 
1013 	return (0);
1014 }
1015 
1016 void
relay_error(struct bufferevent * bev,short error,void * arg)1017 relay_error(struct bufferevent *bev, short error, void *arg)
1018 {
1019 	struct ctl_relay_event	*cre = arg;
1020 	struct rsession		*con = cre->con;
1021 	struct evbuffer		*dst;
1022 
1023 	DPRINTF("%s: session %d: dir %d state %d to read %lld event error %x",
1024 		__func__, con->se_id, cre->dir, cre->state, cre->toread, error);
1025 	if (error & EVBUFFER_TIMEOUT) {
1026 		if (cre->splicelen >= 0) {
1027 			bufferevent_enable(bev, EV_READ);
1028 		} else if (cre->dst->splicelen >= 0) {
1029 			switch (relay_splicelen(cre->dst)) {
1030 			case -1:
1031 				goto fail;
1032 			case 0:
1033 				relay_close(con, "buffer event timeout", 1);
1034 				break;
1035 			case 1:
1036 				cre->timedout = 1;
1037 				bufferevent_enable(bev, EV_READ);
1038 				break;
1039 			}
1040 		} else {
1041 			relay_close(con, "buffer event timeout", 1);
1042 		}
1043 		return;
1044 	}
1045 	if (error & EVBUFFER_ERROR && errno == ETIMEDOUT) {
1046 		if (cre->dst->splicelen >= 0) {
1047 			switch (relay_splicelen(cre->dst)) {
1048 			case -1:
1049 				goto fail;
1050 			case 0:
1051 				relay_close(con, "splice timeout", 1);
1052 				return;
1053 			case 1:
1054 				bufferevent_enable(bev, EV_READ);
1055 				break;
1056 			}
1057 		} else if (cre->dst->timedout) {
1058 			relay_close(con, "splice timeout", 1);
1059 			return;
1060 		}
1061 		if (relay_spliceadjust(cre) == -1)
1062 			goto fail;
1063 		if (relay_splice(cre) == -1)
1064 			goto fail;
1065 		return;
1066 	}
1067 	if (error & EVBUFFER_ERROR && errno == EFBIG) {
1068 		if (relay_spliceadjust(cre) == -1)
1069 			goto fail;
1070 		bufferevent_enable(cre->bev, EV_READ);
1071 		return;
1072 	}
1073 	if (error & (EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF)) {
1074 		bufferevent_disable(bev, EV_READ|EV_WRITE);
1075 
1076 		con->se_done = 1;
1077 		if (cre->dst->bev != NULL) {
1078 			dst = EVBUFFER_OUTPUT(cre->dst->bev);
1079 			if (EVBUFFER_LENGTH(dst))
1080 				return;
1081 		} else if (cre->toread == TOREAD_UNLIMITED || cre->toread == 0)
1082 			return;
1083 
1084 		relay_close(con, "done", 0);
1085 		return;
1086 	}
1087 	relay_close(con, "buffer event error", 1);
1088 	return;
1089  fail:
1090 	relay_close(con, strerror(errno), 1);
1091 }
1092 
1093 void
relay_accept(int fd,short event,void * arg)1094 relay_accept(int fd, short event, void *arg)
1095 {
1096 	struct privsep		*ps = env->sc_ps;
1097 	struct relay		*rlay = arg;
1098 	struct rsession		*con = NULL;
1099 	struct ctl_natlook	*cnl = NULL;
1100 	socklen_t		 slen;
1101 	struct timeval		 tv;
1102 	struct sockaddr_storage	 ss;
1103 	int			 s = -1;
1104 
1105 	event_add(&rlay->rl_ev, NULL);
1106 	if ((event & EV_TIMEOUT))
1107 		return;
1108 
1109 	slen = sizeof(ss);
1110 	if ((s = accept_reserve(fd, (struct sockaddr *)&ss,
1111 	    &slen, FD_RESERVE, &relay_inflight)) == -1) {
1112 		/*
1113 		 * Pause accept if we are out of file descriptors, or
1114 		 * libevent will haunt us here too.
1115 		 */
1116 		if (errno == ENFILE || errno == EMFILE) {
1117 			struct timeval evtpause = { 1, 0 };
1118 
1119 			event_del(&rlay->rl_ev);
1120 			evtimer_add(&rlay->rl_evt, &evtpause);
1121 			log_debug("%s: deferring connections", __func__);
1122 		}
1123 		return;
1124 	}
1125 	if (rlay->rl_conf.flags & F_DISABLE)
1126 		goto err;
1127 
1128 	if ((con = calloc(1, sizeof(*con))) == NULL)
1129 		goto err;
1130 
1131 	/* Pre-allocate log buffer */
1132 	con->se_haslog = 0;
1133 	con->se_log = evbuffer_new();
1134 	if (con->se_log == NULL)
1135 		goto err;
1136 
1137 	con->se_in.s = s;
1138 	con->se_in.tls = NULL;
1139 	con->se_out.s = -1;
1140 	con->se_out.tls = NULL;
1141 	con->se_in.dst = &con->se_out;
1142 	con->se_out.dst = &con->se_in;
1143 	con->se_in.con = con;
1144 	con->se_out.con = con;
1145 	con->se_in.splicelen = -1;
1146 	con->se_out.splicelen = -1;
1147 	con->se_in.toread = TOREAD_UNLIMITED;
1148 	con->se_out.toread = TOREAD_UNLIMITED;
1149 	con->se_relay = rlay;
1150 	con->se_id = ++relay_conid;
1151 	con->se_relayid = rlay->rl_conf.id;
1152 	con->se_pid = getpid();
1153 	con->se_in.dir = RELAY_DIR_REQUEST;
1154 	con->se_out.dir = RELAY_DIR_RESPONSE;
1155 	con->se_retry = rlay->rl_conf.dstretry;
1156 	con->se_bnds = -1;
1157 	con->se_out.port = rlay->rl_conf.dstport;
1158 	switch (ss.ss_family) {
1159 	case AF_INET:
1160 		con->se_in.port = ((struct sockaddr_in *)&ss)->sin_port;
1161 		break;
1162 	case AF_INET6:
1163 		con->se_in.port = ((struct sockaddr_in6 *)&ss)->sin6_port;
1164 		break;
1165 	}
1166 	memcpy(&con->se_in.ss, &ss, sizeof(con->se_in.ss));
1167 
1168 	slen = sizeof(con->se_sockname);
1169 	if (getsockname(s, (struct sockaddr *)&con->se_sockname, &slen) == -1) {
1170 		relay_close(con, "sockname lookup failed", 1);
1171 		return;
1172 	}
1173 
1174 	getmonotime(&con->se_tv_start);
1175 	bcopy(&con->se_tv_start, &con->se_tv_last, sizeof(con->se_tv_last));
1176 
1177 	if (rlay->rl_conf.flags & F_HASHKEY) {
1178 		SipHash24_Init(&con->se_siphashctx,
1179 		    &rlay->rl_conf.hashkey.siphashkey);
1180 	}
1181 
1182 	relay_sessions++;
1183 	SPLAY_INSERT(session_tree, &rlay->rl_sessions, con);
1184 	relay_session_publish(con);
1185 
1186 	/* Increment the per-relay session counter */
1187 	rlay->rl_stats[ps->ps_instance].last++;
1188 
1189 	/* Pre-allocate output buffer */
1190 	con->se_out.output = evbuffer_new();
1191 	if (con->se_out.output == NULL) {
1192 		relay_close(con, "failed to allocate output buffer", 1);
1193 		return;
1194 	}
1195 
1196 	if (rlay->rl_conf.flags & F_DIVERT) {
1197 		memcpy(&con->se_out.ss, &con->se_sockname,
1198 		    sizeof(con->se_out.ss));
1199 		con->se_out.port = relay_socket_getport(&con->se_out.ss);
1200 
1201 		/* Detect loop and fall back to the alternate forward target */
1202 		if (bcmp(&rlay->rl_conf.ss, &con->se_out.ss,
1203 		    sizeof(con->se_out.ss)) == 0 &&
1204 		    con->se_out.port == rlay->rl_conf.port)
1205 			con->se_out.ss.ss_family = AF_UNSPEC;
1206 	} else if (rlay->rl_conf.flags & F_NATLOOK) {
1207 		if ((cnl = calloc(1, sizeof(*cnl))) == NULL) {
1208 			relay_close(con, "failed to allocate nat lookup", 1);
1209 			return;
1210 		}
1211 
1212 		con->se_cnl = cnl;
1213 		bzero(cnl, sizeof(*cnl));
1214 		cnl->in = -1;
1215 		cnl->id = con->se_id;
1216 		cnl->proc = ps->ps_instance;
1217 		cnl->proto = IPPROTO_TCP;
1218 
1219 		memcpy(&cnl->src, &con->se_in.ss, sizeof(cnl->src));
1220 		memcpy(&cnl->dst, &con->se_sockname, sizeof(cnl->dst));
1221 
1222 		proc_compose(env->sc_ps, PROC_PFE, IMSG_NATLOOK,
1223 		    cnl, sizeof(*cnl));
1224 
1225 		/* Schedule timeout */
1226 		evtimer_set(&con->se_ev, relay_natlook, con);
1227 		bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv));
1228 		evtimer_add(&con->se_ev, &tv);
1229 		return;
1230 	}
1231 
1232 	if (rlay->rl_conf.flags & F_TLSINSPECT) {
1233 		relay_preconnect(con);
1234 		return;
1235 	}
1236 
1237 	relay_session(con);
1238 	return;
1239  err:
1240 	if (s != -1) {
1241 		close(s);
1242 		free(con);
1243 		/*
1244 		 * the session struct was not completely set up, but still
1245 		 * counted as an inflight session. account for this.
1246 		 */
1247 		relay_inflight--;
1248 		log_debug("%s: inflight decremented, now %d",
1249 		    __func__, relay_inflight);
1250 	}
1251 }
1252 
1253 void
relay_hash_addr(SIPHASH_CTX * ctx,struct sockaddr_storage * ss,int portset)1254 relay_hash_addr(SIPHASH_CTX *ctx, struct sockaddr_storage *ss, int portset)
1255 {
1256 	struct sockaddr_in	*sin4;
1257 	struct sockaddr_in6	*sin6;
1258 	in_port_t		 port;
1259 
1260 	if (ss->ss_family == AF_INET) {
1261 		sin4 = (struct sockaddr_in *)ss;
1262 		SipHash24_Update(ctx, &sin4->sin_addr,
1263 		    sizeof(struct in_addr));
1264 	} else {
1265 		sin6 = (struct sockaddr_in6 *)ss;
1266 		SipHash24_Update(ctx, &sin6->sin6_addr,
1267 		    sizeof(struct in6_addr));
1268 	}
1269 
1270 	if (portset != -1) {
1271 		port = (in_port_t)portset;
1272 		SipHash24_Update(ctx, &port, sizeof(port));
1273 	}
1274 }
1275 
1276 int
relay_from_table(struct rsession * con)1277 relay_from_table(struct rsession *con)
1278 {
1279 	struct relay		*rlay = con->se_relay;
1280 	struct host		*host = NULL;
1281 	struct relay_table	*rlt = NULL;
1282 	struct table		*table = NULL;
1283 	int			 idx = -1;
1284 	int			 cnt = 0;
1285 	int			 maxtries;
1286 	u_int64_t		 p = 0;
1287 
1288 	/* the table is already selected */
1289 	if (con->se_table != NULL) {
1290 		rlt = con->se_table;
1291 		table = rlt->rlt_table;
1292 		if (table->conf.check && !table->up)
1293 			table = NULL;
1294 		goto gottable;
1295 	}
1296 
1297 	/* otherwise grep the first active table */
1298 	TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
1299 		table = rlt->rlt_table;
1300 		if ((rlt->rlt_flags & F_USED) == 0 ||
1301 		    (table->conf.check && !table->up))
1302 			table = NULL;
1303 		else
1304 			break;
1305 	}
1306 
1307  gottable:
1308 	if (table == NULL) {
1309 		log_debug("%s: session %d: no active hosts",
1310 		    __func__, con->se_id);
1311 		return (-1);
1312 	}
1313 
1314 	switch (rlt->rlt_mode) {
1315 	case RELAY_DSTMODE_ROUNDROBIN:
1316 		if ((int)rlt->rlt_index >= rlt->rlt_nhosts)
1317 			rlt->rlt_index = 0;
1318 		idx = (int)rlt->rlt_index;
1319 		break;
1320 	case RELAY_DSTMODE_RANDOM:
1321 		idx = (int)arc4random_uniform(rlt->rlt_nhosts);
1322 		break;
1323 	case RELAY_DSTMODE_SRCHASH:
1324 		/* Source IP address without port */
1325 		relay_hash_addr(&con->se_siphashctx, &con->se_in.ss, -1);
1326 		break;
1327 	case RELAY_DSTMODE_LOADBALANCE:
1328 		/* Source IP address without port */
1329 		relay_hash_addr(&con->se_siphashctx, &con->se_in.ss, -1);
1330 		/* FALLTHROUGH */
1331 	case RELAY_DSTMODE_HASH:
1332 		/* Local "destination" IP address and port */
1333 		relay_hash_addr(&con->se_siphashctx, &rlay->rl_conf.ss,
1334 		    rlay->rl_conf.port);
1335 		break;
1336 	default:
1337 		fatalx("%s: unsupported mode", __func__);
1338 		/* NOTREACHED */
1339 	}
1340 	if (idx == -1) {
1341 		/* handle all hashing algorithms */
1342 		p = SipHash24_End(&con->se_siphashctx);
1343 
1344 		/* Reset hash context */
1345 		SipHash24_Init(&con->se_siphashctx,
1346 		    &rlay->rl_conf.hashkey.siphashkey);
1347 
1348 		maxtries = (rlt->rlt_nhosts < RELAY_MAX_HASH_RETRIES ?
1349 		    rlt->rlt_nhosts : RELAY_MAX_HASH_RETRIES);
1350 		for (cnt = 0; cnt < maxtries; cnt++) {
1351 			if ((idx = p % rlt->rlt_nhosts) >= RELAY_MAXHOSTS)
1352 				return (-1);
1353 
1354 			host = rlt->rlt_host[idx];
1355 
1356 			DPRINTF("%s: session %d: table %s host %s, "
1357 			    "p 0x%016llx, idx %d, cnt %d, max %d",
1358 			    __func__, con->se_id, table->conf.name,
1359 			    host->conf.name, p, idx, cnt, maxtries);
1360 
1361 			if (!table->conf.check || host->up == HOST_UP)
1362 				goto found;
1363 			p = p >> 1;
1364 		}
1365 	} else {
1366 		/* handle all non-hashing algorithms */
1367 		host = rlt->rlt_host[idx];
1368 		DPRINTF("%s: session %d: table %s host %s, p 0x%016llx, idx %d",
1369 		    __func__, con->se_id, table->conf.name, host->conf.name,
1370 		    p, idx);
1371 	}
1372 
1373 	while (host != NULL) {
1374 		DPRINTF("%s: session %d: host %s", __func__,
1375 		    con->se_id, host->conf.name);
1376 		if (!table->conf.check || host->up == HOST_UP)
1377 			goto found;
1378 		host = TAILQ_NEXT(host, entry);
1379 	}
1380 	TAILQ_FOREACH(host, &table->hosts, entry) {
1381 		DPRINTF("%s: session %d: next host %s",
1382 		    __func__, con->se_id, host->conf.name);
1383 		if (!table->conf.check || host->up == HOST_UP)
1384 			goto found;
1385 	}
1386 
1387 	/* Should not happen */
1388 	fatalx("%s: no active hosts, desynchronized", __func__);
1389 
1390  found:
1391 	if (rlt->rlt_mode == RELAY_DSTMODE_ROUNDROBIN)
1392 		rlt->rlt_index = host->idx + 1;
1393 	con->se_retry = host->conf.retry;
1394 	con->se_out.port = table->conf.port;
1395 	bcopy(&host->conf.ss, &con->se_out.ss, sizeof(con->se_out.ss));
1396 
1397 	return (0);
1398 }
1399 
1400 void
relay_natlook(int fd,short event,void * arg)1401 relay_natlook(int fd, short event, void *arg)
1402 {
1403 	struct rsession		*con = arg;
1404 	struct relay		*rlay = con->se_relay;
1405 	struct ctl_natlook	*cnl = con->se_cnl;
1406 
1407 	if (cnl == NULL)
1408 		fatalx("invalid NAT lookup");
1409 
1410 	if (con->se_out.ss.ss_family == AF_UNSPEC && cnl->in == -1 &&
1411 	    rlay->rl_conf.dstss.ss_family == AF_UNSPEC &&
1412 	    TAILQ_EMPTY(&rlay->rl_tables)) {
1413 		relay_close(con, "session NAT lookup failed", 1);
1414 		return;
1415 	}
1416 	if (cnl->in != -1) {
1417 		bcopy(&cnl->rdst, &con->se_out.ss, sizeof(con->se_out.ss));
1418 		con->se_out.port = cnl->rdport;
1419 	}
1420 	free(con->se_cnl);
1421 	con->se_cnl = NULL;
1422 
1423 	relay_session(con);
1424 }
1425 
1426 void
relay_session(struct rsession * con)1427 relay_session(struct rsession *con)
1428 {
1429 	struct relay		*rlay = con->se_relay;
1430 	struct ctl_relay_event	*in = &con->se_in, *out = &con->se_out;
1431 
1432 	if (bcmp(&rlay->rl_conf.ss, &out->ss, sizeof(out->ss)) == 0 &&
1433 	    out->port == rlay->rl_conf.port) {
1434 		log_debug("%s: session %d: looping", __func__, con->se_id);
1435 		relay_close(con, "session aborted", 1);
1436 		return;
1437 	}
1438 
1439 	if (rlay->rl_conf.flags & F_UDP) {
1440 		/*
1441 		 * Call the UDP protocol-specific handler
1442 		 */
1443 		if (rlay->rl_proto->request == NULL)
1444 			fatalx("invalid UDP session");
1445 		if ((*rlay->rl_proto->request)(con) == -1)
1446 			relay_close(con, "session failed", 1);
1447 		return;
1448 	}
1449 
1450 	if ((rlay->rl_conf.flags & F_TLS) && (in->tls == NULL)) {
1451 		relay_tls_transaction(con, in);
1452 		return;
1453 	}
1454 
1455 	if (rlay->rl_proto->type != RELAY_PROTO_HTTP) {
1456 		if (rlay->rl_conf.fwdmode == FWD_TRANS)
1457 			relay_bindanyreq(con, 0, IPPROTO_TCP);
1458 		else if (relay_connect(con) == -1) {
1459 			relay_close(con, "session failed", 1);
1460 			return;
1461 		}
1462 	}
1463 
1464 	relay_input(con);
1465 }
1466 
1467 void
relay_bindanyreq(struct rsession * con,in_port_t port,int proto)1468 relay_bindanyreq(struct rsession *con, in_port_t port, int proto)
1469 {
1470 	struct privsep		*ps = env->sc_ps;
1471 	struct relay		*rlay = con->se_relay;
1472 	struct ctl_bindany	 bnd;
1473 	struct timeval		 tv;
1474 
1475 	bzero(&bnd, sizeof(bnd));
1476 	bnd.bnd_id = con->se_id;
1477 	bnd.bnd_proc = ps->ps_instance;
1478 	bnd.bnd_port = port;
1479 	bnd.bnd_proto = proto;
1480 	bcopy(&con->se_in.ss, &bnd.bnd_ss, sizeof(bnd.bnd_ss));
1481 	proc_compose(env->sc_ps, PROC_PARENT, IMSG_BINDANY,
1482 	    &bnd, sizeof(bnd));
1483 
1484 	/* Schedule timeout */
1485 	evtimer_set(&con->se_ev, relay_bindany, con);
1486 	bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv));
1487 	evtimer_add(&con->se_ev, &tv);
1488 }
1489 
1490 void
relay_bindany(int fd,short event,void * arg)1491 relay_bindany(int fd, short event, void *arg)
1492 {
1493 	struct rsession	*con = arg;
1494 
1495 	if (con->se_bnds == -1) {
1496 		relay_close(con, "bindany failed, invalid socket", 1);
1497 		return;
1498 	}
1499 	if (relay_connect(con) == -1)
1500 		relay_close(con, "session failed", 1);
1501 }
1502 
1503 void
relay_connect_state(struct rsession * con,struct ctl_relay_event * cre,enum relay_state new)1504 relay_connect_state(struct rsession *con, struct ctl_relay_event *cre,
1505     enum relay_state new)
1506 {
1507 	DPRINTF("%s: session %d: %s state %s -> %s",
1508 	    __func__, con->se_id,
1509 	    cre->dir == RELAY_DIR_REQUEST ? "accept" : "connect",
1510 	    relay_state(cre->state), relay_state(new));
1511 	cre->state = new;
1512 }
1513 
1514 void
relay_connect_retry(int fd,short sig,void * arg)1515 relay_connect_retry(int fd, short sig, void *arg)
1516 {
1517 	struct timeval	 evtpause = { 1, 0 };
1518 	struct rsession	*con = arg;
1519 	struct relay	*rlay = con->se_relay;
1520 	int		 bnds = -1;
1521 
1522 	if (relay_inflight < 1) {
1523 		log_warnx("%s: no connection in flight", __func__);
1524 		relay_inflight = 1;
1525 	}
1526 
1527 	DPRINTF("%s: retry %d of %d, inflight: %d",__func__,
1528 	    con->se_retrycount, con->se_retry, relay_inflight);
1529 
1530 	if (sig != EV_TIMEOUT)
1531 		fatalx("%s: called without timeout", __func__);
1532 
1533 	evtimer_del(&con->se_inflightevt);
1534 
1535 	/*
1536 	 * XXX we might want to check if the inbound socket is still
1537 	 * available: client could have closed it while we were waiting?
1538 	 */
1539 
1540 	DPRINTF("%s: got EV_TIMEOUT", __func__);
1541 
1542 	if (getdtablecount() + FD_RESERVE +
1543 	    relay_inflight > getdtablesize()) {
1544 		if (con->se_retrycount < RELAY_OUTOF_FD_RETRIES) {
1545 			evtimer_add(&con->se_inflightevt, &evtpause);
1546 			return;
1547 		}
1548 		/* we waited for RELAY_OUTOF_FD_RETRIES seconds, give up */
1549 		event_add(&rlay->rl_ev, NULL);
1550 		relay_abort_http(con, 504, "connection timed out", 0);
1551 		return;
1552 	}
1553 
1554 	if (rlay->rl_conf.fwdmode == FWD_TRANS) {
1555 		/* con->se_bnds cannot be unset */
1556 		bnds = con->se_bnds;
1557 	}
1558 
1559  retry:
1560 	if ((con->se_out.s = relay_socket_connect(&con->se_out.ss,
1561 	    con->se_out.port, rlay->rl_proto, bnds)) == -1) {
1562 		log_debug("%s: session %d: "
1563 		    "forward failed: %s, %s", __func__,
1564 		    con->se_id, strerror(errno),
1565 		    con->se_retry ? "next retry" : "last retry");
1566 
1567 		con->se_retrycount++;
1568 
1569 		if ((errno == ENFILE || errno == EMFILE) &&
1570 		    (con->se_retrycount < con->se_retry)) {
1571 			event_del(&rlay->rl_ev);
1572 			evtimer_add(&con->se_inflightevt, &evtpause);
1573 			evtimer_add(&rlay->rl_evt, &evtpause);
1574 			return;
1575 		} else if (con->se_retrycount < con->se_retry)
1576 			goto retry;
1577 		event_add(&rlay->rl_ev, NULL);
1578 		relay_abort_http(con, 504, "connect failed", 0);
1579 		return;
1580 	}
1581 
1582 	if (rlay->rl_conf.flags & F_TLSINSPECT)
1583 		relay_connect_state(con, &con->se_out, STATE_PRECONNECT);
1584 	else
1585 		relay_connect_state(con, &con->se_out, STATE_CONNECTED);
1586 	relay_inflight--;
1587 	DPRINTF("%s: inflight decremented, now %d",__func__, relay_inflight);
1588 
1589 	event_add(&rlay->rl_ev, NULL);
1590 
1591 	if (errno == EINPROGRESS)
1592 		event_again(&con->se_ev, con->se_out.s, EV_WRITE|EV_TIMEOUT,
1593 		    relay_connected, &con->se_tv_start, &rlay->rl_conf.timeout,
1594 		    con);
1595 	else
1596 		relay_connected(con->se_out.s, EV_WRITE, con);
1597 
1598 	return;
1599 }
1600 
1601 int
relay_preconnect(struct rsession * con)1602 relay_preconnect(struct rsession *con)
1603 {
1604 	int rv;
1605 
1606 	log_debug("%s: session %d: process %d", __func__,
1607 	    con->se_id, privsep_process);
1608 	rv = relay_connect(con);
1609 	if (con->se_out.state == STATE_CONNECTED)
1610 		relay_connect_state(con, &con->se_out, STATE_PRECONNECT);
1611 	return (rv);
1612 }
1613 
1614 int
relay_connect(struct rsession * con)1615 relay_connect(struct rsession *con)
1616 {
1617 	struct relay	*rlay = con->se_relay;
1618 	struct timeval	 evtpause = { 1, 0 };
1619 	int		 bnds = -1, ret;
1620 
1621 	/* relay_connect should only be called once per relay */
1622 	if (con->se_out.state == STATE_CONNECTED) {
1623 		log_debug("%s: connect already called once", __func__);
1624 		return (0);
1625 	}
1626 
1627 	/* Connection is already established but session not active */
1628 	if ((rlay->rl_conf.flags & F_TLSINSPECT) &&
1629 	    con->se_out.state == STATE_PRECONNECT) {
1630 		if (con->se_out.tls == NULL) {
1631 			log_debug("%s: tls connect failed", __func__);
1632 			return (-1);
1633 		}
1634 		relay_connected(con->se_out.s, EV_WRITE, con);
1635 		relay_connect_state(con, &con->se_out, STATE_CONNECTED);
1636 		return (0);
1637 	}
1638 
1639 	if (relay_inflight < 1) {
1640 		log_warnx("relay_connect: no connection in flight");
1641 		relay_inflight = 1;
1642 	}
1643 
1644 	getmonotime(&con->se_tv_start);
1645 
1646 	if (con->se_out.ss.ss_family == AF_UNSPEC &&
1647 	    !TAILQ_EMPTY(&rlay->rl_tables)) {
1648 		if (relay_from_table(con) != 0)
1649 			return (-1);
1650 	} else if (con->se_out.ss.ss_family == AF_UNSPEC) {
1651 		bcopy(&rlay->rl_conf.dstss, &con->se_out.ss,
1652 		    sizeof(con->se_out.ss));
1653 		con->se_out.port = rlay->rl_conf.dstport;
1654 	}
1655 
1656 	if (rlay->rl_conf.fwdmode == FWD_TRANS) {
1657 		if (con->se_bnds == -1) {
1658 			log_debug("%s: could not bind any sock", __func__);
1659 			return (-1);
1660 		}
1661 		bnds = con->se_bnds;
1662 	}
1663 
1664 	/* Do the IPv4-to-IPv6 or IPv6-to-IPv4 translation if requested */
1665 	if (rlay->rl_conf.dstaf.ss_family != AF_UNSPEC) {
1666 		if (con->se_out.ss.ss_family == AF_INET &&
1667 		    rlay->rl_conf.dstaf.ss_family == AF_INET6)
1668 			ret = map4to6(&con->se_out.ss, &rlay->rl_conf.dstaf);
1669 		else if (con->se_out.ss.ss_family == AF_INET6 &&
1670 		    rlay->rl_conf.dstaf.ss_family == AF_INET)
1671 			ret = map6to4(&con->se_out.ss);
1672 		else
1673 			ret = 0;
1674 		if (ret != 0) {
1675 			log_debug("%s: mapped to invalid address", __func__);
1676 			return (-1);
1677 		}
1678 	}
1679 
1680  retry:
1681 	if ((con->se_out.s = relay_socket_connect(&con->se_out.ss,
1682 	    con->se_out.port, rlay->rl_proto, bnds)) == -1) {
1683 		if (errno == ENFILE || errno == EMFILE) {
1684 			log_debug("%s: session %d: forward failed: %s",
1685 			    __func__, con->se_id, strerror(errno));
1686 			evtimer_set(&con->se_inflightevt, relay_connect_retry,
1687 			    con);
1688 			event_del(&rlay->rl_ev);
1689 			evtimer_add(&con->se_inflightevt, &evtpause);
1690 			evtimer_add(&rlay->rl_evt, &evtpause);
1691 
1692 			/* this connect is pending */
1693 			relay_connect_state(con, &con->se_out, STATE_PENDING);
1694 			return (0);
1695 		} else {
1696 			if (con->se_retry) {
1697 				con->se_retry--;
1698 				log_debug("%s: session %d: "
1699 				    "forward failed: %s, %s", __func__,
1700 				    con->se_id, strerror(errno),
1701 				    con->se_retry ?
1702 				    "next retry" : "last retry");
1703 				goto retry;
1704 			}
1705 			log_debug("%s: session %d: forward failed: %s",
1706 			    __func__, con->se_id, strerror(errno));
1707 			return (-1);
1708 		}
1709 	}
1710 
1711 	relay_connect_state(con, &con->se_out, STATE_CONNECTED);
1712 	relay_inflight--;
1713 	DPRINTF("%s: inflight decremented, now %d",__func__,
1714 	    relay_inflight);
1715 
1716 	if (errno == EINPROGRESS)
1717 		event_again(&con->se_ev, con->se_out.s, EV_WRITE|EV_TIMEOUT,
1718 		    relay_connected, &con->se_tv_start, &rlay->rl_conf.timeout,
1719 		    con);
1720 	else
1721 		relay_connected(con->se_out.s, EV_WRITE, con);
1722 
1723 	return (0);
1724 }
1725 
1726 void
relay_close(struct rsession * con,const char * msg,int err)1727 relay_close(struct rsession *con, const char *msg, int err)
1728 {
1729 	char		 ibuf[128], obuf[128], *ptr = NULL;
1730 	struct relay	*rlay = con->se_relay;
1731 	struct protocol	*proto = rlay->rl_proto;
1732 
1733 	SPLAY_REMOVE(session_tree, &rlay->rl_sessions, con);
1734 	relay_session_unpublish(con);
1735 
1736 	event_del(&con->se_ev);
1737 
1738 	if ((env->sc_conf.opts & (RELAYD_OPT_LOGCON|RELAYD_OPT_LOGCONERR)) &&
1739 	    msg != NULL) {
1740 		bzero(&ibuf, sizeof(ibuf));
1741 		bzero(&obuf, sizeof(obuf));
1742 		(void)print_host(&con->se_in.ss, ibuf, sizeof(ibuf));
1743 		(void)print_host(&con->se_out.ss, obuf, sizeof(obuf));
1744 		if (EVBUFFER_LENGTH(con->se_log) &&
1745 		    evbuffer_add_printf(con->se_log, "\r\n") != -1) {
1746 			ptr = evbuffer_readln(con->se_log, NULL,
1747 			    EVBUFFER_EOL_CRLF);
1748 		}
1749 		if (err == 0 && (env->sc_conf.opts & RELAYD_OPT_LOGCON))
1750 			log_info("relay %s, "
1751 			    "session %d (%d active), %s, %s -> %s:%d, "
1752 			    "%s%s%s", rlay->rl_conf.name, con->se_id,
1753 			    relay_sessions, con->se_tag != 0 ?
1754 			    tag_id2name(con->se_tag) : "0", ibuf, obuf,
1755 			    ntohs(con->se_out.port), msg, ptr == NULL ?
1756 			    "" : ",", ptr == NULL ? "" : ptr);
1757 		if (err == 1 && (env->sc_conf.opts & RELAYD_OPT_LOGCONERR))
1758 			log_warn("relay %s, "
1759 			    "session %d (%d active), %s, %s -> %s:%d, "
1760 			    "%s%s%s", rlay->rl_conf.name, con->se_id,
1761 			    relay_sessions, con->se_tag != 0 ?
1762 			    tag_id2name(con->se_tag) : "0", ibuf, obuf,
1763 			    ntohs(con->se_out.port), msg, ptr == NULL ?
1764 			    "" : ",", ptr == NULL ? "" : ptr);
1765 		free(ptr);
1766 	}
1767 
1768 	if (proto->close != NULL)
1769 		(*proto->close)(con);
1770 
1771 	free(con->se_priv);
1772 
1773 	relay_connect_state(con, &con->se_in, STATE_DONE);
1774 	if (relay_reset_event(con, &con->se_in)) {
1775 		if (con->se_out.s == -1) {
1776 			/*
1777 			 * the output was never connected,
1778 			 * thus this was an inflight session.
1779 			 */
1780 			relay_inflight--;
1781 			log_debug("%s: sessions inflight decremented, now %d",
1782 			    __func__, relay_inflight);
1783 		}
1784 	}
1785 	if (con->se_in.output != NULL)
1786 		evbuffer_free(con->se_in.output);
1787 
1788 	relay_connect_state(con, &con->se_out, STATE_DONE);
1789 	if (relay_reset_event(con, &con->se_out)) {
1790 		/* Some file descriptors are available again. */
1791 		if (evtimer_pending(&rlay->rl_evt, NULL)) {
1792 			evtimer_del(&rlay->rl_evt);
1793 			event_add(&rlay->rl_ev, NULL);
1794 		}
1795 	}
1796 	if (con->se_out.output != NULL)
1797 		evbuffer_free(con->se_out.output);
1798 
1799 	if (con->se_log != NULL)
1800 		evbuffer_free(con->se_log);
1801 
1802 	if (con->se_cnl != NULL) {
1803 #if 0
1804 		proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_KILLSTATES, -1,
1805 		    cnl, sizeof(*cnl));
1806 #endif
1807 		free(con->se_cnl);
1808 	}
1809 
1810 	free(con);
1811 	relay_sessions--;
1812 }
1813 
1814 int
relay_reset_event(struct rsession * con,struct ctl_relay_event * cre)1815 relay_reset_event(struct rsession *con, struct ctl_relay_event *cre)
1816 {
1817 	int		 rv = 0;
1818 
1819 	if (cre->state != STATE_DONE)
1820 		relay_connect_state(con, cre, STATE_CLOSED);
1821 	if (cre->bev != NULL) {
1822 		bufferevent_disable(cre->bev, EV_READ|EV_WRITE);
1823 		bufferevent_free(cre->bev);
1824 	}
1825 	if (cre->tls != NULL)
1826 		tls_close(cre->tls);
1827 	tls_free(cre->tls);
1828 	tls_free(cre->tls_ctx);
1829 	tls_config_free(cre->tls_cfg);
1830 	free(cre->tlscert);
1831 	if (cre->s != -1) {
1832 		close(cre->s);
1833 		rv = 1;
1834 	}
1835 	cre->bev = NULL;
1836 	cre->tls = NULL;
1837 	cre->tls_cfg = NULL;
1838 	cre->tlscert = NULL;
1839 	cre->s = -1;
1840 
1841 	return (rv);
1842 }
1843 
1844 int
relay_dispatch_pfe(int fd,struct privsep_proc * p,struct imsg * imsg)1845 relay_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
1846 {
1847 	struct relay		*rlay;
1848 	struct rsession		*con, se;
1849 	struct ctl_natlook	 cnl;
1850 	struct timeval		 tv;
1851 	struct host		*host;
1852 	struct table		*table;
1853 	struct ctl_status	 st;
1854 	objid_t			 id;
1855 	int			 cid;
1856 
1857 	switch (imsg->hdr.type) {
1858 	case IMSG_HOST_DISABLE:
1859 		memcpy(&id, imsg->data, sizeof(id));
1860 		if ((host = host_find(env, id)) == NULL)
1861 			fatalx("%s: desynchronized", __func__);
1862 		if ((table = table_find(env, host->conf.tableid)) ==
1863 		    NULL)
1864 			fatalx("%s: invalid table id", __func__);
1865 		if (host->up == HOST_UP)
1866 			table->up--;
1867 		host->flags |= F_DISABLE;
1868 		host->up = HOST_UNKNOWN;
1869 		break;
1870 	case IMSG_HOST_ENABLE:
1871 		memcpy(&id, imsg->data, sizeof(id));
1872 		if ((host = host_find(env, id)) == NULL)
1873 			fatalx("%s: desynchronized", __func__);
1874 		host->flags &= ~(F_DISABLE);
1875 		host->up = HOST_UNKNOWN;
1876 		break;
1877 	case IMSG_TABLE_DISABLE:
1878 		memcpy(&id, imsg->data, sizeof(id));
1879 		if ((table = table_find(env, id)) == NULL)
1880 			fatalx("%s: desynchronized", __func__);
1881 		table->conf.flags |= F_DISABLE;
1882 		table->up = 0;
1883 		TAILQ_FOREACH(host, &table->hosts, entry)
1884 			host->up = HOST_UNKNOWN;
1885 		break;
1886 	case IMSG_TABLE_ENABLE:
1887 		memcpy(&id, imsg->data, sizeof(id));
1888 		if ((table = table_find(env, id)) == NULL)
1889 			fatalx("%s: desynchronized", __func__);
1890 		table->conf.flags &= ~(F_DISABLE);
1891 		table->up = 0;
1892 		TAILQ_FOREACH(host, &table->hosts, entry)
1893 			host->up = HOST_UNKNOWN;
1894 		break;
1895 	case IMSG_HOST_STATUS:
1896 		IMSG_SIZE_CHECK(imsg, &st);
1897 		memcpy(&st, imsg->data, sizeof(st));
1898 		if ((host = host_find(env, st.id)) == NULL)
1899 			fatalx("%s: invalid host id", __func__);
1900 		if (host->flags & F_DISABLE)
1901 			break;
1902 		if (host->up == st.up) {
1903 			log_debug("%s: host %d => %d", __func__,
1904 			    host->conf.id, host->up);
1905 			fatalx("%s: desynchronized", __func__);
1906 		}
1907 
1908 		if ((table = table_find(env, host->conf.tableid))
1909 		    == NULL)
1910 			fatalx("%s: invalid table id", __func__);
1911 
1912 		DPRINTF("%s: [%d] state %d for "
1913 		    "host %u %s", __func__, p->p_ps->ps_instance, st.up,
1914 		    host->conf.id, host->conf.name);
1915 
1916 		if ((st.up == HOST_UNKNOWN && host->up == HOST_DOWN) ||
1917 		    (st.up == HOST_DOWN && host->up == HOST_UNKNOWN)) {
1918 			host->up = st.up;
1919 			break;
1920 		}
1921 		if (st.up == HOST_UP)
1922 			table->up++;
1923 		else
1924 			table->up--;
1925 		host->up = st.up;
1926 		break;
1927 	case IMSG_NATLOOK:
1928 		bcopy(imsg->data, &cnl, sizeof(cnl));
1929 		if ((con = session_find(env, cnl.id)) == NULL ||
1930 		    con->se_cnl == NULL) {
1931 			log_debug("%s: session %d: expired",
1932 			    __func__, cnl.id);
1933 			break;
1934 		}
1935 		bcopy(&cnl, con->se_cnl, sizeof(*con->se_cnl));
1936 		evtimer_del(&con->se_ev);
1937 		evtimer_set(&con->se_ev, relay_natlook, con);
1938 		bzero(&tv, sizeof(tv));
1939 		evtimer_add(&con->se_ev, &tv);
1940 		break;
1941 	case IMSG_CTL_SESSION:
1942 		IMSG_SIZE_CHECK(imsg, &cid);
1943 		memcpy(&cid, imsg->data, sizeof(cid));
1944 		TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
1945 			SPLAY_FOREACH(con, session_tree,
1946 			    &rlay->rl_sessions) {
1947 				memcpy(&se, con, sizeof(se));
1948 				se.se_cid = cid;
1949 				proc_compose(env->sc_ps, p->p_id,
1950 				    IMSG_CTL_SESSION, &se, sizeof(se));
1951 			}
1952 		}
1953 		proc_compose(env->sc_ps, p->p_id, IMSG_CTL_END,
1954 		    &cid, sizeof(cid));
1955 		break;
1956 	default:
1957 		return (-1);
1958 	}
1959 
1960 	return (0);
1961 }
1962 
1963 int
relay_dispatch_ca(int fd,struct privsep_proc * p,struct imsg * imsg)1964 relay_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg)
1965 {
1966 	switch (imsg->hdr.type) {
1967 	case IMSG_CA_PRIVENC:
1968 	case IMSG_CA_PRIVDEC:
1969 		log_warnx("%s: priv%s result after timeout", __func__,
1970 		    imsg->hdr.type == IMSG_CA_PRIVENC ? "enc" : "dec");
1971 		return (0);
1972 	}
1973 
1974 	return (-1);
1975 }
1976 
1977 int
relay_dispatch_parent(int fd,struct privsep_proc * p,struct imsg * imsg)1978 relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
1979 {
1980 	struct relay_ticket_key	 ticket;
1981 	struct relay		*rlay;
1982 	struct rsession		*con;
1983 	struct timeval		 tv;
1984 	objid_t			 id;
1985 
1986 	switch (imsg->hdr.type) {
1987 	case IMSG_BINDANY:
1988 		bcopy(imsg->data, &id, sizeof(id));
1989 		if ((con = session_find(env, id)) == NULL) {
1990 			log_debug("%s: session %d: expired",
1991 			    __func__, id);
1992 			break;
1993 		}
1994 
1995 		/* Will validate the result later */
1996 		con->se_bnds = imsg_get_fd(imsg);
1997 
1998 		evtimer_del(&con->se_ev);
1999 		evtimer_set(&con->se_ev, relay_bindany, con);
2000 		bzero(&tv, sizeof(tv));
2001 		evtimer_add(&con->se_ev, &tv);
2002 		break;
2003 	case IMSG_CFG_TABLE:
2004 		config_gettable(env, imsg);
2005 		break;
2006 	case IMSG_CFG_HOST:
2007 		config_gethost(env, imsg);
2008 		break;
2009 	case IMSG_CFG_PROTO:
2010 		config_getproto(env, imsg);
2011 		break;
2012 	case IMSG_CFG_RULE:
2013 		config_getrule(env, imsg);
2014 		break;
2015 	case IMSG_CFG_RELAY:
2016 		config_getrelay(env, imsg);
2017 		break;
2018 	case IMSG_CFG_RELAY_TABLE:
2019 		config_getrelaytable(env, imsg);
2020 		break;
2021 	case IMSG_CFG_RELAY_FD:
2022 		config_getrelayfd(env, imsg);
2023 		break;
2024 	case IMSG_CFG_DONE:
2025 		config_getcfg(env, imsg);
2026 		break;
2027 	case IMSG_CTL_START:
2028 		relay_launch();
2029 		break;
2030 	case IMSG_CTL_RESET:
2031 		config_getreset(env, imsg);
2032 		break;
2033 	case IMSG_TLSTICKET_REKEY:
2034 		IMSG_SIZE_CHECK(imsg, (&ticket));
2035 		memcpy(&env->sc_ticket, imsg->data, sizeof(env->sc_ticket));
2036 		TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
2037 			if (rlay->rl_conf.flags & F_TLS)
2038 				tls_config_add_ticket_key(rlay->rl_tls_cfg,
2039 				    env->sc_ticket.tt_keyrev,
2040 				    env->sc_ticket.tt_key,
2041 				    sizeof(env->sc_ticket.tt_key));
2042 		}
2043 		break;
2044 	default:
2045 		return (-1);
2046 	}
2047 
2048 	return (0);
2049 }
2050 
2051 int
relay_dispatch_hce(int fd,struct privsep_proc * p,struct imsg * imsg)2052 relay_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
2053 {
2054 	switch (imsg->hdr.type) {
2055 	default:
2056 		break;
2057 	}
2058 
2059 	return (-1);
2060 }
2061 
2062 static int
relay_tls_ctx_create_proto(struct protocol * proto,struct tls_config * tls_cfg)2063 relay_tls_ctx_create_proto(struct protocol *proto, struct tls_config *tls_cfg)
2064 {
2065 	uint32_t		 protocols = 0;
2066 
2067 	/* Set the allowed TLS protocols */
2068 	if (proto->tlsflags & TLSFLAG_TLSV1_2)
2069 		protocols |= TLS_PROTOCOL_TLSv1_2;
2070 	if (proto->tlsflags & TLSFLAG_TLSV1_3)
2071 		protocols |= TLS_PROTOCOL_TLSv1_3;
2072 	if (tls_config_set_protocols(tls_cfg, protocols) == -1) {
2073 		log_warnx("could not set the TLS protocol: %s",
2074 		    tls_config_error(tls_cfg));
2075 		return (-1);
2076 	}
2077 
2078 	if (tls_config_set_ciphers(tls_cfg, proto->tlsciphers)) {
2079 		log_warnx("could not set the TLS cypers: %s",
2080 		    tls_config_error(tls_cfg));
2081 		return (-1);
2082 	}
2083 
2084 	if ((proto->tlsflags & TLSFLAG_CIPHER_SERVER_PREF) == 0)
2085 		tls_config_prefer_ciphers_client(tls_cfg);
2086 
2087 	/*
2088 	 * Set session ID context to a random value. It needs to be the
2089 	 * same across all relay processes or session caching will fail.
2090 	 */
2091 	if (tls_config_set_session_id(tls_cfg, env->sc_conf.tls_sid,
2092 	    sizeof(env->sc_conf.tls_sid)) == -1) {
2093 		log_warnx("could not set the TLS session ID: %s",
2094 		    tls_config_error(tls_cfg));
2095 		return (-1);
2096 	}
2097 
2098 	/* Set callback for TLS session tickets if enabled */
2099 	if (proto->tickets == 1) {
2100 		/* set timeout to the ticket rekey time */
2101 		tls_config_set_session_lifetime(tls_cfg, TLS_SESSION_LIFETIME);
2102 
2103 		tls_config_add_ticket_key(tls_cfg,
2104 		    env->sc_ticket.tt_keyrev, env->sc_ticket.tt_key,
2105 		    sizeof(env->sc_ticket.tt_key));
2106 	}
2107 
2108 	if (tls_config_set_ecdhecurves(tls_cfg, proto->tlsecdhecurves) != 0) {
2109 		log_warnx("failed to set ecdhe curves %s: %s",
2110 		    proto->tlsecdhecurves, tls_config_error(tls_cfg));
2111 		return (-1);
2112 	}
2113 
2114 	if (tls_config_set_dheparams(tls_cfg, proto->tlsdhparams) != 0) {
2115 		log_warnx("failed to set dh params %s: %s",
2116 		    proto->tlsdhparams, tls_config_error(tls_cfg));
2117 		return (-1);
2118 	}
2119 
2120 	return (0);
2121 }
2122 
2123 /*
2124  * This function is not publicy exported because it is a hack until libtls
2125  * has a proper privsep setup
2126  */
2127 void tls_config_use_fake_private_key(struct tls_config *config);
2128 
2129 int
relay_tls_ctx_create(struct relay * rlay)2130 relay_tls_ctx_create(struct relay *rlay)
2131 {
2132 	struct tls_config	*tls_cfg, *tls_client_cfg;
2133 	struct tls		*tls = NULL;
2134 	struct relay_cert	*cert;
2135 	int			 keyfound = 0;
2136 	char			*buf = NULL, *cabuf = NULL, *ocspbuf = NULL;
2137 	off_t			 len = 0, calen = 0, ocsplen = 0;
2138 
2139 	if ((tls_cfg = tls_config_new()) == NULL) {
2140 		log_warnx("unable to allocate TLS config");
2141 		return (-1);
2142 	}
2143 	if ((tls_client_cfg = tls_config_new()) == NULL) {
2144 		log_warnx("unable to allocate TLS config");
2145 		return (-1);
2146 	}
2147 
2148 	if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_cfg) == -1)
2149 		goto err;
2150 	if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_client_cfg) == -1)
2151 		goto err;
2152 
2153 	/* Verify the server certificate if we have a CA chain */
2154 	if (rlay->rl_conf.flags & F_TLSCLIENT) {
2155 		/*
2156 		 * Currently relayd can't verify the name of certs and changing
2157 		 * this is non trivial. For now just disable name verification.
2158 		 */
2159 		tls_config_insecure_noverifyname(tls_client_cfg);
2160 
2161 		if (rlay->rl_tls_ca_fd != -1) {
2162 			if ((buf = relay_load_fd(rlay->rl_tls_ca_fd, &len)) == NULL) {
2163 				log_warn("failed to read root certificates");
2164 				goto err;
2165 			}
2166 			rlay->rl_tls_ca_fd = -1;
2167 
2168 			if (tls_config_set_ca_mem(tls_client_cfg, buf, len) !=
2169 			    0) {
2170 				log_warnx("failed to set root certificates: %s",
2171 				    tls_config_error(tls_client_cfg));
2172 				goto err;
2173 			}
2174 			purge_key(&buf, len);
2175 		} else {
2176 			/* No root cert available so disable the checking */
2177 			tls_config_insecure_noverifycert(tls_client_cfg);
2178 		}
2179 
2180 		rlay->rl_tls_client_cfg = tls_client_cfg;
2181 	}
2182 
2183 	if (rlay->rl_conf.flags & F_TLS) {
2184 		log_debug("%s: loading certificate", __func__);
2185 		/*
2186 		 * Use the public key as the "private" key - the secret key
2187 		 * parameters are hidden in an extra process that will be
2188 		 * contacted by the RSA engine.  The TLS library needs at
2189 		 * least the public key parameters in the current process.
2190 		 */
2191 		tls_config_use_fake_private_key(tls_cfg);
2192 
2193 		TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
2194 			if (cert->cert_relayid != rlay->rl_conf.id ||
2195 			    cert->cert_fd == -1)
2196 				continue;
2197 			keyfound++;
2198 
2199 			if ((buf = relay_load_fd(cert->cert_fd,
2200 			    &len)) == NULL) {
2201 				log_warn("failed to load tls certificate");
2202 				goto err;
2203 			}
2204 			cert->cert_fd = -1;
2205 
2206 			if (cert->cert_ocsp_fd != -1 &&
2207 			    (ocspbuf = relay_load_fd(cert->cert_ocsp_fd,
2208 			    &ocsplen)) == NULL) {
2209 				log_warn("failed to load OCSP staplefile");
2210 				goto err;
2211 			}
2212 			if (ocsplen == 0)
2213 				purge_key(&ocspbuf, ocsplen);
2214 			cert->cert_ocsp_fd = -1;
2215 
2216 			if (keyfound == 1 &&
2217 			    tls_config_set_keypair_ocsp_mem(tls_cfg, buf, len,
2218 			    NULL, 0, ocspbuf, ocsplen) != 0) {
2219 				log_warnx("failed to set tls certificate: %s",
2220 				    tls_config_error(tls_cfg));
2221 				goto err;
2222 			}
2223 
2224 			/* loading certificate public key */
2225 			if (keyfound == 1 &&
2226 			    !ssl_load_pkey(buf, len, NULL, &rlay->rl_tls_pkey))
2227 				goto err;
2228 
2229 			if (tls_config_add_keypair_ocsp_mem(tls_cfg, buf, len,
2230 			    NULL, 0, ocspbuf, ocsplen) != 0) {
2231 				log_warnx("failed to add tls certificate: %s",
2232 				    tls_config_error(tls_cfg));
2233 				goto err;
2234 			}
2235 
2236 			purge_key(&buf, len);
2237 			purge_key(&ocspbuf, ocsplen);
2238 		}
2239 
2240 		if (rlay->rl_tls_cacert_fd != -1) {
2241 			if ((cabuf = relay_load_fd(rlay->rl_tls_cacert_fd,
2242 			    &calen)) == NULL) {
2243 				log_warn("failed to load tls CA certificate");
2244 				goto err;
2245 			}
2246 			log_debug("%s: loading CA certificate", __func__);
2247 			if (!ssl_load_pkey(cabuf, calen,
2248 			    &rlay->rl_tls_cacertx509, &rlay->rl_tls_capkey))
2249 				goto err;
2250 		}
2251 		rlay->rl_tls_cacert_fd = -1;
2252 
2253 		if (rlay->rl_tls_client_ca_fd != -1) {
2254 			if ((buf = relay_load_fd(rlay->rl_tls_client_ca_fd,
2255 			    &len)) == NULL) {
2256 				log_warn(
2257 				    "failed to read tls client CA certificate");
2258 				goto err;
2259 			}
2260 
2261 			if (tls_config_set_ca_mem(tls_cfg, buf, len) != 0) {
2262 				log_warnx(
2263 				    "failed to set tls client CA cert: %s",
2264 				    tls_config_error(tls_cfg));
2265 				goto err;
2266 			}
2267 			purge_key(&buf, len);
2268 
2269 			tls_config_verify_client(tls_cfg);
2270 		}
2271 		rlay->rl_tls_client_ca_fd = -1;
2272 
2273 		tls = tls_server();
2274 		if (tls == NULL) {
2275 			log_warnx("unable to allocate TLS context");
2276 			goto err;
2277 		}
2278 		if (tls_configure(tls, tls_cfg) == -1) {
2279 			log_warnx("could not configure the TLS context: %s",
2280 			    tls_error(tls));
2281 			tls_free(tls);
2282 			goto err;
2283 		}
2284 		rlay->rl_tls_cfg = tls_cfg;
2285 		rlay->rl_tls_ctx = tls;
2286 
2287 		purge_key(&cabuf, calen);
2288 	}
2289 
2290 	if (rlay->rl_tls_client_cfg == NULL)
2291 		tls_config_free(tls_client_cfg);
2292 	if (rlay->rl_tls_cfg == NULL)
2293 		tls_config_free(tls_cfg);
2294 
2295 	return (0);
2296  err:
2297 	purge_key(&ocspbuf, ocsplen);
2298 	purge_key(&cabuf, calen);
2299 	purge_key(&buf, len);
2300 
2301 	tls_config_free(tls_client_cfg);
2302 	tls_config_free(tls_cfg);
2303 	return (-1);
2304 }
2305 
2306 static struct tls *
relay_tls_inspect_create(struct relay * rlay,struct ctl_relay_event * cre)2307 relay_tls_inspect_create(struct relay *rlay, struct ctl_relay_event *cre)
2308 {
2309 	struct tls_config	*tls_cfg;
2310 	struct tls		*tls = NULL;
2311 
2312 	/* TLS inspection: use session-specific certificate */
2313 	if ((tls_cfg = tls_config_new()) == NULL) {
2314 		log_warnx("unable to allocate TLS config");
2315 		goto err;
2316 	}
2317 	if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_cfg) == -1) {
2318 		/* error already printed */
2319 		goto err;
2320 	}
2321 
2322 	tls_config_use_fake_private_key(tls_cfg);
2323 
2324 	if (tls_config_set_keypair_ocsp_mem(tls_cfg,
2325 	    cre->tlscert, cre->tlscert_len, NULL, 0, NULL, 0) != 0) {
2326 		log_warnx("failed to set tls certificate: %s",
2327 		    tls_config_error(tls_cfg));
2328 		goto err;
2329 	}
2330 
2331 	tls = tls_server();
2332 	if (tls == NULL) {
2333 		log_warnx("unable to allocate TLS context");
2334 		goto err;
2335 	}
2336 	if (tls_configure(tls, tls_cfg) == -1) {
2337 		log_warnx("could not configure the TLS context: %s",
2338 		    tls_error(tls));
2339 		tls_free(tls);
2340 		goto err;
2341 	}
2342 
2343 	cre->tls_cfg = tls_cfg;
2344 	cre->tls_ctx = tls;
2345 	return (tls);
2346  err:
2347 	tls_config_free(tls_cfg);
2348 	return (NULL);
2349 }
2350 
2351 void
relay_tls_transaction(struct rsession * con,struct ctl_relay_event * cre)2352 relay_tls_transaction(struct rsession *con, struct ctl_relay_event *cre)
2353 {
2354 	struct relay		*rlay = con->se_relay;
2355 	struct tls		*tls_server;
2356 	const char		*errstr;
2357 	u_int			 flag;
2358 
2359 	if (cre->dir == RELAY_DIR_REQUEST) {
2360 		if (cre->tlscert != NULL)
2361 			tls_server = relay_tls_inspect_create(rlay, cre);
2362 		else
2363 			tls_server = rlay->rl_tls_ctx;
2364 		if (tls_server == NULL) {
2365 			errstr = "no TLS server context available";
2366 			goto err;
2367 		}
2368 
2369 		if (tls_accept_socket(tls_server, &cre->tls, cre->s) == -1) {
2370 			errstr = "could not accept the TLS connection";
2371 			goto err;
2372 		}
2373 		flag = EV_READ;
2374 	} else {
2375 		cre->tls = tls_client();
2376 		if (cre->tls == NULL ||
2377 		    tls_configure(cre->tls, rlay->rl_tls_client_cfg) == -1) {
2378 			errstr = "could not configure the TLS client context";
2379 			goto err;
2380 		}
2381 		if (tls_connect_socket(cre->tls, cre->s, NULL) == -1) {
2382 			errstr = "could not connect the TLS connection";
2383 			goto err;
2384 		}
2385 		flag = EV_WRITE;
2386 	}
2387 
2388 	log_debug("%s: session %d: scheduling on %s", __func__, con->se_id,
2389 	    (flag == EV_READ) ? "EV_READ" : "EV_WRITE");
2390 	event_again(&con->se_ev, cre->s, EV_TIMEOUT|flag, relay_tls_handshake,
2391 	    &con->se_tv_start, &rlay->rl_conf.timeout, cre);
2392 	return;
2393 
2394  err:
2395 	relay_close(con, errstr, 1);
2396 }
2397 
2398 void
relay_tls_handshake(int fd,short event,void * arg)2399 relay_tls_handshake(int fd, short event, void *arg)
2400 {
2401 	struct ctl_relay_event	*cre = arg;
2402 	struct rsession		*con = cre->con;
2403 	struct relay		*rlay = con->se_relay;
2404 	int			 retry_flag = 0;
2405 	int			 ret;
2406 	char			*msg;
2407 
2408 	if (event == EV_TIMEOUT) {
2409 		relay_close(con, "TLS handshake timeout", 1);
2410 		return;
2411 	}
2412 
2413 	ret = tls_handshake(cre->tls);
2414 	if (ret == 0) {
2415 #ifdef DEBUG
2416 		log_info(
2417 #else
2418 		log_debug(
2419 #endif
2420 		    "relay %s, tls session %d %s (%d active)",
2421 		    rlay->rl_conf.name, con->se_id,
2422 		    cre->dir == RELAY_DIR_REQUEST ? "established" : "connected",
2423 		    relay_sessions);
2424 
2425 		if (cre->dir == RELAY_DIR_REQUEST) {
2426 			relay_session(con);
2427 			return;
2428 		}
2429 
2430 		if (rlay->rl_conf.flags & F_TLSINSPECT) {
2431 			const uint8_t	*servercert;
2432 			size_t		 len;
2433 
2434 			servercert = tls_peer_cert_chain_pem(con->se_out.tls,
2435 			    &len);
2436 			if (servercert != NULL) {
2437 				con->se_in.tlscert = ssl_update_certificate(
2438 				    servercert, len,
2439 				    rlay->rl_tls_pkey, rlay->rl_tls_capkey,
2440 				    rlay->rl_tls_cacertx509,
2441 				    &con->se_in.tlscert_len);
2442 			} else
2443 				con->se_in.tlscert = NULL;
2444 			if (con->se_in.tlscert == NULL)
2445 				relay_close(con,
2446 				    "could not create certificate", 1);
2447 			else
2448 				relay_session(con);
2449 			return;
2450 		}
2451 		relay_connected(fd, EV_WRITE, con);
2452 		return;
2453 	} else if (ret == TLS_WANT_POLLIN) {
2454 		retry_flag = EV_READ;
2455 	} else if (ret == TLS_WANT_POLLOUT) {
2456 		retry_flag = EV_WRITE;
2457 	} else {
2458 		if (asprintf(&msg, "TLS handshake error: %s",
2459 		    tls_error(cre->tls)) >= 0) {
2460 			relay_close(con, msg, 1);
2461 			free(msg);
2462 		} else {
2463 			relay_close(con, "TLS handshake error", 1);
2464 		}
2465 		return;
2466 	}
2467 
2468 	DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id,
2469 	    (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE");
2470 	event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_tls_handshake,
2471 	    &con->se_tv_start, &rlay->rl_conf.timeout, cre);
2472 }
2473 
2474 void
relay_tls_connected(struct ctl_relay_event * cre)2475 relay_tls_connected(struct ctl_relay_event *cre)
2476 {
2477 	/*
2478 	 * Hack libevent - we overwrite the internal bufferevent I/O
2479 	 * functions to handle the TLS abstraction.
2480 	 */
2481 	event_del(&cre->bev->ev_read);
2482 	event_del(&cre->bev->ev_write);
2483 
2484 	event_set(&cre->bev->ev_read, cre->s, EV_READ,
2485 	    relay_tls_readcb, cre->bev);
2486 	event_set(&cre->bev->ev_write, cre->s, EV_WRITE,
2487 	    relay_tls_writecb, cre->bev);
2488 }
2489 
2490 void
relay_tls_readcb(int fd,short event,void * arg)2491 relay_tls_readcb(int fd, short event, void *arg)
2492 {
2493 	char			 rbuf[IBUF_READ_SIZE];
2494 	struct bufferevent	*bufev = arg;
2495 	struct ctl_relay_event	*cre = bufev->cbarg;
2496 	short			 what = EVBUFFER_READ;
2497 	int			 howmuch = IBUF_READ_SIZE;
2498 	ssize_t			 ret;
2499 	size_t			 len;
2500 
2501 	if (event == EV_TIMEOUT) {
2502 		what |= EVBUFFER_TIMEOUT;
2503 		goto err;
2504 	}
2505 
2506 	if (bufev->wm_read.high != 0)
2507 		howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
2508 
2509 	ret = tls_read(cre->tls, rbuf, howmuch);
2510 	if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
2511 		goto retry;
2512 	} else if (ret == -1) {
2513 		what |= EVBUFFER_ERROR;
2514 		goto err;
2515 	}
2516 	len = ret;
2517 
2518 	if (len == 0) {
2519 		what |= EVBUFFER_EOF;
2520 		goto err;
2521 	}
2522 
2523 	if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
2524 		what |= EVBUFFER_ERROR;
2525 		goto err;
2526 	}
2527 
2528 	relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
2529 
2530 	len = EVBUFFER_LENGTH(bufev->input);
2531 	if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
2532 		return;
2533 	if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
2534 		struct evbuffer *buf = bufev->input;
2535 		event_del(&bufev->ev_read);
2536 		evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
2537 		return;
2538 	}
2539 
2540 	if (bufev->readcb != NULL)
2541 		(*bufev->readcb)(bufev, bufev->cbarg);
2542 	return;
2543 
2544  retry:
2545 	relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
2546 	return;
2547 
2548  err:
2549 	(*bufev->errorcb)(bufev, what, bufev->cbarg);
2550 }
2551 
2552 void
relay_tls_writecb(int fd,short event,void * arg)2553 relay_tls_writecb(int fd, short event, void *arg)
2554 {
2555 	struct bufferevent	*bufev = arg;
2556 	struct ctl_relay_event	*cre = bufev->cbarg;
2557 	ssize_t			 ret;
2558 	size_t			 len;
2559 	short			 what = EVBUFFER_WRITE;
2560 
2561 	if (event == EV_TIMEOUT) {
2562 		what |= EVBUFFER_TIMEOUT;
2563 		goto err;
2564 	}
2565 
2566 	if (EVBUFFER_LENGTH(bufev->output)) {
2567 		ret = tls_write(cre->tls, EVBUFFER_DATA(bufev->output),
2568 		    EVBUFFER_LENGTH(bufev->output));
2569 		if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
2570 			goto retry;
2571 		} else if (ret == -1) {
2572 			what |= EVBUFFER_ERROR;
2573 			goto err;
2574 		}
2575 		len = ret;
2576 		evbuffer_drain(bufev->output, len);
2577 	}
2578 
2579 	if (EVBUFFER_LENGTH(bufev->output) != 0)
2580 		relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
2581 
2582 	if (bufev->writecb != NULL &&
2583 	    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
2584 		(*bufev->writecb)(bufev, bufev->cbarg);
2585 	return;
2586 
2587  retry:
2588 	relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
2589 	return;
2590 
2591  err:
2592 	(*bufev->errorcb)(bufev, what, bufev->cbarg);
2593 }
2594 
2595 int
relay_bufferevent_add(struct event * ev,int timeout)2596 relay_bufferevent_add(struct event *ev, int timeout)
2597 {
2598 	struct timeval tv, *ptv = NULL;
2599 
2600 	if (timeout) {
2601 		timerclear(&tv);
2602 		tv.tv_sec = timeout;
2603 		ptv = &tv;
2604 	}
2605 
2606 	return (event_add(ev, ptv));
2607 }
2608 
2609 #ifdef notyet
2610 int
relay_bufferevent_printf(struct ctl_relay_event * cre,const char * fmt,...)2611 relay_bufferevent_printf(struct ctl_relay_event *cre, const char *fmt, ...)
2612 {
2613 	int	ret;
2614 	va_list	ap;
2615 
2616 	va_start(ap, fmt);
2617 	ret = evbuffer_add_vprintf(cre->output, fmt, ap);
2618 	va_end(ap);
2619 
2620 	if (cre->bev != NULL &&
2621 	    ret != -1 && EVBUFFER_LENGTH(cre->output) > 0 &&
2622 	    (cre->bev->enabled & EV_WRITE))
2623 		bufferevent_enable(cre->bev, EV_WRITE);
2624 
2625 	return (ret);
2626 }
2627 #endif
2628 
2629 int
relay_bufferevent_print(struct ctl_relay_event * cre,const char * str)2630 relay_bufferevent_print(struct ctl_relay_event *cre, const char *str)
2631 {
2632 	if (cre->bev == NULL)
2633 		return (evbuffer_add(cre->output, str, strlen(str)));
2634 	return (bufferevent_write(cre->bev, str, strlen(str)));
2635 }
2636 
2637 int
relay_bufferevent_write_buffer(struct ctl_relay_event * cre,struct evbuffer * buf)2638 relay_bufferevent_write_buffer(struct ctl_relay_event *cre,
2639     struct evbuffer *buf)
2640 {
2641 	if (cre->bev == NULL)
2642 		return (evbuffer_add_buffer(cre->output, buf));
2643 	return (bufferevent_write_buffer(cre->bev, buf));
2644 }
2645 
2646 int
relay_bufferevent_write_chunk(struct ctl_relay_event * cre,struct evbuffer * buf,size_t size)2647 relay_bufferevent_write_chunk(struct ctl_relay_event *cre,
2648     struct evbuffer *buf, size_t size)
2649 {
2650 	int ret;
2651 	ret = relay_bufferevent_write(cre, EVBUFFER_DATA(buf), size);
2652 	if (ret != -1)
2653 		evbuffer_drain(buf, size);
2654 	return (ret);
2655 }
2656 
2657 int
relay_bufferevent_write(struct ctl_relay_event * cre,void * data,size_t size)2658 relay_bufferevent_write(struct ctl_relay_event *cre, void *data, size_t size)
2659 {
2660 	if (cre->bev == NULL)
2661 		return (evbuffer_add(cre->output, data, size));
2662 	return (bufferevent_write(cre->bev, data, size));
2663 }
2664 
2665 int
relay_cmp_af(struct sockaddr_storage * a,struct sockaddr_storage * b)2666 relay_cmp_af(struct sockaddr_storage *a, struct sockaddr_storage *b)
2667 {
2668 	int			ret = -1;
2669 	struct sockaddr_in	ia, ib;
2670 	struct sockaddr_in6	ia6, ib6;
2671 
2672 	switch (a->ss_family) {
2673 	case AF_INET:
2674 		bcopy(a, &ia, sizeof(struct sockaddr_in));
2675 		bcopy(b, &ib, sizeof(struct sockaddr_in));
2676 
2677 		ret = memcmp(&ia.sin_addr, &ib.sin_addr,
2678 		    sizeof(ia.sin_addr));
2679 		if (ret == 0)
2680 			ret = memcmp(&ia.sin_port, &ib.sin_port,
2681 			    sizeof(ia.sin_port));
2682 		break;
2683 	case AF_INET6:
2684 		bcopy(a, &ia6, sizeof(struct sockaddr_in6));
2685 		bcopy(b, &ib6, sizeof(struct sockaddr_in6));
2686 
2687 		ret = memcmp(&ia6.sin6_addr, &ib6.sin6_addr,
2688 		    sizeof(ia6.sin6_addr));
2689 		if (ret == 0)
2690 			ret = memcmp(&ia6.sin6_port, &ib6.sin6_port,
2691 			    sizeof(ia6.sin6_port));
2692 		break;
2693 	default:
2694 		break;
2695 	}
2696 
2697 	return (ret);
2698 }
2699 
2700 int
relay_session_cmp(struct rsession * a,struct rsession * b)2701 relay_session_cmp(struct rsession *a, struct rsession *b)
2702 {
2703 	struct relay	*rlay = b->se_relay;
2704 	struct protocol	*proto = rlay->rl_proto;
2705 
2706 	if (proto != NULL && proto->cmp != NULL)
2707 		return ((*proto->cmp)(a, b));
2708 
2709 	return ((int)a->se_id - b->se_id);
2710 }
2711 
2712 void
relay_log(struct rsession * con,char * msg)2713 relay_log(struct rsession *con, char *msg)
2714 {
2715 	if (con->se_haslog && con->se_log != NULL) {
2716 		evbuffer_add(con->se_log, msg, strlen(msg));
2717 	}
2718 }
2719 
2720 SPLAY_GENERATE(session_tree, rsession, se_nodes, relay_session_cmp);
2721