1 /*-
2  * SSLsplit - transparent SSL/TLS interception
3  * https://www.roe.ch/SSLsplit
4  *
5  * Copyright (c) 2009-2019, Daniel Roethlisberger <daniel@roe.ch>.
6  * Copyright (c) 2017-2021, Soner Tari <sonertari@gmail.com>.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "pxyconn.h"
31 
32 #include "prototcp.h"
33 #include "protossl.h"
34 #include "protohttp.h"
35 #include "protopop3.h"
36 #include "protosmtp.h"
37 #include "protoautossl.h"
38 #include "protopassthrough.h"
39 
40 #include "privsep.h"
41 #include "sys.h"
42 #include "log.h"
43 #include "attrib.h"
44 #include "proc.h"
45 #include "util.h"
46 
47 #include <string.h>
48 #include <arpa/inet.h>
49 #include <sys/param.h>
50 #include <assert.h>
51 
52 #include <event2/listener.h>
53 
54 #ifdef __linux__
55 #include <glob.h>
56 #endif /* __linux__ */
57 
58 #include <net/if_arp.h>
59 #include <sys/ioctl.h>
60 #include <sys/socket.h>
61 #if (__linux__ && HAVE_SYSCTL) || !__linux__
62 #include <sys/sysctl.h>
63 #endif
64 #include <net/route.h>
65 #include <netinet/if_ether.h>
66 #ifdef __OpenBSD__
67 #include <net/if_dl.h>
68 #endif /* __OpenBSD__ */
69 
70 /*
71  * Maximum size of data to buffer per connection direction before
72  * temporarily stopping to read data from the other end.
73  */
74 #define OUTBUF_LIMIT	(128*1024)
75 
76 // getdtablecount() returns int, hence we don't use size_t here
77 int descriptor_table_size = 0;
78 
79 // @attention The order of names should match the order in protocol enum
80 char *protocol_names[] = {
81 	// ERROR = -1
82 	"PASSTHROUGH", // = 0
83 	"HTTP",
84 	"HTTPS",
85 	"POP3",
86 	"POP3S",
87 	"SMTP",
88 	"SMTPS",
89 	"AUTOSSL",
90 	"TCP",
91 	"SSL",
92 };
93 
94 static protocol_t NONNULL(1)
pxy_setup_proto_child(pxy_conn_child_ctx_t * ctx)95 pxy_setup_proto_child(pxy_conn_child_ctx_t *ctx)
96 {
97 	ctx->protoctx = malloc(sizeof(proto_child_ctx_t));
98 	if (!ctx->protoctx) {
99 		return PROTO_ERROR;
100 	}
101 	memset(ctx->protoctx, 0, sizeof(proto_child_ctx_t));
102 
103 	// Default to tcp
104 	prototcp_setup_child(ctx);
105 
106 	protocol_t proto;
107 	if (ctx->conn->spec->upgrade) {
108 		proto = protoautossl_setup_child(ctx);
109 	} else if (ctx->conn->spec->http) {
110 		if (ctx->conn->spec->ssl) {
111 			proto = protohttps_setup_child(ctx);
112 		} else {
113 			proto = protohttp_setup_child(ctx);
114 		}
115 	} else if (ctx->conn->spec->pop3) {
116 		if (ctx->conn->spec->ssl) {
117 			proto = (protossl_setup_child(ctx) != PROTO_ERROR) ? PROTO_POP3S : PROTO_ERROR;
118 		} else {
119 			proto = PROTO_POP3;
120 		}
121 	} else if (ctx->conn->spec->smtp) {
122 		if (ctx->conn->spec->ssl) {
123 			proto = (protossl_setup_child(ctx) != PROTO_ERROR) ? PROTO_SMTPS : PROTO_ERROR;
124 		} else {
125 			proto = PROTO_SMTP;
126 		}
127 	} else if (ctx->conn->spec->ssl) {
128 		proto = protossl_setup_child(ctx);
129 	} else {
130 		proto = PROTO_TCP;
131 	}
132 
133 	if (proto == PROTO_ERROR) {
134 		free(ctx->protoctx);
135 	}
136 	return proto;
137 }
138 
139 static pxy_conn_child_ctx_t * MALLOC NONNULL(2)
pxy_conn_ctx_new_child(evutil_socket_t fd,pxy_conn_ctx_t * ctx)140 pxy_conn_ctx_new_child(evutil_socket_t fd, pxy_conn_ctx_t *ctx)
141 {
142 	assert(ctx != NULL);
143 
144 	log_finest_va("ENTER, fd=%d", fd);
145 
146 	pxy_conn_child_ctx_t *child_ctx = malloc(sizeof(pxy_conn_child_ctx_t));
147 	if (!child_ctx) {
148 		return NULL;
149 	}
150 	memset(child_ctx, 0, sizeof(pxy_conn_child_ctx_t));
151 
152 	child_ctx->type = CONN_TYPE_CHILD;
153 #ifdef DEBUG_PROXY
154 	child_ctx->id = ctx->child_count++;
155 #endif /* DEBUG_PROXY */
156 	child_ctx->conn = ctx;
157 	child_ctx->fd = fd;
158 
159 	if (pxy_setup_proto_child(child_ctx) == PROTO_ERROR) {
160 		free(child_ctx);
161 		return NULL;
162 	}
163 	return child_ctx;
164 }
165 
166 static void NONNULL(1)
pxy_conn_ctx_free_child(pxy_conn_child_ctx_t * ctx)167 pxy_conn_ctx_free_child(pxy_conn_child_ctx_t *ctx)
168 {
169 	log_finest("ENTER");
170 
171 	// If the proto doesn't have special args, proto_free() callback is NULL
172 	if (ctx->protoctx->proto_free) {
173 		ctx->protoctx->proto_free(ctx);
174 	}
175 	free(ctx->protoctx);
176 	free(ctx);
177 }
178 
179 // This function cannot fail.
180 static void NONNULL(1)
pxy_conn_attach_child(pxy_conn_child_ctx_t * ctx)181 pxy_conn_attach_child(pxy_conn_child_ctx_t *ctx)
182 {
183 	log_finest("Adding child conn");
184 
185 	// @attention Child connections use the parent's event bases, otherwise we would get multithreading issues
186 	// Always keep thr load and conns list in sync
187 	ctx->conn->thr->load++;
188 	ctx->conn->thr->max_load = max(ctx->conn->thr->max_load, ctx->conn->thr->load);
189 
190 	// Prepend child to the children list of parent
191 	ctx->next = ctx->conn->children;
192 	ctx->conn->children = ctx;
193 	if (ctx->next)
194 		ctx->next->prev = ctx;
195 }
196 
197 // This function cannot fail.
198 static void NONNULL(1)
pxy_conn_detach_child(pxy_conn_child_ctx_t * ctx)199 pxy_conn_detach_child(pxy_conn_child_ctx_t *ctx)
200 {
201 	assert(ctx->conn != NULL);
202 	assert(ctx->conn->children != NULL);
203 
204 	log_finest("Removing child conn");
205 
206 	ctx->conn->thr->load--;
207 
208 	if (ctx->prev) {
209 		ctx->prev->next = ctx->next;
210 	} else {
211 		ctx->conn->children = ctx->next;
212 	}
213 	if (ctx->next)
214 		ctx->next->prev = ctx->prev;
215 
216 #ifdef DEBUG_PROXY
217 	if (ctx->conn->children) {
218 		if (ctx->id == ctx->conn->children->id) {
219 			// This should never happen
220 			log_fine("Found child in conn children, first");
221 			assert(0);
222 		} else {
223 			pxy_conn_child_ctx_t *current = ctx->conn->children->next;
224 			pxy_conn_child_ctx_t *previous = ctx->conn->children;
225 			while (current != NULL && previous != NULL) {
226 				if (ctx->id == current->id) {
227 					// This should never happen
228 					log_fine("Found child in conn children");
229 					assert(0);
230 				}
231 				previous = current;
232 				current = current->next;
233 			}
234 			log_finest("Cannot find child in conn children");
235 		}
236 	} else {
237 		log_finest("Cannot find child in conn children, empty");
238 	}
239 #endif /* DEBUG_PROXY */
240 }
241 
242 static void
pxy_conn_free_child(pxy_conn_child_ctx_t * ctx)243 pxy_conn_free_child(pxy_conn_child_ctx_t *ctx)
244 {
245 	assert(ctx->conn != NULL);
246 
247 	log_finest("ENTER");
248 
249 	// We always assign NULL to bevs after freeing them
250 	if (ctx->src.bev) {
251 		ctx->src.free(ctx->src.bev, ctx->conn);
252 		ctx->src.bev = NULL;
253 	} else if (!ctx->src.closed) {
254 		log_fine("!src.closed, evutil_closesocket on NULL src.bev");
255 
256 		// @attention early in the conn setup, src fd may be open, although src.bev is NULL
257 		evutil_closesocket(ctx->fd);
258 	}
259 
260 	if (ctx->dst.bev) {
261 		ctx->dst.free(ctx->dst.bev, ctx->conn);
262 		ctx->dst.bev = NULL;
263 	}
264 
265 	// Save conn and srvdst_xferred before freeing ctx
266 	pxy_conn_ctx_t *conn = ctx->conn;
267 	unsigned int srvdst_xferred = ctx->srvdst_xferred;
268 
269 	pxy_conn_detach_child(ctx);
270 	pxy_conn_ctx_free_child(ctx);
271 
272 	// If there is no child left, free child_evcl asap by calling pxy_conn_free_children()
273 	if (!conn->children) {
274 		pxy_conn_free_children(conn);
275 	}
276 
277 	// If this is the first child, NULL srvdst.bev, so we don't try to access it from this point on
278 	if (srvdst_xferred) {
279 		conn->srvdst.bev = NULL;
280 	}
281 }
282 
283 void
pxy_conn_term_child(pxy_conn_child_ctx_t * ctx)284 pxy_conn_term_child(pxy_conn_child_ctx_t *ctx)
285 {
286 	log_finest("ENTER");
287 	ctx->term = 1;
288 }
289 
290 void
pxy_conn_free_children(pxy_conn_ctx_t * ctx)291 pxy_conn_free_children(pxy_conn_ctx_t *ctx)
292 {
293 	log_finest("ENTER");
294 
295 	// @attention Free the child ctxs asap, we need their fds
296 	while (ctx->children) {
297 		pxy_conn_free_child(ctx->children);
298 	}
299 
300 	// @attention Parent may be closing before there was any child at all nor was child_evcl ever created
301 	if (ctx->child_evcl) {
302 		log_finer_va("Freeing child_evcl, children fd=%d", ctx->children ? ctx->children->fd : -1);
303 
304 		// @attention child_evcl was created with LEV_OPT_CLOSE_ON_FREE, so do not close ctx->child_fd
305 		evconnlistener_free(ctx->child_evcl);
306 		ctx->child_evcl = NULL;
307 	}
308 }
309 
310 /*
311  * Does full clean-up of conn ctx.
312  * This is the conn handling thr version of a similar function
313  * proxy_conn_ctx_free(), which runs on thrmgr and does minimal
314  * clean-up.
315  */
316 void
pxy_conn_ctx_free(pxy_conn_ctx_t * ctx,int by_requestor)317 pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor)
318 {
319 	log_finest("ENTER");
320 
321 	if (WANT_CONTENT_LOG(ctx)) {
322 		// Always try to close log files, even if content, pcap, or mirror logging is disabled by filter rules
323 		// The log files may have been initialized and opened
324 		// so, do not pass down the log_content, log_pcap, and log_mirror fields of ctx
325 		if (log_content_close(&ctx->logctx, by_requestor) == -1) {
326 			log_err_level_printf(LOG_WARNING, "Content log close failed\n");
327 		}
328 	}
329 
330 #ifndef WITHOUT_USERAUTH
331 	if (ctx->conn_opts->user_auth && ctx->srchost_str && ctx->user && ctx->ether) {
332 		// Update userdb atime if idle time is more than 50% of user timeout, which is expected to reduce update frequency
333 		unsigned int idletime = ctx->idletime + (time(NULL) - ctx->ctime);
334 		if (idletime > (ctx->conn_opts->user_timeout / 2)) {
335 			userdbkeys_t keys;
336 			// Zero out for NULL termination
337 			memset(&keys, 0, sizeof(userdbkeys_t));
338 			// Leave room for NULL to make sure the strings are always NULL terminated
339 			strncpy(keys.ip, ctx->srchost_str, sizeof(keys.ip) - 1);
340 			strncpy(keys.user, ctx->user, sizeof(keys.user) - 1);
341 			strncpy(keys.ether, ctx->ether, sizeof(keys.ether) - 1);
342 
343 			if (privsep_client_update_atime(ctx->clisock, &keys) == -1) {
344 				log_finest_va("Error updating user atime: %s", sqlite3_errmsg(ctx->global->userdb));
345 			} else {
346 				log_finest("Successfully updated user atime");
347 			}
348 		} else {
349 			log_finest_va("Will not update user atime, idletime=%u", idletime);
350 		}
351 	}
352 #endif /* !WITHOUT_USERAUTH */
353 
354 	pxy_thr_detach(ctx);
355 
356 	if (ctx->srchost_str) {
357 		free(ctx->srchost_str);
358 	}
359 	if (ctx->srcport_str) {
360 		free(ctx->srcport_str);
361 	}
362 	if (ctx->dsthost_str) {
363 		free(ctx->dsthost_str);
364 	}
365 	if (ctx->dstport_str) {
366 		free(ctx->dstport_str);
367 	}
368 #ifdef HAVE_LOCAL_PROCINFO
369 	if (ctx->lproc.exec_path) {
370 		free(ctx->lproc.exec_path);
371 	}
372 	if (ctx->lproc.user) {
373 		free(ctx->lproc.user);
374 	}
375 	if (ctx->lproc.group) {
376 		free(ctx->lproc.group);
377 	}
378 #endif /* HAVE_LOCAL_PROCINFO */
379 	if (ctx->ev) {
380 		event_free(ctx->ev);
381 	}
382 	if (ctx->sslproxy_header) {
383 		free(ctx->sslproxy_header);
384 	}
385 	// If the proto doesn't have special args, proto_free() callback is NULL
386 	if (ctx->protoctx->proto_free) {
387 		ctx->protoctx->proto_free(ctx);
388 	}
389 	free(ctx->protoctx);
390 
391 #ifndef WITHOUT_USERAUTH
392 	if (ctx->user) {
393 		free(ctx->user);
394 	}
395 	if (ctx->ether) {
396 		free(ctx->ether);
397 	}
398 	if (ctx->desc) {
399 		free(ctx->desc);
400 	}
401 #endif /* !WITHOUT_USERAUTH */
402 	free(ctx);
403 }
404 
405 void
pxy_conn_free(pxy_conn_ctx_t * ctx,int by_requestor)406 pxy_conn_free(pxy_conn_ctx_t *ctx, int by_requestor)
407 {
408 	log_finest("ENTER");
409 
410 	// We always assign NULL to bevs after freeing them
411 	if (ctx->src.bev) {
412 		ctx->src.free(ctx->src.bev, ctx);
413 		ctx->src.bev = NULL;
414 	} else if (!ctx->src.closed) {
415 		log_fine("evutil_closesocket on NULL src.bev");
416 		// @attention early in the conn setup, src fd may be open, although src.bev is NULL
417 		evutil_closesocket(ctx->fd);
418 	}
419 
420 	if (ctx->srvdst.bev) {
421 		// In split mode, srvdst is used as dst, so it should be freed as dst below
422 		// If srvdst has been xferred to the first child conn, the child should free it, not the parent
423 		if (ctx->divert && !ctx->srvdst_xferred) {
424 			ctx->srvdst.free(ctx->srvdst.bev, ctx);
425 		} else /*if (!ctx->divert || ctx->srvdst_xferred)*/ {
426 			// We reuse srvdst as dst or child dst, so srvdst == dst or child_dst.
427 			// But if we don't NULL the callbacks of srvdst in split mode,
428 			// we randomly but rarely get a second eof event for srvdst during conn termination (especially on arm64),
429 			// which crashes us with signal 11 or 10, because the first eof event for dst frees the ctx.
430 			// Note that we don't free anything here, but just disable callbacks and events.
431 			// This does not seem to happen with srvdst_xferred, but just to be safe we do the same for it too.
432 			// This seems to be an issue with libevent.
433 			// @todo Why does libevent raise the same event again for an already disabled and freed conn end?
434 			// Note again that srvdst == dst or child_dst here.
435 
436 			struct bufferevent *ubev = bufferevent_get_underlying(ctx->srvdst.bev);
437 
438 			bufferevent_setcb(ctx->srvdst.bev, NULL, NULL, NULL, NULL);
439 			bufferevent_disable(ctx->srvdst.bev, EV_READ|EV_WRITE);
440 
441 			if (ubev) {
442 				bufferevent_setcb(ubev, NULL, NULL, NULL, NULL);
443 				bufferevent_disable(ubev, EV_READ|EV_WRITE);
444 			}
445 		}
446 		ctx->srvdst.bev = NULL;
447 	}
448 
449 	if (ctx->dst.bev) {
450 		ctx->dst.free(ctx->dst.bev, ctx);
451 		ctx->dst.bev = NULL;
452 	}
453 
454 	pxy_conn_free_children(ctx);
455 	pxy_conn_ctx_free(ctx, by_requestor);
456 }
457 
458 void
pxy_conn_term(pxy_conn_ctx_t * ctx,int by_requestor)459 pxy_conn_term(pxy_conn_ctx_t *ctx, int by_requestor)
460 {
461 	log_finest("ENTER");
462 	ctx->term = 1;
463 	ctx->term_requestor = by_requestor;
464 }
465 
466 void
pxy_log_connect_nonhttp(pxy_conn_ctx_t * ctx)467 pxy_log_connect_nonhttp(pxy_conn_ctx_t *ctx)
468 {
469 	if (!ctx->log_connect)
470 		return;
471 
472 	char *msg;
473 #ifdef HAVE_LOCAL_PROCINFO
474 	char *lpi = NULL;
475 #endif /* HAVE_LOCAL_PROCINFO */
476 	int rv;
477 
478 #ifdef HAVE_LOCAL_PROCINFO
479 	if (ctx->global->lprocinfo) {
480 		rv = asprintf(&lpi, "lproc:%i:%s:%s:%s",
481 		              ctx->lproc.pid,
482 		              STRORDASH(ctx->lproc.user),
483 		              STRORDASH(ctx->lproc.group),
484 		              STRORDASH(ctx->lproc.exec_path));
485 		if ((rv < 0) || !lpi) {
486 			ctx->enomem = 1;
487 			goto out;
488 		}
489 	} else {
490 		lpi = "";
491 	}
492 #endif /* HAVE_LOCAL_PROCINFO */
493 
494 	/*
495 	 * The following ifdef's within asprintf arguments list generates
496 	 * warnings with -Wembedded-directive on some compilers.
497 	 * Not fixing the code in order to avoid more code duplication.
498 	 */
499 
500 	if (!ctx->src.ssl) {
501 		rv = asprintf(&msg, "CONN: %s %s %s %s %s"
502 #ifdef HAVE_LOCAL_PROCINFO
503 		              " %s"
504 #endif /* HAVE_LOCAL_PROCINFO */
505 #ifndef WITHOUT_USERAUTH
506 		              " user:%s"
507 #endif /* !WITHOUT_USERAUTH */
508 		              "\n",
509 		              ctx->proto == PROTO_AUTOSSL ? "autossl" : (ctx->proto == PROTO_PASSTHROUGH ? "passthrough" : (ctx->proto == PROTO_POP3 ? "pop3" : (ctx->proto == PROTO_SMTP ? "smtp" : "tcp"))),
510 		              STRORDASH(ctx->srchost_str),
511 		              STRORDASH(ctx->srcport_str),
512 		              STRORDASH(ctx->dsthost_str),
513 		              STRORDASH(ctx->dstport_str)
514 #ifdef HAVE_LOCAL_PROCINFO
515 		              , lpi
516 #endif /* HAVE_LOCAL_PROCINFO */
517 #ifndef WITHOUT_USERAUTH
518 		              , STRORDASH(ctx->user)
519 #endif /* !WITHOUT_USERAUTH */
520 		              );
521 	} else {
522 		rv = asprintf(&msg, "CONN: %s %s %s %s %s "
523 		              "sni:%s names:%s "
524 		              "sproto:%s:%s dproto:%s:%s "
525 		              "origcrt:%s usedcrt:%s"
526 #ifdef HAVE_LOCAL_PROCINFO
527 		              " %s"
528 #endif /* HAVE_LOCAL_PROCINFO */
529 #ifndef WITHOUT_USERAUTH
530 		              " user:%s"
531 #endif /* !WITHOUT_USERAUTH */
532 		              "\n",
533 		              ctx->proto == PROTO_AUTOSSL ? "autossl" : (ctx->proto == PROTO_POP3S ? "pop3s" : (ctx->proto == PROTO_SMTPS ? "smtps" : "ssl")),
534 		              STRORDASH(ctx->srchost_str),
535 		              STRORDASH(ctx->srcport_str),
536 		              STRORDASH(ctx->dsthost_str),
537 		              STRORDASH(ctx->dstport_str),
538 		              STRORDASH(ctx->sslctx->sni),
539 		              STRORDASH(ctx->sslctx->ssl_names),
540 		              SSL_get_version(ctx->src.ssl),
541 		              SSL_get_cipher(ctx->src.ssl),
542 		              STRORDASH(ctx->sslctx->srvdst_ssl_version),
543 		              STRORDASH(ctx->sslctx->srvdst_ssl_cipher),
544 		              STRORDASH(ctx->sslctx->origcrtfpr),
545 		              STRORDASH(ctx->sslctx->usedcrtfpr)
546 #ifdef HAVE_LOCAL_PROCINFO
547 		              , lpi
548 #endif /* HAVE_LOCAL_PROCINFO */
549 #ifndef WITHOUT_USERAUTH
550 		              , STRORDASH(ctx->user)
551 #endif /* !WITHOUT_USERAUTH */
552 		              );
553 	}
554 	if ((rv < 0) || !msg) {
555 		ctx->enomem = 1;
556 		goto out;
557 	}
558 	if (!ctx->global->detach) {
559 		log_err_printf("%s", msg);
560 	} else if (ctx->global->statslog) {
561 		if (log_conn(msg) == -1) {
562 			log_err_level_printf(LOG_WARNING, "Conn logging failed\n");
563 		}
564 	}
565 	if (ctx->global->connectlog) {
566 		if (log_connect_print_free(msg) == -1) {
567 			free(msg);
568 			log_err_level_printf(LOG_WARNING, "Connection logging failed\n");
569 		}
570 	} else {
571 		free(msg);
572 	}
573 out:
574 #ifdef HAVE_LOCAL_PROCINFO
575 	if (lpi && ctx->global->lprocinfo) {
576 		free(lpi);
577 	}
578 #endif /* HAVE_LOCAL_PROCINFO */
579 	return;
580 }
581 
582 static int NONNULL(1)
pxy_log_content_inbuf(pxy_conn_ctx_t * ctx,struct evbuffer * inbuf,int req)583 pxy_log_content_inbuf(pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, int req)
584 {
585 	if (!ctx->log_content && !ctx->log_pcap
586 #ifndef WITHOUT_MIRROR
587 		&& !ctx->log_mirror
588 #endif /* !WITHOUT_MIRROR */
589 		) {
590 		return 0;
591 	}
592 
593 	size_t sz = evbuffer_get_length(inbuf);
594 	unsigned char *buf = malloc(sz);
595 	if (!buf) {
596 		ctx->enomem = 1;
597 		return -1;
598 	}
599 	if (evbuffer_copyout(inbuf, buf, sz) == -1) {
600 		free(buf);
601 		return -1;
602 	}
603 	logbuf_t *lb = logbuf_new_alloc(sz, NULL);
604 	if (!lb) {
605 		free(buf);
606 		ctx->enomem = 1;
607 		return -1;
608 	}
609 	memcpy(lb->buf, buf, lb->sz);
610 	free(buf);
611 	if (log_content_submit(&ctx->logctx, lb, req, ctx->log_content, ctx->log_pcap
612 #ifndef WITHOUT_MIRROR
613 		, ctx->log_mirror
614 #endif /* !WITHOUT_MIRROR */
615 		) == -1) {
616 		logbuf_free(lb);
617 		log_err_level_printf(LOG_WARNING, "Content log submission failed\n");
618 		return -1;
619 	}
620 	return 0;
621 }
622 
623 #ifdef HAVE_LOCAL_PROCINFO
624 int
pxy_prepare_logging_local_procinfo(pxy_conn_ctx_t * ctx)625 pxy_prepare_logging_local_procinfo(pxy_conn_ctx_t *ctx)
626 {
627 	if (ctx->global->lprocinfo) {
628 		/* fetch process info */
629 		if (proc_pid_for_addr(&ctx->lproc.pid,
630 				(struct sockaddr*)&ctx->lproc.srcaddr,
631 				ctx->lproc.srcaddrlen) == 0 &&
632 			ctx->lproc.pid != -1 &&
633 			proc_get_info(ctx->lproc.pid,
634 						  &ctx->lproc.exec_path,
635 						  &ctx->lproc.uid,
636 						  &ctx->lproc.gid) == 0) {
637 			/* fetch user/group names */
638 			ctx->lproc.user = sys_user_str(
639 							ctx->lproc.uid);
640 			ctx->lproc.group = sys_group_str(
641 							ctx->lproc.gid);
642 			if (!ctx->lproc.user ||
643 				!ctx->lproc.group) {
644 				ctx->enomem = 1;
645 				pxy_conn_term(ctx, 1);
646 				return -1;
647 			}
648 		}
649 	}
650 	return 0;
651 }
652 #endif /* HAVE_LOCAL_PROCINFO */
653 
654 static int
pxy_prepare_logging(pxy_conn_ctx_t * ctx)655 pxy_prepare_logging(pxy_conn_ctx_t *ctx)
656 {
657 	/* prepare logging, part 2 */
658 #ifdef HAVE_LOCAL_PROCINFO
659 	if (WANT_CONNECT_LOG(ctx) || WANT_CONTENT_LOG(ctx)) {
660 		if (pxy_prepare_logging_local_procinfo(ctx) == -1) {
661 			return -1;
662 		}
663 	}
664 #endif /* HAVE_LOCAL_PROCINFO */
665 	if (WANT_CONTENT_LOG(ctx)) {
666 		if (log_content_open(&ctx->logctx, ctx->global,
667 							 (struct sockaddr *)&ctx->srcaddr,
668 							 ctx->srcaddrlen,
669 							 (struct sockaddr *)&ctx->dstaddr,
670 							 ctx->dstaddrlen,
671 							 STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str),
672 							 STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str),
673 #ifdef HAVE_LOCAL_PROCINFO
674 							 ctx->lproc.exec_path,
675 							 ctx->lproc.user,
676 							 ctx->lproc.group,
677 #else /* HAVE_LOCAL_PROCINFO */
678 							 NULL, NULL, NULL,
679 #endif /* HAVE_LOCAL_PROCINFO */
680 							 ctx->log_content, ctx->log_pcap
681 #ifndef WITHOUT_MIRROR
682 							 , ctx->log_mirror
683 #endif /* !WITHOUT_MIRROR */
684 		) == -1) {
685 			if (errno == ENOMEM)
686 				ctx->enomem = 1;
687 			pxy_conn_term(ctx, 1);
688 			return -1;
689 		}
690 	}
691 	return 0;
692 }
693 
694 static void NONNULL(1,2)
pxy_log_dbg_connect_type(pxy_conn_ctx_t * ctx,pxy_conn_desc_t * this)695 pxy_log_dbg_connect_type(pxy_conn_ctx_t *ctx, pxy_conn_desc_t *this)
696 {
697 	if (OPTS_DEBUG(ctx->global)) {
698 		if (this->ssl) {
699 			char *keystr;
700 			/* for SSL, we get two connect events */
701 			log_dbg_printf("%s connected to [%s]:%s %s %s\n",
702 						   protocol_names[ctx->proto],
703 						   STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str),
704 						   SSL_get_version(this->ssl), SSL_get_cipher(this->ssl));
705 			keystr = ssl_ssl_masterkey_to_str(this->ssl);
706 			if (keystr) {
707 				log_dbg_print_free(keystr);
708 			}
709 		} else {
710 			/* for TCP, we get only a dst connect event,
711 			 * since src was already connected from the
712 			 * beginning; mirror SSL debug output anyway
713 			 * in order not to confuse anyone who might be
714 			 * looking closely at the output */
715 			log_dbg_printf("%s connected to [%s]:%s\n",
716 						   protocol_names[ctx->proto],
717 						   STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
718 			log_dbg_printf("%s connected from [%s]:%s\n",
719 						   protocol_names[ctx->proto],
720 						   STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str));
721 		}
722 	}
723 }
724 
725 void
pxy_log_connect_src(pxy_conn_ctx_t * ctx)726 pxy_log_connect_src(pxy_conn_ctx_t *ctx)
727 {
728 	/* log connection if we don't analyze any headers */
729 	if (!ctx->spec->http && WANT_CONNECT_LOG(ctx)) {
730 		pxy_log_connect_nonhttp(ctx);
731 	}
732 
733 	if (ctx->src.ssl && ctx->log_cert && ctx->global->certgendir) {
734 		/* write SSL certificates to gendir */
735 		protossl_srccert_write(ctx);
736 	}
737 
738 	if (protossl_log_masterkey(ctx, &ctx->src) == -1) {
739 		return;
740 	}
741 
742 	pxy_log_dbg_connect_type(ctx, &ctx->src);
743 }
744 
745 void
pxy_log_connect_srvdst(pxy_conn_ctx_t * ctx)746 pxy_log_connect_srvdst(pxy_conn_ctx_t *ctx)
747 {
748 	// @attention srvdst.bev may be NULL, if its writecb fires first
749 	if (ctx->srvdst.bev) {
750 		/* log connection if we don't analyze any headers */
751 		if (!ctx->srvdst.ssl && !ctx->spec->http && WANT_CONNECT_LOG(ctx)) {
752 			pxy_log_connect_nonhttp(ctx);
753 		}
754 
755 		if (protossl_log_masterkey(ctx, &ctx->srvdst) == -1) {
756 			return;
757 		}
758 
759 		pxy_log_dbg_connect_type(ctx, &ctx->srvdst);
760 	}
761 }
762 
763 static void
pxy_log_dbg_disconnect(pxy_conn_ctx_t * ctx)764 pxy_log_dbg_disconnect(pxy_conn_ctx_t *ctx)
765 {
766 	/* we only get a single disconnect event here for both connections */
767 	if (OPTS_DEBUG(ctx->global)) {
768 		log_dbg_printf("%s disconnected to [%s]:%s, fd=%d\n",
769 					   protocol_names[ctx->proto],
770 					   STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str), ctx->fd);
771 		log_dbg_printf("%s disconnected from [%s]:%s, fd=%d\n",
772 					   protocol_names[ctx->proto],
773 					   STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), ctx->fd);
774 	}
775 }
776 
777 static void
pxy_log_dbg_disconnect_child(pxy_conn_child_ctx_t * ctx)778 pxy_log_dbg_disconnect_child(pxy_conn_child_ctx_t *ctx)
779 {
780 	/* we only get a single disconnect event here for both connections */
781 	if (OPTS_DEBUG(ctx->conn->global)) {
782 		log_dbg_printf("Child %s disconnected to [%s]:%s, child fd=%d, fd=%d\n",
783 					   protocol_names[ctx->conn->proto],
784 					   STRORDASH(ctx->conn->dsthost_str), STRORDASH(ctx->conn->dstport_str), ctx->fd, ctx->conn->fd);
785 		log_dbg_printf("Child %s disconnected from [%s]:%s, child fd=%d, fd=%d\n",
786 					   protocol_names[ctx->conn->proto],
787 					   STRORDASH(ctx->conn->srchost_str), STRORDASH(ctx->conn->srcport_str), ctx->fd, ctx->conn->fd);
788 	}
789 }
790 
791 #ifdef DEBUG_PROXY
792 void
pxy_log_dbg_evbuf_info(pxy_conn_ctx_t * ctx,pxy_conn_desc_t * this,pxy_conn_desc_t * other)793 pxy_log_dbg_evbuf_info(pxy_conn_ctx_t *ctx, pxy_conn_desc_t *this, pxy_conn_desc_t *other)
794 {
795 	// This function is used by child conns too, they pass ctx->conn instead of ctx
796 	if (OPTS_DEBUG(ctx->global)) {
797 		log_dbg_printf("evbuffer size at EOF: i:%zu o:%zu i:%zu o:%zu\n",
798 						evbuffer_get_length(bufferevent_get_input(this->bev)),
799 						evbuffer_get_length(bufferevent_get_output(this->bev)),
800 						other->closed ? 0 : evbuffer_get_length(bufferevent_get_input(other->bev)),
801 						other->closed ? 0 : evbuffer_get_length(bufferevent_get_output(other->bev)));
802 	}
803 }
804 #endif /* DEBUG_PROXY */
805 
806 unsigned char *
pxy_malloc_packet(size_t sz,pxy_conn_ctx_t * ctx)807 pxy_malloc_packet(size_t sz, pxy_conn_ctx_t *ctx)
808 {
809 	unsigned char *packet = malloc(sz);
810 	if (!packet) {
811 		ctx->enomem = 1;
812 		return NULL;
813 	}
814 	return packet;
815 }
816 
817 #ifdef DEBUG_PROXY
818 char *bev_names[] = {
819 	"src",
820 	"dst",
821 	"srvdst",
822 	"NULL",
823 	"UNKWN"
824 };
825 
826 static char *
pxy_get_event_name(struct bufferevent * bev,pxy_conn_ctx_t * ctx)827 pxy_get_event_name(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
828 {
829 	if (bev == ctx->src.bev) {
830 		return bev_names[0];
831 	} else if (bev == ctx->dst.bev) {
832 		return bev_names[1];
833 	} else if (bev == ctx->srvdst.bev) {
834 		return bev_names[2];
835 	} else if (bev == NULL) {
836 		log_fine("event_name=NULL");
837 		return bev_names[3];
838 	} else {
839 		log_fine("event_name=UNKWN");
840 		return bev_names[4];
841 	}
842 }
843 #endif /* DEBUG_PROXY */
844 
845 void
pxy_try_set_watermark(struct bufferevent * bev,pxy_conn_ctx_t * ctx,struct bufferevent * other)846 pxy_try_set_watermark(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct bufferevent *other)
847 {
848 	if (evbuffer_get_length(bufferevent_get_output(other)) >= OUTBUF_LIMIT) {
849 		log_fine_va("%s", pxy_get_event_name(bev, ctx));
850 
851 		/* temporarily disable data source;
852 		 * set an appropriate watermark. */
853 		bufferevent_setwatermark(other, EV_WRITE, OUTBUF_LIMIT/2, OUTBUF_LIMIT);
854 		bufferevent_disable(bev, EV_READ);
855 		ctx->thr->set_watermarks++;
856 	}
857 }
858 
859 void
pxy_try_unset_watermark(struct bufferevent * bev,pxy_conn_ctx_t * ctx,pxy_conn_desc_t * other)860 pxy_try_unset_watermark(struct bufferevent *bev, pxy_conn_ctx_t *ctx, pxy_conn_desc_t *other)
861 {
862 	if (other->bev && !(bufferevent_get_enabled(other->bev) & EV_READ)) {
863 		log_fine_va("%s", pxy_get_event_name(bev, ctx));
864 
865 		/* data source temporarily disabled;
866 		 * re-enable and reset watermark to 0. */
867 		bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
868 		bufferevent_enable(other->bev, EV_READ);
869 		ctx->thr->unset_watermarks++;
870 	}
871 }
872 
873 void
pxy_discard_inbuf(struct bufferevent * bev)874 pxy_discard_inbuf(struct bufferevent *bev)
875 {
876 	struct evbuffer *inbuf = bufferevent_get_input(bev);
877 	size_t inbuf_size = evbuffer_get_length(inbuf);
878 
879 	log_dbg_printf("Warning: Drained %zu bytes (conn closed)\n", inbuf_size);
880 	evbuffer_drain(inbuf, inbuf_size);
881 }
882 
883 #ifdef DEBUG_PROXY
884 static void
pxy_insert_sslproxy_header(pxy_conn_ctx_t * ctx,unsigned char * packet,size_t * packet_size)885 pxy_insert_sslproxy_header(pxy_conn_ctx_t *ctx, unsigned char *packet, size_t *packet_size)
886 {
887 	log_finer("ENTER");
888 
889 	// @attention Cannot use string manipulation functions; we are dealing with binary arrays here, not NULL-terminated strings
890 	memmove(packet + ctx->sslproxy_header_len + 2, packet, *packet_size);
891 	memcpy(packet, ctx->sslproxy_header, ctx->sslproxy_header_len);
892 	memcpy(packet + ctx->sslproxy_header_len, "\r\n", 2);
893 	*packet_size += ctx->sslproxy_header_len + 2;
894 	ctx->sent_sslproxy_header = 1;
895 }
896 #endif /* DEBUG_PROXY */
897 
898 int
pxy_try_prepend_sslproxy_header(pxy_conn_ctx_t * ctx,struct evbuffer * inbuf,struct evbuffer * outbuf)899 pxy_try_prepend_sslproxy_header(pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, struct evbuffer *outbuf)
900 {
901 	log_finer("ENTER");
902 
903 	if (ctx->divert && !ctx->sent_sslproxy_header) {
904 #ifdef DEBUG_PROXY
905 		size_t packet_size = evbuffer_get_length(inbuf);
906 		// +2 for \r\n
907 		unsigned char *packet = pxy_malloc_packet(packet_size + ctx->sslproxy_header_len + 2, ctx);
908 		if (!packet) {
909 			return -1;
910 		}
911 
912 		evbuffer_remove(inbuf, packet, packet_size);
913 
914 		log_finest_va("ORIG packet, size=%zu:\n%.*s", packet_size, (int)packet_size, packet);
915 
916 		pxy_insert_sslproxy_header(ctx, packet, &packet_size);
917 		evbuffer_add(outbuf, packet, packet_size);
918 
919 		log_finest_va("NEW packet, size=%zu:\n%.*s", packet_size, (int)packet_size, packet);
920 
921 		free(packet);
922 	}
923 	else {
924 		evbuffer_add_buffer(outbuf, inbuf);
925 	}
926 #else /* DEBUG_PROXY */
927 		evbuffer_add_printf(outbuf, "%s\r\n", ctx->sslproxy_header);
928 		ctx->sent_sslproxy_header = 1;
929 	}
930 	evbuffer_add_buffer(outbuf, inbuf);
931 #endif /* !DEBUG_PROXY */
932 	return 0;
933 }
934 
935 void
pxy_try_remove_sslproxy_header(pxy_conn_child_ctx_t * ctx,unsigned char * packet,size_t * packet_size)936 pxy_try_remove_sslproxy_header(pxy_conn_child_ctx_t *ctx, unsigned char *packet, size_t *packet_size)
937 {
938 	// @attention Cannot use string manipulation functions; we are dealing with binary arrays here, not NULL-terminated strings
939 	unsigned char *pos = memmem(packet, *packet_size, ctx->conn->sslproxy_header, ctx->conn->sslproxy_header_len);
940 	if (pos) {
941 		log_finer("REMOVE");
942 		memmove(pos, pos + ctx->conn->sslproxy_header_len + 2, *packet_size - (pos - packet) - (ctx->conn->sslproxy_header_len + 2));
943 		*packet_size -= ctx->conn->sslproxy_header_len + 2;
944 		ctx->removed_sslproxy_header = 1;
945 	}
946 }
947 
948 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
949 #define getdtablecount() 0
950 
951 /*
952  * Copied from:
953  * opensmtpd-201801101641p1/openbsd-compat/imsg.c
954  *
955  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
956  *
957  * Permission to use, copy, modify, and distribute this software for any
958  * purpose with or without fee is hereby granted, provided that the above
959  * copyright notice and this permission notice appear in all copies.
960  *
961  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
962  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
963  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
964  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
965  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
966  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
967  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
968  */
969 static int
available_fds(unsigned int n)970 available_fds(unsigned int n)
971 {
972 	unsigned int i;
973 	int ret, fds[256];
974 
975 	if (n > (sizeof(fds)/sizeof(fds[0])))
976 		return -1;
977 
978 	ret = 0;
979 	for (i = 0; i < n; i++) {
980 		fds[i] = -1;
981 		if ((fds[i] = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
982 			ret = -1;
983 			break;
984 		}
985 	}
986 
987 	for (i = 0; i < n && fds[i] >= 0; i++)
988 		close(fds[i]);
989 
990 	return ret;
991 }
992 #endif /* __APPLE__ || __FreeBSD__ */
993 
994 #ifdef __linux__
995 /*
996  * Copied from:
997  * https://github.com/tmux/tmux/blob/master/compat/getdtablecount.c
998  *
999  * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
1000  *
1001  * Permission to use, copy, modify, and distribute this software for any
1002  * purpose with or without fee is hereby granted, provided that the above
1003  * copyright notice and this permission notice appear in all copies.
1004  *
1005  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1006  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1007  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1008  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1009  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
1010  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1011  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1012  */
1013 int
getdtablecount()1014 getdtablecount()
1015 {
1016 	char path[PATH_MAX];
1017 	glob_t g;
1018 	int n = 0;
1019 
1020 	if (snprintf(path, sizeof path, "/proc/%ld/fd/*", (long)getpid()) < 0) {
1021 		log_err_level_printf(LOG_CRIT, "snprintf overflow\n");
1022 		return 0;
1023 	}
1024 	if (glob(path, 0, NULL, &g) == 0)
1025 		n = g.gl_pathc;
1026 	globfree(&g);
1027 	return n;
1028 }
1029 #endif /* __linux__ */
1030 
1031 /*
1032  * Check if we are out of file descriptors to close the conn, or else libevent will crash us
1033  * @attention We cannot guess the number of children in a connection at conn setup time. So, FD_RESERVE is just a ball park figure.
1034  * But what if a connection passes the check below, but eventually tries to create more children than FD_RESERVE allows for? This will crash us the same.
1035  * Beware, this applies to all current conns, not just the last connection setup.
1036  * For example, 20x conns pass the check below before creating any children, at which point we reach the last FD_RESERVE fds,
1037  * then they all start creating children, which crashes us again.
1038  * So, no matter how large an FD_RESERVE we choose, there will always be a risk of running out of fds, if we check the number of fds during parent conn setup only.
1039  * If we are left with less than FD_RESERVE fds, we should not create more children than FD_RESERVE allows for either.
1040  * Therefore, we check if we are out of fds in pxy_listener_acceptcb_child() and close the conn there too.
1041  * @attention These checks are expected to slow us further down, but it is critical to avoid a crash in case we run out of fds.
1042  */
1043 static int
check_fd_usage(pxy_conn_ctx_t * ctx)1044 check_fd_usage(
1045 #ifdef DEBUG_PROXY
1046 	pxy_conn_ctx_t *ctx
1047 #endif /* DEBUG_PROXY */
1048 	)
1049 {
1050 	int dtable_count = getdtablecount();
1051 
1052 	log_finer_va("descriptor_table_size=%d, dtablecount=%d, reserve=%d", descriptor_table_size, dtable_count, FD_RESERVE);
1053 
1054 	if (dtable_count + FD_RESERVE >= descriptor_table_size) {
1055 		goto out;
1056 	}
1057 
1058 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
1059 	if (available_fds(FD_RESERVE) == -1) {
1060 		goto out;
1061 	}
1062 #endif /* __APPLE__ || __FreeBSD__ */
1063 
1064 	return 0;
1065 out:
1066 	errno = EMFILE;
1067 	log_err_level_printf(LOG_CRIT, "Out of file descriptors\n");
1068 	return -1;
1069 }
1070 
1071 /*
1072  * Callback for accept events on the socket listener bufferevent.
1073  */
1074 static void
pxy_listener_acceptcb_child(UNUSED struct evconnlistener * listener,evutil_socket_t fd,UNUSED struct sockaddr * peeraddr,UNUSED int peeraddrlen,void * arg)1075 pxy_listener_acceptcb_child(UNUSED struct evconnlistener *listener, evutil_socket_t fd,
1076 							UNUSED struct sockaddr *peeraddr, UNUSED int peeraddrlen, void *arg)
1077 {
1078 	pxy_conn_ctx_t *ctx = arg;
1079 
1080 	ctx->atime = time(NULL);
1081 
1082 #ifdef DEBUG_PROXY
1083 	log_finest_va("ENTER, fd=%d, ctx->child_fd=%d", fd, ctx->child_fd);
1084 
1085 	char *host, *port;
1086 	if (sys_sockaddr_str(peeraddr, peeraddrlen, &host, &port) == 0) {
1087 		log_finest_va("peer addr=[%s]:%s, fd=%d", host, port, fd);
1088 		free(host);
1089 		free(port);
1090 	}
1091 #endif /* DEBUG_PROXY */
1092 
1093 	if (!ctx->dstaddrlen) {
1094 		log_err_level_printf(LOG_CRIT, "Child no target address; aborting connection\n");
1095 		evutil_closesocket(fd);
1096 		pxy_conn_term(ctx, 1);
1097 		goto out;
1098 	}
1099 
1100 	if (check_fd_usage(
1101 #ifdef DEBUG_PROXY
1102 			ctx
1103 #endif /* DEBUG_PROXY */
1104 			) == -1) {
1105 		evutil_closesocket(fd);
1106 		pxy_conn_term(ctx, 1);
1107 		goto out;
1108 	}
1109 
1110 	pxy_conn_child_ctx_t *child_ctx = pxy_conn_ctx_new_child(fd, ctx);
1111 	if (!child_ctx) {
1112 		log_err_level_printf(LOG_CRIT, "Error allocating memory\n");
1113 		evutil_closesocket(fd);
1114 		pxy_conn_term(ctx, 1);
1115 		goto out;
1116 	}
1117 
1118 	pxy_conn_attach_child(child_ctx);
1119 
1120 	// @attention Do not enable src events here yet, they will be enabled after dst connects
1121 	if (prototcp_setup_src_child(child_ctx) == -1) {
1122 		goto out;
1123 	}
1124 
1125 	// @attention fd (child_ctx->fd) is different from child event listener fd (ctx->child_fd)
1126 	ctx->thr->max_fd = max(ctx->thr->max_fd, child_ctx->fd);
1127 	ctx->child_src_fd = child_ctx->fd;
1128 
1129 	/* create server-side socket and eventbuffer */
1130 	// Children rely on the findings of parent
1131 	child_ctx->protoctx->connectcb(child_ctx);
1132 
1133 	if (ctx->term || ctx->enomem) {
1134 		goto out;
1135 	}
1136 
1137 	if (OPTS_DEBUG(ctx->global)) {
1138 		log_dbg_printf("Child connecting to [%s]:%s\n", STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
1139 	}
1140 
1141 	/* initiate connection, except for the first child conn which uses the parent's srvdst as dst */
1142 	if (child_ctx->dst.bev != ctx->srvdst.bev) {
1143 		if (bufferevent_socket_connect(child_ctx->dst.bev, (struct sockaddr *)&ctx->dstaddr, ctx->dstaddrlen) == -1) {
1144 			pxy_conn_term(ctx, 1);
1145 			goto out;
1146 		}
1147 	}
1148 
1149 	child_ctx->dst_fd = bufferevent_getfd(child_ctx->dst.bev);
1150 	ctx->child_dst_fd = child_ctx->dst_fd;
1151 	ctx->thr->max_fd = max(ctx->thr->max_fd, child_ctx->dst_fd);
1152 	// Do not return here, but continue and check term/enomem flags below
1153 out:
1154 	// @attention Do not use child_ctx->conn here, child_ctx may be uninitialized
1155 	// @attention Call pxy_conn_free() directly, not pxy_conn_term() here
1156 	// This is our last chance to close and free the conn
1157 	if (ctx->term || ctx->enomem) {
1158 		pxy_conn_free(ctx, ctx->term ? ctx->term_requestor : 1);
1159 	}
1160 }
1161 
1162 static int WUNRES NONNULL(1)
pxy_opensock_child(pxy_conn_ctx_t * ctx)1163 pxy_opensock_child(pxy_conn_ctx_t *ctx)
1164 {
1165 	evutil_socket_t fd = socket(ctx->spec->return_addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
1166 	if (fd == -1) {
1167 		log_err_level_printf(LOG_CRIT, "Error from socket(): %s (%i)\n", strerror(errno), errno);
1168 		log_fine_va("Error from socket(): %s (%i)", strerror(errno), errno);
1169 		evutil_closesocket(fd);
1170 		return -1;
1171 	}
1172 
1173 	if (evutil_make_socket_nonblocking(fd) == -1) {
1174 		log_err_level_printf(LOG_CRIT, "Error making socket nonblocking: %s (%i)\n", strerror(errno), errno);
1175 		log_fine_va("Error making socket nonblocking: %s (%i)", strerror(errno), errno);
1176 		evutil_closesocket(fd);
1177 		return -1;
1178 	}
1179 
1180 	int on = 1;
1181 	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on)) == -1) {
1182 		log_err_level_printf(LOG_CRIT, "Error from setsockopt(SO_KEEPALIVE): %s (%i)\n", strerror(errno), errno);
1183 		log_fine_va("Error from setsockopt(SO_KEEPALIVE): %s (%i)", strerror(errno), errno);
1184 		evutil_closesocket(fd);
1185 		return -1;
1186 	}
1187 
1188 	if (evutil_make_listen_socket_reuseable(fd) == -1) {
1189 		log_err_level_printf(LOG_CRIT, "Error from setsockopt(SO_REUSABLE): %s (%i)\n", strerror(errno), errno);
1190 		log_fine_va("Error from setsockopt(SO_REUSABLE): %s (%i)", strerror(errno), errno);
1191 		evutil_closesocket(fd);
1192 		return -1;
1193 	}
1194 
1195 	if (bind(fd, (struct sockaddr *)&ctx->spec->return_addr, ctx->spec->return_addrlen) == -1) {
1196 		log_err_level_printf(LOG_CRIT, "Error from bind(): %s (%i)\n", strerror(errno), errno);
1197 		log_fine_va("Error from bind(): %s (%i)", strerror(errno), errno);
1198 		evutil_closesocket(fd);
1199 		return -1;
1200 	}
1201 	return fd;
1202 }
1203 
1204 int
pxy_setup_child_listener(pxy_conn_ctx_t * ctx)1205 pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
1206 {
1207 	if (!ctx->divert) {
1208 		// split mode
1209 		return 0;
1210 	}
1211 
1212 	// @attention Defer child setup and evcl creation until after parent init is complete, otherwise (1) causes multithreading issues (proxy_listener_acceptcb is
1213 	// running on a different thread from the conn, and we only have thrmgr mutex), and (2) we need to clean up less upon errors.
1214 	// Child evcls use the evbase of the parent thread, otherwise we would get multithreading issues.
1215 	// We don't need a privsep call to open a socket for child listener,
1216 	// because listener port of child conns are assigned by the system, hence are from non-privileged range above 1024
1217 	ctx->child_fd = pxy_opensock_child(ctx);
1218 	if (ctx->child_fd < 0) {
1219 		log_err_level_printf(LOG_CRIT, "Error opening child socket: %s (%i)\n", strerror(errno), errno);
1220 		log_fine_va("Error opening child socket: %s (%i)", strerror(errno), errno);
1221 		pxy_conn_term(ctx, 1);
1222 		return -1;
1223 	}
1224 	ctx->thr->max_fd = max(ctx->thr->max_fd, ctx->child_fd);
1225 
1226 	// @attention Do not pass NULL as user-supplied pointer
1227 	struct evconnlistener *child_evcl = evconnlistener_new(ctx->thr->evbase, pxy_listener_acceptcb_child, ctx, LEV_OPT_CLOSE_ON_FREE, 1024, ctx->child_fd);
1228 	if (!child_evcl) {
1229 		log_err_level_printf(LOG_CRIT, "Error creating child evconnlistener: %s\n", strerror(errno));
1230 		log_fine_va("Error creating child evconnlistener: %s", strerror(errno));
1231 
1232 		// @attention Close child fd separately, because child evcl does not exist yet, hence fd would not be closed by calling pxy_conn_free()
1233 		evutil_closesocket(ctx->child_fd);
1234 		pxy_conn_term(ctx, 1);
1235 		return -1;
1236 	}
1237 	ctx->child_evcl = child_evcl;
1238 
1239 	evconnlistener_set_error_cb(child_evcl, proxy_listener_errorcb);
1240 
1241 	log_finer_va("Finished setting up child listener, child_fd=%d", ctx->child_fd);
1242 
1243 	struct sockaddr_in child_listener_addr;
1244 	socklen_t child_listener_len = sizeof(child_listener_addr);
1245 
1246 	if (getsockname(ctx->child_fd, (struct sockaddr *)&child_listener_addr, &child_listener_len) < 0) {
1247 		log_err_level_printf(LOG_CRIT, "Error in getsockname: %s\n", strerror(errno));
1248 		// @attention Do not close the child fd here, because child evcl exists now, hence pxy_conn_free() will close it while freeing child_evcl
1249 		pxy_conn_term(ctx, 1);
1250 		return -1;
1251 	}
1252 
1253 	// @todo Children are assumed to be listening on an IPv4 address, should we support IPv6 children?
1254 	char addr[INET_ADDRSTRLEN];
1255 	if (!inet_ntop(AF_INET, &child_listener_addr.sin_addr, addr, INET_ADDRSTRLEN)) {
1256 		pxy_conn_term(ctx, 1);
1257 		return -1;
1258 	}
1259 
1260 	// Port may be 4 or 5 chars long
1261 	unsigned int port = ntohs(child_listener_addr.sin_port);
1262 	size_t port_len = port < 10000 ? 4 : 5;
1263 
1264 #ifndef WITHOUT_USERAUTH
1265 	int user_len = 0;
1266 	if (ctx->conn_opts->user_auth && ctx->user) {
1267 		// +1 for comma
1268 		user_len = strlen(ctx->user) + 1;
1269 	}
1270 #endif /* !WITHOUT_USERAUTH */
1271 
1272 	// SSLproxy: [127.0.0.1]:34649,[192.168.3.24]:47286,[74.125.206.108]:465,s,soner
1273 	// SSLproxy:        +   + [ + addr         + ] + : + p        + , + [ + srchost_str              + ] + : + srcport_str              + , + [ + dsthost_str              + ] + : + dstport_str              + , + s + , + user
1274 	// SSLPROXY_KEY_LEN + 1 + 1 + strlen(addr) + 1 + 1 + port_len + 1 + 1 + strlen(ctx->srchost_str) + 1 + 1 + strlen(ctx->srcport_str) + 1 + 1 + strlen(ctx->dsthost_str) + 1 + 1 + strlen(ctx->dstport_str) + 1 + 1 + user_len
1275 	ctx->sslproxy_header_len = SSLPROXY_KEY_LEN + strlen(addr) + port_len + strlen(ctx->srchost_str) + strlen(ctx->srcport_str) + strlen(ctx->dsthost_str) + strlen(ctx->dstport_str) + 14
1276 #ifndef WITHOUT_USERAUTH
1277 			+ user_len
1278 #endif /* !WITHOUT_USERAUTH */
1279 			;
1280 
1281 	// +1 for NULL
1282 	ctx->sslproxy_header = malloc(ctx->sslproxy_header_len + 1);
1283 	if (!ctx->sslproxy_header) {
1284 		pxy_conn_term(ctx, 1);
1285 		return -1;
1286 	}
1287 
1288 	// printf(3): "snprintf() will write at most size-1 of the characters (the size'th character then gets the terminating NULL)"
1289 	// So, +1 for NULL
1290 	if (snprintf(ctx->sslproxy_header, ctx->sslproxy_header_len + 1, "%s [%s]:%u,[%s]:%s,[%s]:%s,%s"
1291 #ifndef WITHOUT_USERAUTH
1292 			"%s%s"
1293 #endif /* !WITHOUT_USERAUTH */
1294 			,
1295 			SSLPROXY_KEY, addr, port, STRORNONE(ctx->srchost_str), STRORNONE(ctx->srcport_str),
1296 			STRORNONE(ctx->dsthost_str), STRORNONE(ctx->dstport_str), ctx->spec->ssl ? "s":"p"
1297 #ifndef WITHOUT_USERAUTH
1298 			, user_len ? "," : "", user_len ? ctx->user : ""
1299 #endif /* !WITHOUT_USERAUTH */
1300 			) < 0) {
1301 		// ctx->sslproxy_header is freed by pxy_conn_ctx_free()
1302 		pxy_conn_term(ctx, 1);
1303 		return -1;
1304 	}
1305 	log_finer_va("sslproxy_header= %s", ctx->sslproxy_header);
1306 	return 0;
1307 }
1308 
1309 int
pxy_try_close_conn_end(pxy_conn_desc_t * conn_end,pxy_conn_ctx_t * ctx)1310 pxy_try_close_conn_end(pxy_conn_desc_t *conn_end, pxy_conn_ctx_t *ctx)
1311 {
1312 	/* if the other end is still open and doesn't have data
1313 	 * to send, close it, otherwise its writecb will close
1314 	 * it after writing what's left in the output buffer */
1315 	if (evbuffer_get_length(bufferevent_get_output(conn_end->bev)) == 0) {
1316 		log_finest("evbuffer_get_length(outbuf) == 0, terminate conn");
1317 		conn_end->free(conn_end->bev, ctx);
1318 		conn_end->bev = NULL;
1319 		conn_end->closed = 1;
1320 		return 1;
1321 	}
1322 	return 0;
1323 }
1324 
1325 void
pxy_try_disconnect(pxy_conn_ctx_t * ctx,pxy_conn_desc_t * this,pxy_conn_desc_t * other,int is_requestor)1326 pxy_try_disconnect(pxy_conn_ctx_t *ctx, pxy_conn_desc_t *this, pxy_conn_desc_t *other, int is_requestor)
1327 {
1328 	this->closed = 1;
1329 	this->free(this->bev, ctx);
1330 	this->bev = NULL;
1331 	if (other->closed) {
1332 		log_finest("other->closed, terminate conn");
1333 		// Uses only ctx to log disconnect, never any of the bevs
1334 		pxy_log_dbg_disconnect(ctx);
1335 		pxy_conn_term(ctx, is_requestor);
1336 	}
1337 }
1338 
1339 void
pxy_try_disconnect_child(pxy_conn_child_ctx_t * ctx,pxy_conn_desc_t * this,pxy_conn_desc_t * other)1340 pxy_try_disconnect_child(pxy_conn_child_ctx_t *ctx, pxy_conn_desc_t *this, pxy_conn_desc_t *other)
1341 {
1342 	this->closed = 1;
1343 	this->free(this->bev, ctx->conn);
1344 	this->bev = NULL;
1345 	if (other->closed) {
1346 		log_finest("other->closed, terminate conn");
1347 		// Uses only ctx to log disconnect, never any of the bevs
1348 		pxy_log_dbg_disconnect_child(ctx);
1349 		pxy_conn_term_child(ctx);
1350 	}
1351 }
1352 
1353 int
pxy_try_consume_last_input(struct bufferevent * bev,pxy_conn_ctx_t * ctx)1354 pxy_try_consume_last_input(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
1355 {
1356 	/* if there is data pending in the closed connection,
1357 	 * handle it here, otherwise it will be lost. */
1358 	if (evbuffer_get_length(bufferevent_get_input(bev))) {
1359 		log_fine("evbuffer_get_length(inbuf) > 0, terminate conn");
1360 
1361 		if (pxy_bev_readcb_preexec_logging_and_stats(bev, ctx) == -1) {
1362 			return -1;
1363 		}
1364 		ctx->protoctx->bev_readcb(bev, ctx);
1365 	}
1366 	return 0;
1367 }
1368 
1369 int
pxy_try_consume_last_input_child(struct bufferevent * bev,pxy_conn_child_ctx_t * ctx)1370 pxy_try_consume_last_input_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ctx)
1371 {
1372 	/* if there is data pending in the closed connection,
1373 	 * handle it here, otherwise it will be lost. */
1374 	if (evbuffer_get_length(bufferevent_get_input(bev))) {
1375 		log_fine("evbuffer_get_length(inbuf) > 0, terminate conn");
1376 
1377 		if (pxy_bev_readcb_preexec_logging_and_stats_child(bev, ctx) == -1) {
1378 			return -1;
1379 		}
1380 		ctx->protoctx->bev_readcb(bev, ctx);
1381 	}
1382 	return 0;
1383 }
1384 
1385 static int NONNULL(1)
pxy_set_dstaddr(pxy_conn_ctx_t * ctx)1386 pxy_set_dstaddr(pxy_conn_ctx_t *ctx)
1387 {
1388 	if (sys_sockaddr_str((struct sockaddr *)&ctx->dstaddr, ctx->dstaddrlen, &ctx->dsthost_str, &ctx->dstport_str) != 0) {
1389 		// sys_sockaddr_str() may fail due to either malloc() or getnameinfo()
1390 		ctx->enomem = 1;
1391 		pxy_conn_term(ctx, 1);
1392 		return -1;
1393 	}
1394 	return 0;
1395 }
1396 
1397 int
pxy_bev_readcb_preexec_logging_and_stats(struct bufferevent * bev,pxy_conn_ctx_t * ctx)1398 pxy_bev_readcb_preexec_logging_and_stats(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
1399 {
1400 	if (bev == ctx->src.bev || bev == ctx->dst.bev) {
1401 		struct evbuffer *inbuf = bufferevent_get_input(bev);
1402 		size_t inbuf_size = evbuffer_get_length(inbuf);
1403 
1404 		if (bev == ctx->src.bev) {
1405 			ctx->thr->intif_in_bytes += inbuf_size;
1406 		} else {
1407 			ctx->thr->intif_out_bytes += inbuf_size;
1408 		}
1409 
1410 		if (WANT_CONTENT_LOG(ctx->conn)) {
1411 			// HTTP content logging at this point may record certain header lines twice, if we have not seen all headers yet
1412 			return pxy_log_content_inbuf(ctx, inbuf, (bev == ctx->src.bev));
1413 		}
1414 	}
1415 	return 0;
1416 }
1417 
1418 /*
1419  * Callback for read events on the up- and downstream connection bufferevents.
1420  * Called when there is data ready in the input evbuffer.
1421  */
1422 void
pxy_bev_readcb(struct bufferevent * bev,void * arg)1423 pxy_bev_readcb(struct bufferevent *bev, void *arg)
1424 {
1425 	pxy_conn_ctx_t *ctx = arg;
1426 
1427 	if (pxy_bev_readcb_preexec_logging_and_stats(bev, ctx) == -1) {
1428 		goto out;
1429 	}
1430 
1431 	if (!ctx->connected) {
1432 		log_err_level(LOG_CRIT, "readcb called when not connected - aborting");
1433 		log_exceptcb();
1434 		return;
1435 	}
1436 
1437 	ctx->atime = time(NULL);
1438 	ctx->protoctx->bev_readcb(bev, ctx);
1439 
1440 out:
1441 	if (ctx->term || ctx->enomem) {
1442 		pxy_conn_free(ctx, ctx->term ? ctx->term_requestor : (bev == ctx->src.bev));
1443 	}
1444 }
1445 
1446 int
pxy_bev_readcb_preexec_logging_and_stats_child(struct bufferevent * bev,pxy_conn_child_ctx_t * ctx)1447 pxy_bev_readcb_preexec_logging_and_stats_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ctx)
1448 {
1449 	struct evbuffer *inbuf = bufferevent_get_input(bev);
1450 	size_t inbuf_size = evbuffer_get_length(inbuf);
1451 
1452 	if (bev == ctx->src.bev) {
1453 		ctx->conn->thr->extif_out_bytes += inbuf_size;
1454 	} else {
1455 		ctx->conn->thr->extif_in_bytes += inbuf_size;
1456 	}
1457 
1458 	if (WANT_CONTENT_LOG(ctx->conn)) {
1459 		return pxy_log_content_inbuf(ctx->conn, inbuf, (bev == ctx->src.bev));
1460 	}
1461 	return 0;
1462 }
1463 
1464 void
pxy_bev_readcb_child(struct bufferevent * bev,void * arg)1465 pxy_bev_readcb_child(struct bufferevent *bev, void *arg)
1466 {
1467 	pxy_conn_child_ctx_t *ctx = arg;
1468 
1469 	if (pxy_bev_readcb_preexec_logging_and_stats_child(bev, ctx) == -1) {
1470 		goto out;
1471 	}
1472 
1473 	if (!ctx->connected) {
1474 		log_err_level(LOG_CRIT, "readcb called when not connected - aborting");
1475 		log_exceptcb();
1476 		return;
1477 	}
1478 
1479 	ctx->conn->atime = time(NULL);
1480 	ctx->protoctx->bev_readcb(bev, ctx);
1481 
1482 out:
1483 	if (ctx->conn->term || ctx->conn->enomem) {
1484 		pxy_conn_free(ctx->conn, ctx->conn->term ? ctx->conn->term_requestor : (bev == ctx->src.bev));
1485 		return;
1486 	}
1487 
1488 	if (ctx->term) {
1489 		pxy_conn_free_child(ctx);
1490 	}
1491 }
1492 
1493 /*
1494  * Callback for write events on the up- and downstream connection bufferevents.
1495  * Called when either all data from the output evbuffer has been written,
1496  * or if the outbuf is only half full again after having been full.
1497  */
1498 void
pxy_bev_writecb(struct bufferevent * bev,void * arg)1499 pxy_bev_writecb(struct bufferevent *bev, void *arg)
1500 {
1501 	pxy_conn_ctx_t *ctx = arg;
1502 
1503 	ctx->atime = time(NULL);
1504 	ctx->protoctx->bev_writecb(bev, ctx);
1505 
1506 	if (ctx->term || ctx->enomem) {
1507 		pxy_conn_free(ctx, ctx->term ? ctx->term_requestor : (bev == ctx->src.bev));
1508 	}
1509 }
1510 
1511 void
pxy_bev_writecb_child(struct bufferevent * bev,void * arg)1512 pxy_bev_writecb_child(struct bufferevent *bev, void *arg)
1513 {
1514 	pxy_conn_child_ctx_t *ctx = arg;
1515 
1516 	ctx->conn->atime = time(NULL);
1517 	ctx->protoctx->bev_writecb(bev, ctx);
1518 
1519 	if (ctx->conn->term || ctx->conn->enomem) {
1520 		pxy_conn_free(ctx->conn, ctx->conn->term ? ctx->conn->term_requestor : (bev == ctx->src.bev));
1521 		return;
1522 	}
1523 
1524 	if (ctx->term) {
1525 		pxy_conn_free_child(ctx);
1526 	}
1527 }
1528 
1529 static int NONNULL(1,3)
pxy_bev_eventcb_postexec_logging_and_stats(struct bufferevent * bev,short events,pxy_conn_ctx_t * ctx)1530 pxy_bev_eventcb_postexec_logging_and_stats(struct bufferevent *bev, short events, pxy_conn_ctx_t *ctx)
1531 {
1532 	if (ctx->term || ctx->enomem) {
1533 		return -1;
1534 	}
1535 
1536 	if (events & BEV_EVENT_CONNECTED) {
1537 		// Passthrough proto does its own connect logging
1538 		if (ctx->proto != PROTO_PASSTHROUGH) {
1539 			if (bev == ctx->src.bev) {
1540 				// @todo When do we reach here? If proto is autossl? Otherwise, src is connected in acceptcb.
1541 				pxy_log_connect_src(ctx);
1542 			} else if (ctx->connected) {
1543 				if (pxy_prepare_logging(ctx) == -1) {
1544 					return -1;
1545 				}
1546 				// Doesn't log connect if proto is http, http proto does its own connect logging
1547 				pxy_log_connect_srvdst(ctx);
1548 			}
1549 		}
1550 
1551 		if (bev == ctx->srvdst.bev) {
1552 			ctx->thr->max_load = max(ctx->thr->max_load, ctx->thr->load);
1553 			ctx->thr->max_fd = max(ctx->thr->max_fd, ctx->fd);
1554 
1555 			// src and other fd stats are collected in acceptcb functions
1556 			ctx->srvdst_fd = bufferevent_getfd(ctx->srvdst.bev);
1557 			ctx->thr->max_fd = max(ctx->thr->max_fd, ctx->srvdst_fd);
1558 
1559 			// Passthrough proto may have a NULL dst.bev
1560 			if (ctx->dst.bev) {
1561 				ctx->dst_fd = bufferevent_getfd(ctx->dst.bev);
1562 				ctx->thr->max_fd = max(ctx->thr->max_fd, ctx->dst_fd);
1563 			}
1564 		}
1565 	}
1566 	return 0;
1567 }
1568 
1569 /*
1570  * Callback for meta events on the up- and downstream connection bufferevents.
1571  * Called when EOF has been reached, a connection has been made, and on errors.
1572  */
1573 void
pxy_bev_eventcb(struct bufferevent * bev,short events,void * arg)1574 pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg)
1575 {
1576 	pxy_conn_ctx_t *ctx = arg;
1577 
1578 	ctx->atime = time(NULL);
1579 
1580 	if (events & BEV_EVENT_ERROR) {
1581 		log_err_printf("Client-side BEV_EVENT_ERROR\n");
1582 		ctx->thr->errors++;
1583 	}
1584 
1585 	ctx->protoctx->bev_eventcb(bev, events, arg);
1586 
1587 	pxy_bev_eventcb_postexec_logging_and_stats(bev, events, ctx);
1588 
1589 	// Logging functions may set term or enomem too
1590 	// EOF eventcb may call readcb possibly causing enomem
1591 	if (ctx->term || ctx->enomem) {
1592 		pxy_conn_free(ctx, ctx->term ? ctx->term_requestor : (bev == ctx->src.bev));
1593 	}
1594 }
1595 
1596 void
pxy_bev_eventcb_postexec_stats_child(short events,pxy_conn_child_ctx_t * ctx)1597 pxy_bev_eventcb_postexec_stats_child(short events, pxy_conn_child_ctx_t *ctx)
1598 {
1599 	if (events & BEV_EVENT_CONNECTED) {
1600 		ctx->conn->thr->max_fd = max(ctx->conn->thr->max_fd, max(bufferevent_getfd(ctx->src.bev), bufferevent_getfd(ctx->dst.bev)));
1601 	}
1602 }
1603 
1604 void
pxy_bev_eventcb_child(struct bufferevent * bev,short events,void * arg)1605 pxy_bev_eventcb_child(struct bufferevent *bev, short events, void *arg)
1606 {
1607 	pxy_conn_child_ctx_t *ctx = arg;
1608 
1609 	ctx->conn->atime = time(NULL);
1610 
1611 	if (events & BEV_EVENT_ERROR) {
1612 		log_err_printf("Server-side BEV_EVENT_ERROR\n");
1613 		ctx->conn->thr->errors++;
1614 	}
1615 
1616 	// All child conns including this one will be freed if this child engages passthrough mode
1617 	// So save the vars used after eventcb call
1618 	pxy_conn_ctx_t *conn = ctx->conn;
1619 	unsigned int term_requestor = bev == ctx->src.bev;
1620 
1621 	ctx->protoctx->bev_eventcb(bev, events, arg);
1622 
1623 	// EOF eventcb may call readcb possibly causing enomem
1624 	if (conn->term || conn->enomem) {
1625 		pxy_conn_free(conn, conn->term ? conn->term_requestor : term_requestor);
1626 		return;
1627 	}
1628 
1629 	if (conn->children) {
1630 		if (ctx->term) {
1631 			pxy_conn_free_child(ctx);
1632 			return;
1633 		}
1634 
1635 		pxy_bev_eventcb_postexec_stats_child(events, ctx);
1636 	}
1637 }
1638 
1639 static filter_action_t * NONNULL(1,2)
pxy_conn_filter_match_ip(pxy_conn_ctx_t * ctx,filter_list_t * list)1640 pxy_conn_filter_match_ip(pxy_conn_ctx_t *ctx, filter_list_t *list)
1641 {
1642 	filter_site_t *site = filter_site_find(list->ip_btree, list->ip_acm, list->ip_all, ctx->dsthost_str);
1643 	if (!site)
1644 		return NULL;
1645 
1646 	log_fine_va("Found site (line=%d): %s for %s:%s, %s:%s", site->action.line_num, site->site,
1647 		STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
1648 
1649 	// Port spec determines the precedence of a site rule, unless the rule does not have any port
1650 	if (!site->port_btree && !site->port_acm && (site->action.precedence < ctx->filter_precedence)) {
1651 		log_finest_va("Rule precedence lower than conn filter precedence %d < %d (line=%d): %s, %s", site->action.precedence, ctx->filter_precedence, site->action.line_num, site->site, ctx->dsthost_str);
1652 		return NULL;
1653 	}
1654 
1655 #ifdef DEBUG_PROXY
1656 	if (site->all_sites)
1657 		log_finest_va("Match all dst (line=%d): %s, %s", site->action.line_num, site->site, ctx->dsthost_str);
1658 	else if (site->exact)
1659 		log_finest_va("Match exact with dst (line=%d): %s, %s", site->action.line_num, site->site, ctx->dsthost_str);
1660 	else
1661 		log_finest_va("Match substring in dst (line=%d): %s, %s", site->action.line_num, site->site, ctx->dsthost_str);
1662 #endif /* DEBUG_PROXY */
1663 
1664 	filter_action_t *port_action = pxy_conn_filter_port(ctx, site);
1665 	if (port_action)
1666 		return port_action;
1667 
1668 	return &site->action;
1669 }
1670 
1671 static filter_action_t * NONNULL(1,2)
pxy_conn_dsthost_filter(pxy_conn_ctx_t * ctx,filter_list_t * list)1672 pxy_conn_dsthost_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
1673 {
1674 	if (ctx->dsthost_str) {
1675 		filter_action_t *action;
1676 		if ((action = pxy_conn_filter_match_ip(ctx, list)))
1677 			return pxy_conn_set_filter_action(action, NULL
1678 #ifdef DEBUG_PROXY
1679 					, ctx, ctx->dsthost_str, NULL
1680 #endif /* DEBUG_PROXY */
1681 					);
1682 
1683 		log_finest_va("No filter match with ip: %s:%s, %s:%s",
1684 			STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
1685 	}
1686 	return NULL;
1687 }
1688 
1689 int
pxy_conn_apply_filter(pxy_conn_ctx_t * ctx,unsigned int defer_action)1690 pxy_conn_apply_filter(pxy_conn_ctx_t *ctx, unsigned int defer_action)
1691 {
1692 	int rv = 0;
1693 	filter_action_t *a;
1694 	if ((a = pxy_conn_filter(ctx, pxy_conn_dsthost_filter))) {
1695 		unsigned int action = pxy_conn_translate_filter_action(ctx, a);
1696 
1697 		ctx->filter_precedence = action & FILTER_PRECEDENCE;
1698 
1699 		// If we reach here, the matching filtering rule must have a higher precedence
1700 		// Override any deferred action, if the current rule action is not match
1701 		// Match action cannot override other filter actions
1702 
1703 		if (action & FILTER_ACTION_DIVERT) {
1704 			ctx->deferred_action = FILTER_ACTION_NONE;
1705 			ctx->divert = 1;
1706 		}
1707 		else if (action & FILTER_ACTION_SPLIT) {
1708 			ctx->deferred_action = FILTER_ACTION_NONE;
1709 			ctx->divert = 0;
1710 		}
1711 		else if (action & FILTER_ACTION_PASS) {
1712 			if (defer_action & FILTER_ACTION_PASS) {
1713 				log_fine("Deferring pass action");
1714 				ctx->deferred_action = FILTER_ACTION_PASS;
1715 			}
1716 			else {
1717 				ctx->deferred_action = FILTER_ACTION_NONE;
1718 				protopassthrough_engage(ctx);
1719 				ctx->pass = 1;
1720 				rv = 1;
1721 			}
1722 		}
1723 		else if (action & FILTER_ACTION_BLOCK) {
1724 			if (defer_action & FILTER_ACTION_BLOCK) {
1725 				// This block action should override any deferred pass action,
1726 				// because the current rule must have a higher precedence
1727 				log_fine("Deferring block action");
1728 				ctx->deferred_action = FILTER_ACTION_BLOCK;
1729 			}
1730 			else {
1731 				pxy_conn_term(ctx, 1);
1732 				rv = 1;
1733 			}
1734 		}
1735 		//else { /* FILTER_ACTION_MATCH */ }
1736 
1737 		// Filtering rules at higher precedence can enable/disable logging
1738 		if (action & FILTER_LOG_CONNECT)
1739 			ctx->log_connect = 1;
1740 		else if (action & FILTER_LOG_NOCONNECT)
1741 			ctx->log_connect = 0;
1742 		if (action & FILTER_LOG_MASTER)
1743 			ctx->log_master = 1;
1744 		else if (action & FILTER_LOG_NOMASTER)
1745 			ctx->log_master = 0;
1746 		if (action & FILTER_LOG_CERT)
1747 			ctx->log_cert = 1;
1748 		else if (action & FILTER_LOG_NOCERT)
1749 			ctx->log_cert = 0;
1750 		if (action & FILTER_LOG_CONTENT)
1751 			ctx->log_content = 1;
1752 		else if (action & FILTER_LOG_NOCONTENT)
1753 			ctx->log_content = 0;
1754 		if (action & FILTER_LOG_PCAP)
1755 			ctx->log_pcap = 1;
1756 		else if (action & FILTER_LOG_NOPCAP)
1757 			ctx->log_pcap = 0;
1758 #ifndef WITHOUT_MIRROR
1759 		if (action & FILTER_LOG_MIRROR)
1760 			ctx->log_mirror = 1;
1761 		else if (action & FILTER_LOG_NOMIRROR)
1762 			ctx->log_mirror = 0;
1763 #endif /* !WITHOUT_MIRROR */
1764 
1765 		if (a->conn_opts)
1766 			ctx->conn_opts = a->conn_opts;
1767 	}
1768 	return rv;
1769 }
1770 
1771 /*
1772  * Complete the connection.  This gets called after finding out where to
1773  * connect to.
1774  */
1775 void
pxy_conn_connect(pxy_conn_ctx_t * ctx)1776 pxy_conn_connect(pxy_conn_ctx_t *ctx)
1777 {
1778 	log_finest("ENTER");
1779 
1780 	if (!ctx->dstaddrlen) {
1781 		log_err_level_printf(LOG_CRIT, "No target address; aborting connection\n");
1782 		evutil_closesocket(ctx->fd);
1783 		pxy_conn_ctx_free(ctx, 1);
1784 		return;
1785 	}
1786 
1787 	// This function may be called more than once for the same conn
1788 	// So, set the dstaddr only once
1789 	if (!ctx->dsthost_str && (pxy_set_dstaddr(ctx) == -1)) {
1790 		return;
1791 	}
1792 
1793 	// Apply dstip filter now, so we can replace the SSL/TLS configuration of the conn with the one in the matching filtering rule
1794 	// It does not matter if this function is called more than once for the same conn
1795 	// Defer any pass action until srvdst connected
1796 	// Defer any block action until HTTP filter application or the first src readcb of non-http proto
1797 	if (pxy_conn_apply_filter(ctx, FILTER_ACTION_PASS | FILTER_ACTION_BLOCK)) {
1798 		// We never reach here, since we defer pass and block actions
1799 		return;
1800 	}
1801 
1802 	if (OPTS_DEBUG(ctx->global)) {
1803 		log_dbg_printf("Connecting to [%s]:%s\n", ctx->dsthost_str, ctx->dstport_str);
1804 	}
1805 
1806 	if (ctx->protoctx->connectcb(ctx) == -1) {
1807 		// The return value of -1 from connectcb indicates that there was a fatal error before event callbacks were set, so we can terminate the connection.
1808 		// Otherwise, it is up to the event callbacks to terminate the connection.
1809 		if (ctx->term || ctx->enomem) {
1810 			pxy_conn_free(ctx, ctx->term ? ctx->term_requestor : 1);
1811 			return;
1812 		}
1813 	}
1814 
1815 	if (bufferevent_socket_connect(ctx->srvdst.bev, (struct sockaddr *)&ctx->dstaddr, ctx->dstaddrlen) == -1) {
1816 		log_err_level(LOG_CRIT, "bufferevent_socket_connect for srvdst failed");
1817 		pxy_conn_free(ctx, ctx->term ? ctx->term_requestor : 1);
1818 	}
1819 }
1820 
1821 #ifndef WITHOUT_USERAUTH
1822 #if defined(__OpenBSD__) || defined(__linux__)
1823 int
pxy_is_listuser(userlist_t * list,const char * user,pxy_conn_ctx_t * ctx,const char * listname)1824 pxy_is_listuser(userlist_t *list, const char *user
1825 #ifdef DEBUG_PROXY
1826 	, pxy_conn_ctx_t *ctx, const char *listname
1827 #endif /* DEBUG_PROXY */
1828 	)
1829 {
1830 	while (list) {
1831 		if (equal(user, list->user)) {
1832 			log_finest_va("User %s in %s", user, listname);
1833 			return 1;
1834 		}
1835 		list = list->next;
1836 	}
1837 	return 0;
1838 }
1839 
1840 void
pxy_classify_user(pxy_conn_ctx_t * ctx)1841 pxy_classify_user(pxy_conn_ctx_t *ctx)
1842 {
1843 	if (ctx->spec->opts->passusers && pxy_is_listuser(ctx->spec->opts->passusers, ctx->user
1844 #ifdef DEBUG_PROXY
1845 			, ctx, "PassUsers"
1846 #endif /* DEBUG_PROXY */
1847 			)) {
1848 		log_fine_va("User %s in PassUsers; engaging passthrough mode", ctx->user);
1849 		protopassthrough_engage(ctx);
1850 	} else if (ctx->spec->opts->divertusers && !pxy_is_listuser(ctx->spec->opts->divertusers, ctx->user
1851 #ifdef DEBUG_PROXY
1852 			, ctx, "DivertUsers"
1853 #endif /* DEBUG_PROXY */
1854 			)) {
1855 		log_fine_va("User %s not in DivertUsers; terminating connection", ctx->user);
1856 		pxy_conn_term(ctx, 1);
1857 	}
1858 }
1859 
1860 static void
identify_user(UNUSED evutil_socket_t fd,UNUSED short what,void * arg)1861 identify_user(UNUSED evutil_socket_t fd, UNUSED short what, void *arg)
1862 {
1863 	pxy_conn_ctx_t *ctx = arg;
1864 
1865 	log_finest("ENTER");
1866 
1867 	if (ctx->ev) {
1868 		event_free(ctx->ev);
1869 		ctx->ev = NULL;
1870 	}
1871 
1872 	if (ctx->identify_user_count++ >= 50) {
1873 		log_finest("Cannot get conn user");
1874 		goto redirect;
1875 	} else {
1876 		int rc;
1877 
1878 		// @todo Do we really need to reset the stmt, as we always reset while returning?
1879 		sqlite3_reset(ctx->thr->get_user);
1880 		sqlite3_bind_text(ctx->thr->get_user, 1, ctx->srchost_str, -1, NULL);
1881 		rc = sqlite3_step(ctx->thr->get_user);
1882 
1883 		// Retry in case we cannot acquire db file or database: SQLITE_BUSY or SQLITE_LOCKED respectively
1884 		if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) {
1885 			log_finest_va("User db busy or locked, retrying, count=%d", ctx->identify_user_count);
1886 
1887 			// Do not forget to reset sqlite stmt, or else the userdb may remain busy/locked
1888 			sqlite3_reset(ctx->thr->get_user);
1889 
1890 			ctx->ev = event_new(ctx->thr->evbase, -1, 0, identify_user, ctx);
1891 			if (!ctx->ev)
1892 				goto memout;
1893 			struct timeval retry_delay = {0, 100};
1894 			if (event_add(ctx->ev, &retry_delay) == -1)
1895 				goto memout;
1896 			return;
1897 		} else if (rc == SQLITE_DONE) {
1898 			log_finest("Conn has no user");
1899 			goto redirect;
1900 		} else if (rc == SQLITE_ROW) {
1901 			char *ether = (char *)sqlite3_column_text(ctx->thr->get_user, 1);
1902 			if (strncasecmp(ether, ctx->ether, 17)) {
1903 				log_finest_va("Ethernet addresses do not match, db=%s, arp cache=%s", ether, ctx->ether);
1904 				goto redirect;
1905 			}
1906 
1907 			log_finest_va("Passed ethernet address test, %s", ether);
1908 
1909 			ctx->idletime = time(NULL) - sqlite3_column_int(ctx->thr->get_user, 2);
1910 			if (ctx->idletime > ctx->conn_opts->user_timeout) {
1911 				log_finest_va("User entry timed out, idletime=%u", ctx->idletime);
1912 				goto redirect;
1913 			}
1914 
1915 			log_finest_va("Passed timeout test, idletime=%u", ctx->idletime);
1916 
1917 			ctx->user = strdup((char *)sqlite3_column_text(ctx->thr->get_user, 0));
1918 			// Desc is needed for filtering
1919 			ctx->desc = strdup((char *)sqlite3_column_text(ctx->thr->get_user, 3));
1920 			if (!ctx->user || !ctx->desc) {
1921 				goto memout;
1922 			}
1923 
1924 			log_finest_va("Conn user=%s, desc=%s", ctx->user, ctx->desc);
1925 
1926 			ctx->protoctx->classify_usercb(ctx);
1927 		}
1928 	}
1929 	log_finest("Passed user identification");
1930 redirect:
1931 	sqlite3_reset(ctx->thr->get_user);
1932 
1933 	if (ctx->ev) {
1934 		event_free(ctx->ev);
1935 		ctx->ev = NULL;
1936 	}
1937 	return;
1938 
1939 memout:
1940 	log_err_level_printf(LOG_CRIT, "Aborting connection user identification!\n");
1941 	pxy_conn_term(ctx, 1);
1942 }
1943 #endif /* __OpenBSD__ || __linux__ */
1944 
1945 #ifdef __linux__
1946 // Assume proc filesystem support
1947 #define ARP_CACHE "/proc/net/arp"
1948 
1949 /*
1950  * We do not care about multiple matches or expiration status of arp cache entries on Linux.
1951  */
1952 static int NONNULL(1)
get_client_ether(pxy_conn_ctx_t * ctx)1953 get_client_ether(pxy_conn_ctx_t *ctx)
1954 {
1955 	int rv = 0;
1956 
1957 	FILE *arp_cache = fopen(ARP_CACHE, "r");
1958 	if (!arp_cache) {
1959 		log_err_level_printf(LOG_CRIT, "Failed to open arp cache: \"" ARP_CACHE "\"\n");
1960 		return -1;
1961 	}
1962 
1963 	// Skip the first line, which contains the header
1964 	char header[1024];
1965 	if (!fgets(header, sizeof(header), arp_cache)) {
1966 		log_err_level_printf(LOG_CRIT, "Failed to skip arp cache header\n");
1967 		rv = -1;
1968 		goto out;
1969 	}
1970 
1971 	char ip[46], ether[18];
1972 	//192.168.0.1     0x1         0x2         00:50:56:2c:bf:e0     *        enp3s0f1
1973 	while (fscanf(arp_cache, "%45s %*s %*s %17s %*s %*s", ip, ether) == 2) {
1974 		if (!strncasecmp(ip, ctx->srchost_str, 45)) {
1975 			log_finest_va("Arp entry for %s: %s", ip, ether);
1976 			ctx->ether = strdup(ether);
1977 			rv = 1;
1978 			goto out;
1979 		}
1980 	}
1981 out:
1982 	fclose(arp_cache);
1983 	return rv;
1984 }
1985 #endif /* __linux__ */
1986 
1987 #ifdef __OpenBSD__
1988 /*
1989  * This is a modified version of the same function from OpenBSD sources,
1990  * which has a 3-clause BSD license.
1991  */
1992 static char *
ether_str(struct sockaddr_dl * sdl)1993 ether_str(struct sockaddr_dl *sdl)
1994 {
1995 	char hbuf[NI_MAXHOST];
1996 	u_char *cp;
1997 
1998 	if (sdl->sdl_alen) {
1999 		cp = (u_char *)LLADDR(sdl);
2000 		snprintf(hbuf, sizeof(hbuf), "%02x:%02x:%02x:%02x:%02x:%02x",
2001 			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
2002 		return strdup(hbuf);
2003 	} else {
2004 		return NULL;
2005 	}
2006 }
2007 
2008 /*
2009  * This is a modified version of a similar function from OpenBSD sources,
2010  * which has a 3-clause BSD license.
2011  */
2012 static int NONNULL(2)
get_client_ether(in_addr_t addr,pxy_conn_ctx_t * ctx)2013 get_client_ether(in_addr_t addr, pxy_conn_ctx_t *ctx)
2014 {
2015 	int mib[7];
2016 	size_t needed;
2017 	char *lim, *buf = NULL, *next;
2018 	struct rt_msghdr *rtm;
2019 	struct sockaddr_inarp *sin;
2020 	struct sockaddr_dl *sdl;
2021 	int found_entry = 0;
2022 	int rdomain = getrtable();
2023 
2024 	mib[0] = CTL_NET;
2025 	mib[1] = PF_ROUTE;
2026 	mib[2] = 0;
2027 	mib[3] = AF_INET;
2028 	mib[4] = NET_RT_FLAGS;
2029 	mib[5] = RTF_LLINFO;
2030 	mib[6] = rdomain;
2031 	while (1) {
2032 		if (sysctl(mib, 7, NULL, &needed, NULL, 0) == -1) {
2033 			log_err_level_printf(LOG_WARNING, "route-sysctl-estimate\n");
2034 		}
2035 		if (needed == 0) {
2036 			return found_entry;
2037 		}
2038 		if ((buf = realloc(buf, needed)) == NULL) {
2039 			return -1;
2040 		}
2041 		if (sysctl(mib, 7, buf, &needed, NULL, 0) == -1) {
2042 			if (errno == ENOMEM)
2043 				continue;
2044 			log_finest("actual retrieval of routing table");
2045 		}
2046 		lim = buf + needed;
2047 		break;
2048 	}
2049 
2050 	int expired = 0;
2051 	int incomplete = 0;
2052 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
2053 		rtm = (struct rt_msghdr *)next;
2054 		if (rtm->rtm_version != RTM_VERSION)
2055 			continue;
2056 		sin = (struct sockaddr_inarp *)(next + rtm->rtm_hdrlen);
2057 		sdl = (struct sockaddr_dl *)(sin + 1);
2058 		if (addr) {
2059 			if (addr != sin->sin_addr.s_addr)
2060 				continue;
2061 			found_entry++;
2062 		}
2063 
2064 		char *expire = NULL;
2065 		if (rtm->rtm_flags & (RTF_PERMANENT_ARP | RTF_LOCAL)) {
2066 			expire = "permanent";
2067 		} else if (rtm->rtm_rmx.rmx_expire == 0) {
2068 			expire = "static";
2069 		} else if (rtm->rtm_rmx.rmx_expire > time(NULL)) {
2070 			expire = "active";
2071 		} else {
2072 			expire = "expired";
2073 			expired++;
2074 		}
2075 
2076 		char *ether = ether_str(sdl);
2077 		if (ether) {
2078 			// Record the first unexpired complete entry
2079 			if (!ctx->ether && (found_entry - expired) == 1) {
2080 				log_finest_va("Arp entry for %s: %s", inet_ntoa(sin->sin_addr), ether);
2081 				// Dup before assignment because we free local var ether below
2082 				ctx->ether = strdup(ether);
2083 				// Do not care about multiple matches, return immediately
2084 				free(ether);
2085 				goto out;
2086 			}
2087 		} else {
2088 			incomplete++;
2089 		}
2090 
2091 		log_finest_va("Arp entry %u for %s: %s (%s)", found_entry, inet_ntoa(sin->sin_addr), ether ? ether : "incomplete", expire);
2092 
2093 		if (ether) {
2094 			free(ether);
2095 		}
2096 	}
2097 out:
2098 	free(buf);
2099 	return found_entry - expired - incomplete;
2100 }
2101 #endif /* __OpenBSD__ */
2102 
2103 void
pxy_userauth(pxy_conn_ctx_t * ctx)2104 pxy_userauth(pxy_conn_ctx_t *ctx)
2105 {
2106 	if (ctx->conn_opts->user_auth && !ctx->user) {
2107 #if defined(__OpenBSD__) || defined(__linux__)
2108 		int ec = get_client_ether(
2109 #if defined(__OpenBSD__)
2110 			((struct sockaddr_in *)&ctx->srcaddr)->sin_addr.s_addr,
2111 #endif /* __OpenBSD__ */
2112 			ctx);
2113 		if (ec == 1) {
2114 			identify_user(-1, 0, ctx);
2115 			return;
2116 		} else if (ec == 0) {
2117 			log_err_level_printf(LOG_CRIT, "Cannot find ethernet address of client IP address\n");
2118 		} else if (ec > 1) {
2119 			// get_client_ether() does not return multiple matches, but keep this in case a future version does
2120 			log_err_level_printf(LOG_CRIT, "Multiple ethernet addresses for the same client IP address\n");
2121 		} else {
2122 			// ec == -1
2123 			log_err_level_printf(LOG_CRIT, "Aborting connection setup (out of memory)!\n");
2124 		}
2125 #endif /* __OpenBSD__ || __linux__ */
2126 		log_err_level_printf(LOG_CRIT, "Aborting connection setup (user auth)!\n");
2127 		pxy_conn_term(ctx, 1);
2128 	}
2129 }
2130 #endif /* !WITHOUT_USERAUTH */
2131 
2132 int
pxy_conn_apply_deferred_block_action(pxy_conn_ctx_t * ctx)2133 pxy_conn_apply_deferred_block_action(pxy_conn_ctx_t *ctx)
2134 {
2135 	if (ctx->deferred_action & FILTER_ACTION_BLOCK) {
2136 		log_fine("Applying deferred block action");
2137 		pxy_conn_term(ctx, 1);
2138 		return 1;
2139 	}
2140 	return 0;
2141 }
2142 
2143 unsigned int
pxy_conn_translate_filter_action(pxy_conn_ctx_t * ctx,filter_action_t * a)2144 pxy_conn_translate_filter_action(pxy_conn_ctx_t *ctx, filter_action_t *a)
2145 {
2146 	unsigned int action = FILTER_ACTION_NONE;
2147 
2148 	if (a->divert) {
2149 		action = FILTER_ACTION_DIVERT;
2150 	}
2151 	else if (a->split) {
2152 		action = FILTER_ACTION_SPLIT;
2153 	}
2154 	else if (a->pass) {
2155 		// Ignore pass action if already in passthrough mode
2156 		if (!ctx->pass) {
2157 			action = FILTER_ACTION_PASS;
2158 		}
2159 	}
2160 	else if (a->block) {
2161 		action = FILTER_ACTION_BLOCK;
2162 	}
2163 	else if (a->match) {
2164 		action = FILTER_ACTION_MATCH;
2165 	}
2166 
2167 	// Multiple log actions can be defined, hence no 'else'
2168 	// 0: don't change, 1: disable, 2: enable
2169 	if (a->log_connect) {
2170 		action |= (a->log_connect % 2) ? FILTER_LOG_NOCONNECT : FILTER_LOG_CONNECT;
2171 	}
2172 	if (a->log_master) {
2173 		action |= (a->log_master % 2) ? FILTER_LOG_NOMASTER : FILTER_LOG_MASTER;
2174 	}
2175 	if (a->log_cert) {
2176 		action |= (a->log_cert % 2) ? FILTER_LOG_NOCERT : FILTER_LOG_CERT;
2177 	}
2178 	if (a->log_content) {
2179 		action |= (a->log_content % 2) ? FILTER_LOG_NOCONTENT : FILTER_LOG_CONTENT;
2180 	}
2181 	if (a->log_pcap) {
2182 		action |= (a->log_pcap % 2) ? FILTER_LOG_NOPCAP : FILTER_LOG_PCAP;
2183 	}
2184 #ifndef WITHOUT_MIRROR
2185 	if (a->log_mirror) {
2186 		action |= (a->log_mirror % 2) ? FILTER_LOG_NOMIRROR : FILTER_LOG_MIRROR;
2187 	}
2188 #endif /* !WITHOUT_MIRROR */
2189 
2190 	action |= a->precedence;
2191 
2192 	return action;
2193 }
2194 
2195 filter_action_t *
pxy_conn_set_filter_action(filter_action_t * a1,filter_action_t * a2,pxy_conn_ctx_t * ctx,char * s1,char * s2)2196 pxy_conn_set_filter_action(filter_action_t *a1, filter_action_t *a2
2197 #ifdef DEBUG_PROXY
2198 	, pxy_conn_ctx_t *ctx, char *s1, char *s2
2199 #endif /* DEBUG_PROXY */
2200 	)
2201 {
2202 	filter_action_t *a;
2203 #ifdef DEBUG_PROXY
2204 	char *site;
2205 #endif /* DEBUG_PROXY */
2206 
2207 	// a1 has precedence over a2, unless a2's precedence is higher
2208 	if (!a1 || (a1 &&  a2 && (a1->precedence < a2->precedence))) {
2209 		a = a2;
2210 #ifdef DEBUG_PROXY
2211 		site = s2;
2212 		if (a1 &&  a2 && (a1->precedence < a2->precedence))
2213 			log_finest_va("Rule 2 has higher precedence than rule 1: %d > %d (line=%d, %d), %s, %s", a2->precedence, a1->precedence, a2->line_num, a1->line_num, s2, s1);
2214 #endif /* DEBUG_PROXY */
2215 	} else {
2216 		a = a1;
2217 #ifdef DEBUG_PROXY
2218 		site = s1;
2219 #endif /* DEBUG_PROXY */
2220 	}
2221 
2222 #ifdef DEBUG_PROXY
2223 	if (a->divert) {
2224 		log_fine_va("Filter divert action for %s, precedence %d (line=%d)", site, a->precedence, a->line_num);
2225 	}
2226 	else if (a->split) {
2227 		log_fine_va("Filter split action for %s, precedence %d (line=%d)", site, a->precedence, a->line_num);
2228 	}
2229 	else if (a->pass) {
2230 		// Ignore pass action if already in passthrough mode
2231 		if (!ctx->pass) {
2232 			log_fine_va("Filter pass action for %s, precedence %d (line=%d)", site, a->precedence, a->line_num);
2233 		}
2234 	}
2235 	else if (a->block) {
2236 		log_fine_va("Filter block action for %s, precedence %d (line=%d)", site, a->precedence, a->line_num);
2237 	}
2238 	else if (a->match) {
2239 		log_fine_va("Filter match action for %s, precedence %d (line=%d)", site, a->precedence, a->line_num);
2240 	}
2241 
2242 	// Multiple log actions can be defined, hence no 'else'
2243 	// 0: don't change, 1: disable, 2: enable
2244 	if (a->log_connect) {
2245 		log_fine_va("Filter %s connect log for %s, precedence %d (line=%d)", a->log_connect % 2 ? "disable" : "enable", site, a->precedence, a->line_num);
2246 	}
2247 	if (a->log_master) {
2248 		log_fine_va("Filter %s master log for %s, precedence %d (line=%d)", a->log_master % 2 ? "disable" : "enable", site, a->precedence, a->line_num);
2249 	}
2250 	if (a->log_cert) {
2251 		log_fine_va("Filter %s cert log for %s, precedence %d (line=%d)", a->log_cert % 2 ? "disable" : "enable", site, a->precedence, a->line_num);
2252 	}
2253 	if (a->log_content) {
2254 		log_fine_va("Filter %s content log for %s, precedence %d (line=%d)", a->log_content % 2 ? "disable" : "enable", site, a->precedence, a->line_num);
2255 	}
2256 	if (a->log_pcap) {
2257 		log_fine_va("Filter %s pcap log for %s, precedence %d (line=%d)", a->log_pcap % 2 ? "disable" : "enable", site, a->precedence, a->line_num);
2258 	}
2259 #ifndef WITHOUT_MIRROR
2260 	if (a->log_mirror) {
2261 		log_fine_va("Filter %s mirror log for %s, precedence %d (line=%d)", a->log_mirror % 2 ? "disable" : "enable", site, a->precedence, a->line_num);
2262 	}
2263 #endif /* !WITHOUT_MIRROR */
2264 #endif /* DEBUG_PROXY */
2265 	return a;
2266 }
2267 
2268 static int NONNULL(1,2)
pxy_conn_filter_match_port(pxy_conn_ctx_t * ctx,filter_port_t * port)2269 pxy_conn_filter_match_port(pxy_conn_ctx_t *ctx, filter_port_t *port)
2270 {
2271 	if (port->action.precedence < ctx->filter_precedence) {
2272 		log_finest_va("Rule port precedence lower than conn filter precedence %d < %d (line=%d): %s, %s", port->action.precedence, ctx->filter_precedence, port->action.line_num, port->port, ctx->dsthost_str);
2273 		return 0;
2274 	}
2275 
2276 #ifdef DEBUG_PROXY
2277 	if (port->all_ports)
2278 		log_finest_va("Match all dst ports (line=%d): %s, %s", port->action.line_num, port->port, ctx->dstport_str);
2279 	else if (port->exact)
2280 		log_finest_va("Match exact with dst port (line=%d): %s, %s", port->action.line_num, port->port, ctx->dstport_str);
2281 	else
2282 		log_finest_va("Match substring in dst port (line=%d): %s, %s", port->action.line_num, port->port, ctx->dstport_str);
2283 #endif /* DEBUG_PROXY */
2284 
2285 	return 1;
2286 }
2287 
2288 filter_action_t *
pxy_conn_filter_port(pxy_conn_ctx_t * ctx,filter_site_t * site)2289 pxy_conn_filter_port(pxy_conn_ctx_t *ctx, filter_site_t *site)
2290 {
2291 	filter_port_t *port = filter_port_find(site, ctx->dstport_str);
2292 	if (port) {
2293 		log_fine_va("Found port (line=%d): %s for %s:%s, %s:%s", port->action.line_num, port->port,
2294 			STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
2295 		if (pxy_conn_filter_match_port(ctx, port))
2296 			return &port->action;
2297 	}
2298 	else
2299 		log_finest_va("No filter match with port: %s:%s, %s:%s",
2300 			STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
2301 
2302 	return NULL;
2303 }
2304 
2305 #ifndef WITHOUT_USERAUTH
2306 static filter_action_t *
pxy_conn_filter_user(pxy_conn_ctx_t * ctx,proto_filter_func_t filtercb,filter_user_t * user)2307 pxy_conn_filter_user(pxy_conn_ctx_t *ctx, proto_filter_func_t filtercb, filter_user_t *user)
2308 {
2309 	filter_action_t * action = NULL;
2310 	if (user) {
2311 		if (ctx->desc) {
2312 			log_finest_va("Searching user keyword exact: %s, %s", ctx->user, ctx->desc);
2313 			filter_desc_t *keyword = filter_desc_exact_match(user->desc_btree, ctx->desc);
2314 			if (keyword && (action = filtercb(ctx, keyword->list))) {
2315 				return action;
2316 			}
2317 
2318 			log_finest_va("Searching user keyword substring: %s, %s", ctx->user, ctx->desc);
2319 			keyword = filter_desc_substring_match(user->desc_acm, ctx->desc);
2320 			if (keyword && (action = filtercb(ctx, keyword->list))) {
2321 				return action;
2322 			}
2323 		}
2324 		if ((action = filtercb(ctx, user->list))) {
2325 			return action;
2326 		}
2327 	}
2328 	return action;
2329 }
2330 #endif /* !WITHOUT_USERAUTH */
2331 
2332 filter_action_t *
pxy_conn_filter(pxy_conn_ctx_t * ctx,proto_filter_func_t filtercb)2333 pxy_conn_filter(pxy_conn_ctx_t *ctx, proto_filter_func_t filtercb)
2334 {
2335 	filter_action_t * action = NULL;
2336 
2337 	filter_t *filter = ctx->spec->opts->filter;
2338 	if (filter) {
2339 #ifndef WITHOUT_USERAUTH
2340 		if (ctx->user) {
2341 			log_finest_va("Searching user exact: %s", ctx->user);
2342 			filter_user_t *user = filter_user_exact_match(filter->user_btree, ctx->user);
2343 			if ((action = pxy_conn_filter_user(ctx, filtercb, user)))
2344 				return action;
2345 
2346 			log_finest_va("Searching user substring: %s", ctx->user);
2347 			user = filter_user_substring_match(filter->user_acm, ctx->user);
2348 			if ((action = pxy_conn_filter_user(ctx, filtercb, user)))
2349 				return action;
2350 
2351 			if (ctx->desc) {
2352 				log_finest_va("Searching keyword exact: %s", ctx->desc);
2353 				filter_desc_t *keyword = filter_desc_exact_match(filter->desc_btree, ctx->desc);
2354 				if (keyword && (action = filtercb(ctx, keyword->list))) {
2355 					return action;
2356 				}
2357 
2358 				log_finest_va("Searching keyword substring: %s, %s", ctx->user, ctx->desc);
2359 				keyword = filter_desc_substring_match(filter->desc_acm, ctx->desc);
2360 				if (keyword && (action = filtercb(ctx, keyword->list))) {
2361 					return action;
2362 				}
2363 			}
2364 
2365 			log_finest("Searching all_user");
2366 			if (filter->all_user && (action = filtercb(ctx, filter->all_user))) {
2367 				return action;
2368 			}
2369 		}
2370 #endif /* !WITHOUT_USERAUTH */
2371 		if (ctx->srchost_str) {
2372 			log_finest_va("Searching ip exact: %s", ctx->srchost_str);
2373 			filter_ip_t *ip = filter_ip_exact_match(filter->ip_btree, ctx->srchost_str);
2374 			if (ip && (action = filtercb(ctx, ip->list))) {
2375 				return action;
2376 			}
2377 
2378 			log_finest_va("Searching ip substring: %s", ctx->srchost_str);
2379 			ip = filter_ip_substring_match(filter->ip_acm, ctx->srchost_str);
2380 			if (ip && (action = filtercb(ctx, ip->list))) {
2381 				return action;
2382 			}
2383 		}
2384 
2385 		log_finest("Searching all");
2386 		if (filter->all && (action = filtercb(ctx, filter->all))) {
2387 			return action;
2388 		}
2389 	}
2390 	return action;
2391 }
2392 
2393 int
pxy_conn_init(pxy_conn_ctx_t * ctx)2394 pxy_conn_init(pxy_conn_ctx_t *ctx)
2395 {
2396 	log_finest("ENTER");
2397 
2398 	pxy_thr_attach(ctx);
2399 
2400 	ctx->ctime = time(NULL);
2401 	ctx->atime = ctx->ctime;
2402 
2403 	if (check_fd_usage(
2404 #ifdef DEBUG_PROXY
2405 			ctx
2406 #endif /* DEBUG_PROXY */
2407 			) == -1) {
2408 			goto out;
2409 	}
2410 
2411 	ctx->af = ctx->srcaddr.ss_family;
2412 
2413 	/* determine original destination of connection */
2414 	if (ctx->spec->natlookup) {
2415 		/* NAT engine lookup */
2416 		ctx->dstaddrlen = sizeof(struct sockaddr_storage);
2417 		if (ctx->spec->natlookup((struct sockaddr *)&ctx->dstaddr, &ctx->dstaddrlen, ctx->fd, (struct sockaddr *)&ctx->srcaddr, ctx->srcaddrlen) == -1) {
2418 			log_err_printf("Connection not found in NAT state table, aborting connection\n");
2419 			goto out;
2420 		}
2421 	} else if (ctx->spec->connect_addrlen > 0) {
2422 		/* static forwarding */
2423 		ctx->dstaddrlen = ctx->spec->connect_addrlen;
2424 		memcpy(&ctx->dstaddr, &ctx->spec->connect_addr, ctx->dstaddrlen);
2425 	} else {
2426 		/* SNI mode */
2427 		if (!ctx->spec->ssl) {
2428 			/* if this happens, the proxyspec parser is broken */
2429 			log_err_printf("SNI mode used for non-SSL connection; aborting connection\n");
2430 			goto out;
2431 		}
2432 	}
2433 
2434 	if (sys_sockaddr_str((struct sockaddr *)&ctx->srcaddr, ctx->srcaddrlen, &ctx->srchost_str, &ctx->srcport_str) != 0) {
2435 		log_err_level_printf(LOG_CRIT, "Aborting connection setup (out of memory)!\n");
2436 		goto out;
2437 	}
2438 	log_finest_va("srcaddr= [%s]:%s", ctx->srchost_str, ctx->srcport_str);
2439 	return 0;
2440 out:
2441 	evutil_closesocket(ctx->fd);
2442 	pxy_conn_ctx_free(ctx, 1);
2443 	return -1;
2444 }
2445 
2446 /* vim: set noet ft=c: */
2447