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 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "proxy.h"
30
31 #include "privsep.h"
32 #include "pxythrmgr.h"
33 #include "pxyconn.h"
34 #include "prototcp.h"
35 #include "protossl.h"
36 #include "protohttp.h"
37 #include "protopop3.h"
38 #include "protosmtp.h"
39 #include "protoautossl.h"
40 #include "cachemgr.h"
41 #include "opts.h"
42 #include "log.h"
43 #include "attrib.h"
44
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <signal.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <errno.h>
53
54 #include <event2/event.h>
55 #include <event2/listener.h>
56 #include <event2/bufferevent.h>
57 #include <event2/bufferevent_ssl.h>
58 #include <event2/buffer.h>
59 #include <event2/thread.h>
60
61 /*
62 * Proxy engine, built around libevent 2.x.
63 */
64
65 static int signals[] = { SIGTERM, SIGQUIT, SIGHUP, SIGINT, SIGPIPE, SIGUSR1 };
66
67 struct proxy_ctx {
68 pxy_thrmgr_ctx_t *thrmgr;
69 struct event_base *evbase;
70 struct event *sev[sizeof(signals)/sizeof(int)];
71 struct event *gcev;
72 struct proxy_listener_ctx *lctx;
73 global_t *global;
74 int loopbreak_reason;
75 };
76
77 static proxy_listener_ctx_t * MALLOC
proxy_listener_ctx_new(pxy_thrmgr_ctx_t * thrmgr,proxyspec_t * spec,global_t * global)78 proxy_listener_ctx_new(pxy_thrmgr_ctx_t *thrmgr, proxyspec_t *spec,
79 global_t *global)
80 {
81 proxy_listener_ctx_t *ctx = malloc(sizeof(proxy_listener_ctx_t));
82 if (!ctx)
83 return NULL;
84 memset(ctx, 0, sizeof(proxy_listener_ctx_t));
85 ctx->thrmgr = thrmgr;
86 ctx->spec = spec;
87 ctx->global = global;
88 return ctx;
89 }
90
91 static void NONNULL(1)
proxy_listener_ctx_free(proxy_listener_ctx_t * ctx)92 proxy_listener_ctx_free(proxy_listener_ctx_t *ctx)
93 {
94 if (ctx->evcl) {
95 evconnlistener_free(ctx->evcl);
96 }
97 if (ctx->next) {
98 proxy_listener_ctx_free(ctx->next);
99 }
100 free(ctx);
101 }
102
103 static protocol_t NONNULL(1)
proxy_setup_proto(pxy_conn_ctx_t * ctx)104 proxy_setup_proto(pxy_conn_ctx_t *ctx)
105 {
106 ctx->protoctx = malloc(sizeof(proto_ctx_t));
107 if (!ctx->protoctx) {
108 return PROTO_ERROR;
109 }
110 memset(ctx->protoctx, 0, sizeof(proto_ctx_t));
111
112 // Default to tcp
113 prototcp_setup(ctx);
114
115 protocol_t proto;
116 if (ctx->spec->upgrade) {
117 proto = protoautossl_setup(ctx);
118 } else if (ctx->spec->http) {
119 if (ctx->spec->ssl) {
120 proto = protohttps_setup(ctx);
121 } else {
122 proto = protohttp_setup(ctx);
123 }
124 } else if (ctx->spec->pop3) {
125 if (ctx->spec->ssl) {
126 proto = protopop3s_setup(ctx);
127 } else {
128 proto = protopop3_setup(ctx);
129 }
130 } else if (ctx->spec->smtp) {
131 if (ctx->spec->ssl) {
132 proto = protosmtps_setup(ctx);
133 } else {
134 proto = protosmtp_setup(ctx);
135 }
136 } else if (ctx->spec->ssl) {
137 proto = protossl_setup(ctx);
138 } else {
139 proto = PROTO_TCP;
140 }
141
142 if (proto == PROTO_ERROR) {
143 free(ctx->protoctx);
144 }
145 return proto;
146 }
147
148 pxy_conn_ctx_t *
proxy_conn_ctx_new(evutil_socket_t fd,pxy_thrmgr_ctx_t * thrmgr,proxyspec_t * spec,global_t * global,evutil_socket_t clisock)149 proxy_conn_ctx_new(evutil_socket_t fd,
150 pxy_thrmgr_ctx_t *thrmgr,
151 proxyspec_t *spec, global_t *global
152 #ifndef WITHOUT_USERAUTH
153 , evutil_socket_t clisock
154 #endif /* !WITHOUT_USERAUTH */
155 )
156 {
157 log_finest_main_va("ENTER, fd=%d", fd);
158
159 pxy_conn_ctx_t *ctx = malloc(sizeof(pxy_conn_ctx_t));
160 if (!ctx) {
161 return NULL;
162 }
163 memset(ctx, 0, sizeof(pxy_conn_ctx_t));
164
165 ctx->type = CONN_TYPE_PARENT;
166 #ifdef DEBUG_PROXY
167 ctx->id = thrmgr->conn_count++;
168 #endif /* DEBUG_PROXY */
169 ctx->conn = ctx;
170 ctx->fd = fd;
171 ctx->thrmgr = thrmgr;
172 ctx->spec = spec;
173 ctx->conn_opts = spec->conn_opts;
174 ctx->divert = spec->opts->divert;
175
176 // Enable all logging for conn if proxyspec does not have any filter
177 if (!spec->opts->filter) {
178 ctx->log_connect = 1;
179 ctx->log_master = 1;
180 ctx->log_cert = 1;
181 ctx->log_content = 1;
182 ctx->log_pcap = 1;
183 #ifndef WITHOUT_MIRROR
184 ctx->log_mirror = 1;
185 #endif /* !WITHOUT_MIRROR */
186 }
187
188 ctx->proto = proxy_setup_proto(ctx);
189 if (ctx->proto == PROTO_ERROR) {
190 free(ctx);
191 return NULL;
192 }
193
194 ctx->global = global;
195 #ifndef WITHOUT_USERAUTH
196 ctx->clisock = clisock;
197 #endif /* !WITHOUT_USERAUTH */
198
199 #ifdef HAVE_LOCAL_PROCINFO
200 ctx->lproc.pid = -1;
201 #endif /* HAVE_LOCAL_PROCINFO */
202
203 log_finest("Created new conn");
204 return ctx;
205 }
206
207 /*
208 * Does minimal clean-up, called on error by proxy_listener_acceptcb() only.
209 * We call this function instead of pxy_conn_ctx_free(), because
210 * proxy_listener_acceptcb() runs on thrmgr, whereas pxy_conn_ctx_free()
211 * runs on conn handling thr. This is necessary to prevent multithreading issues.
212 */
213 static void NONNULL(1)
proxy_conn_ctx_free(pxy_conn_ctx_t * ctx)214 proxy_conn_ctx_free(pxy_conn_ctx_t *ctx)
215 {
216 log_finest("ENTER");
217
218 if (ctx->ev) {
219 event_free(ctx->ev);
220 }
221 // If the proto doesn't have special args, proto_free() callback is NULL
222 if (ctx->protoctx->proto_free) {
223 ctx->protoctx->proto_free(ctx);
224 }
225 free(ctx->protoctx);
226 free(ctx);
227 }
228
229 /*
230 * Callback for accept events on the socket listener bufferevent.
231 * Called when a new incoming connection has been accepted.
232 * Initiates the connection to the server. The incoming connection
233 * from the client is not being activated until we have a successful
234 * connection to the server, because we need the server's certificate
235 * in order to set up the SSL session to the client.
236 * For consistency, plain TCP works the same way, even if we could
237 * start reading from the client while waiting on the connection to
238 * the server to connect.
239 */
240 static void
proxy_listener_acceptcb(UNUSED struct evconnlistener * listener,evutil_socket_t fd,struct sockaddr * peeraddr,int peeraddrlen,void * arg)241 proxy_listener_acceptcb(UNUSED struct evconnlistener *listener,
242 evutil_socket_t fd,
243 struct sockaddr *peeraddr, int peeraddrlen,
244 void *arg)
245 {
246 proxy_listener_ctx_t *lctx = arg;
247
248 log_finest_main_va("ENTER, fd=%d", fd);
249
250 /* create per connection state */
251 pxy_conn_ctx_t *ctx = proxy_conn_ctx_new(fd, lctx->thrmgr, lctx->spec, lctx->global
252 #ifndef WITHOUT_USERAUTH
253 , lctx->clisock
254 #endif /* !WITHOUT_USERAUTH */
255 );
256 if (!ctx) {
257 log_err_level_printf(LOG_CRIT, "Error allocating ctx memory\n");
258 evutil_closesocket(fd);
259 return;
260 }
261
262 // Choose the conn handling thr
263 pxy_thrmgr_assign_thr(ctx);
264
265 /* prepare logging part 1 and user auth */
266 ctx->srcaddrlen = peeraddrlen;
267 memcpy(&ctx->srcaddr, peeraddr, ctx->srcaddrlen);
268
269 // Switch from thrmgr to connection handling thread, i.e. change the event base, asap
270 // This prevents possible multithreading issues between thrmgr and conn handling threads
271 ctx->ev = event_new(ctx->thr->evbase, -1, 0, ctx->protoctx->init_conn, ctx);
272 if (!ctx->ev) {
273 log_err_level(LOG_CRIT, "Error creating initial event, aborting connection");
274 goto out;
275 }
276 // The only purpose of this event is to change the event base, so it is a one-shot event
277 if (event_add(ctx->ev, NULL) == -1)
278 goto out;
279 event_active(ctx->ev, 0, 0);
280 return;
281 out:
282 evutil_closesocket(fd);
283 proxy_conn_ctx_free(ctx);
284 }
285
286 /*
287 * Callback for error events on the socket listener bufferevent.
288 */
289 void
proxy_listener_errorcb(struct evconnlistener * listener,UNUSED void * arg)290 proxy_listener_errorcb(struct evconnlistener *listener, UNUSED void *arg)
291 {
292 struct event_base *evbase = evconnlistener_get_base(listener);
293 int err = EVUTIL_SOCKET_ERROR();
294 log_err_level_printf(LOG_CRIT, "Error %d on listener: %s\n", err,
295 evutil_socket_error_to_string(err));
296 /* Do not break the event loop if out of fds:
297 * Too many open files (24) */
298 if (err == 24) {
299 return;
300 }
301 event_base_loopbreak(evbase);
302 }
303
304 /*
305 * Dump a description of an evbase to debugging code.
306 */
307 static void
proxy_debug_base(const struct event_base * ev_base)308 proxy_debug_base(const struct event_base *ev_base)
309 {
310 log_dbg_printf("Using libevent backend '%s'\n",
311 event_base_get_method(ev_base));
312
313 enum event_method_feature f;
314 f = event_base_get_features(ev_base);
315 log_dbg_printf("Event base supports: edge %s, O(1) %s, anyfd %s\n",
316 ((f & EV_FEATURE_ET) ? "yes" : "no"),
317 ((f & EV_FEATURE_O1) ? "yes" : "no"),
318 ((f & EV_FEATURE_FDS) ? "yes" : "no"));
319 }
320
321 /*
322 * Set up the listener for a single proxyspec and add it to evbase.
323 * Returns the proxy_listener_ctx_t pointer if successful, NULL otherwise.
324 */
325 static proxy_listener_ctx_t *
proxy_listener_setup(struct event_base * evbase,pxy_thrmgr_ctx_t * thrmgr,proxyspec_t * spec,global_t * global,evutil_socket_t clisock)326 proxy_listener_setup(struct event_base *evbase, pxy_thrmgr_ctx_t *thrmgr,
327 proxyspec_t *spec, global_t *global, evutil_socket_t clisock)
328 {
329 log_finest_main("ENTER");
330
331 int fd;
332 if ((fd = privsep_client_opensock(clisock, spec)) == -1) {
333 log_err_level_printf(LOG_CRIT, "Error opening socket: %s (%i)\n",
334 strerror(errno), errno);
335 return NULL;
336 }
337
338 proxy_listener_ctx_t *lctx = proxy_listener_ctx_new(thrmgr, spec, global);
339 if (!lctx) {
340 log_err_level_printf(LOG_CRIT, "Error creating listener context\n");
341 evutil_closesocket(fd);
342 return NULL;
343 }
344
345 #ifndef WITHOUT_USERAUTH
346 lctx->clisock = clisock;
347 #endif /* !WITHOUT_USERAUTH */
348
349 // @attention Do not pass NULL as user-supplied pointer
350 lctx->evcl = evconnlistener_new(evbase, proxy_listener_acceptcb,
351 lctx, LEV_OPT_CLOSE_ON_FREE, 1024, fd);
352 if (!lctx->evcl) {
353 log_err_level_printf(LOG_CRIT, "Error creating evconnlistener: %s\n",
354 strerror(errno));
355 proxy_listener_ctx_free(lctx);
356 evutil_closesocket(fd);
357 return NULL;
358 }
359 evconnlistener_set_error_cb(lctx->evcl, proxy_listener_errorcb);
360 return lctx;
361 }
362
363 /*
364 * Signal handler for SIGTERM, SIGQUIT, SIGINT, SIGHUP, SIGPIPE and SIGUSR1.
365 */
366 static void
proxy_signal_cb(evutil_socket_t fd,UNUSED short what,void * arg)367 proxy_signal_cb(evutil_socket_t fd, UNUSED short what, void *arg)
368 {
369 proxy_ctx_t *ctx = arg;
370
371 if (OPTS_DEBUG(ctx->global)) {
372 log_dbg_printf("Received signal %i\n", fd);
373 }
374
375 switch(fd) {
376 case SIGTERM:
377 case SIGQUIT:
378 case SIGINT:
379 proxy_loopbreak(ctx, fd);
380 break;
381 case SIGHUP:
382 case SIGUSR1:
383 if (log_reopen() == -1) {
384 log_err_level_printf(LOG_WARNING, "Failed to reopen logs\n");
385 } else {
386 log_dbg_printf("Reopened log files\n");
387 }
388 break;
389 case SIGPIPE:
390 log_err_level_printf(LOG_WARNING, "Received SIGPIPE; ignoring.\n");
391 break;
392 default:
393 log_err_level_printf(LOG_WARNING, "Received unexpected signal %i\n", fd);
394 break;
395 }
396 }
397
398 /*
399 * Garbage collection handler.
400 */
401 static void
proxy_gc_cb(UNUSED evutil_socket_t fd,UNUSED short what,void * arg)402 proxy_gc_cb(UNUSED evutil_socket_t fd, UNUSED short what, void *arg)
403 {
404 proxy_ctx_t *ctx = arg;
405
406 if (OPTS_DEBUG(ctx->global))
407 log_dbg_printf("Garbage collecting caches started.\n");
408
409 cachemgr_gc();
410
411 if (OPTS_DEBUG(ctx->global))
412 log_dbg_printf("Garbage collecting caches done.\n");
413 }
414
415 /*
416 * Set up the core event loop.
417 * Socket clisock is the privsep client socket used for binding to ports.
418 * Returns ctx on success, or NULL on error.
419 */
420 proxy_ctx_t *
proxy_new(global_t * global,int clisock)421 proxy_new(global_t *global, int clisock)
422 {
423 proxy_listener_ctx_t *head;
424 proxy_ctx_t *ctx;
425 struct evdns_base *dnsbase;
426 int rc;
427
428 /* adds locking, only required if accessed from separate threads */
429 evthread_use_pthreads();
430
431 #ifndef PURIFY
432 if (OPTS_DEBUG(global)) {
433 event_enable_debug_mode();
434 }
435 #endif /* PURIFY */
436
437 ctx = malloc(sizeof(proxy_ctx_t));
438 if (!ctx) {
439 log_err_level_printf(LOG_CRIT, "Error allocating memory\n");
440 goto leave0;
441 }
442 memset(ctx, 0, sizeof(proxy_ctx_t));
443
444 ctx->global = global;
445 ctx->evbase = event_base_new();
446 if (!ctx->evbase) {
447 log_err_level_printf(LOG_CRIT, "Error getting event base\n");
448 goto leave1;
449 }
450
451 if (global_has_dns_spec(global)) {
452 /* create a dnsbase here purely for being able to test parsing
453 * resolv.conf while we can still alert the user about it. */
454 dnsbase = evdns_base_new(ctx->evbase, 0);
455 if (!dnsbase) {
456 log_err_level_printf(LOG_CRIT, "Error creating dns event base\n");
457 goto leave1b;
458 }
459 rc = evdns_base_resolv_conf_parse(dnsbase, DNS_OPTIONS_ALL,
460 "/etc/resolv.conf");
461 evdns_base_free(dnsbase, 0);
462 if (rc != 0) {
463 log_err_level_printf(LOG_CRIT, "evdns cannot parse resolv.conf: "
464 "%s (%d)\n",
465 rc == 1 ? "failed to open file" :
466 rc == 2 ? "failed to stat file" :
467 rc == 3 ? "file too large" :
468 rc == 4 ? "out of memory" :
469 rc == 5 ? "short read from file" :
470 rc == 6 ? "no nameservers in file" :
471 "unknown error", rc);
472 goto leave1b;
473 }
474 }
475
476 if (OPTS_DEBUG(global)) {
477 proxy_debug_base(ctx->evbase);
478 }
479
480 ctx->thrmgr = pxy_thrmgr_new(global);
481 if (!ctx->thrmgr) {
482 log_err_level_printf(LOG_CRIT, "Error creating thread manager\n");
483 goto leave1b;
484 }
485
486 head = ctx->lctx = NULL;
487 for (proxyspec_t *spec = global->spec; spec; spec = spec->next) {
488 head = proxy_listener_setup(ctx->evbase, ctx->thrmgr,
489 spec, global, clisock);
490 if (!head)
491 goto leave2;
492 head->next = ctx->lctx;
493 ctx->lctx = head;
494 }
495
496 for (size_t i = 0; i < (sizeof(signals) / sizeof(int)); i++) {
497 ctx->sev[i] = evsignal_new(ctx->evbase, signals[i],
498 proxy_signal_cb, ctx);
499 if (!ctx->sev[i])
500 goto leave3;
501 evsignal_add(ctx->sev[i], NULL);
502 }
503
504 struct timeval gc_delay = {60, 0};
505 ctx->gcev = event_new(ctx->evbase, -1, EV_PERSIST, proxy_gc_cb, ctx);
506 if (!ctx->gcev)
507 goto leave4;
508 evtimer_add(ctx->gcev, &gc_delay);
509
510 // @attention Do not close privsep sock if the USERAUTH feature is compiled in, we use it to update user atime
511 #ifdef WITHOUT_USERAUTH
512 privsep_client_close(clisock);
513 #endif /* !WITHOUT_USERAUTH */
514 return ctx;
515
516 leave4:
517 if (ctx->gcev) {
518 event_free(ctx->gcev);
519 }
520
521 leave3:
522 for (size_t i = 0; i < (sizeof(ctx->sev) / sizeof(ctx->sev[0])); i++) {
523 if (ctx->sev[i]) {
524 event_free(ctx->sev[i]);
525 }
526 }
527 leave2:
528 if (ctx->lctx) {
529 proxy_listener_ctx_free(ctx->lctx);
530 }
531 pxy_thrmgr_free(ctx->thrmgr);
532 leave1b:
533 event_base_free(ctx->evbase);
534 leave1:
535 free(ctx);
536 leave0:
537 return NULL;
538 }
539
540 /*
541 * Run the event loop.
542 * Returns 0 on non-signal termination, signal number when the event loop was
543 * canceled by a signal, or -1 on failure.
544 */
545 int
proxy_run(proxy_ctx_t * ctx)546 proxy_run(proxy_ctx_t *ctx)
547 {
548 if (ctx->global->detach) {
549 event_reinit(ctx->evbase);
550 }
551 #ifndef PURIFY
552 if (OPTS_DEBUG(ctx->global)) {
553 event_base_dump_events(ctx->evbase, stderr);
554 }
555 #endif /* PURIFY */
556 if (pxy_thrmgr_run(ctx->thrmgr) == -1) {
557 log_err_level_printf(LOG_CRIT, "Failed to start thread manager\n");
558 return -1;
559 }
560 if (OPTS_DEBUG(ctx->global)) {
561 log_dbg_printf("Starting main event loop.\n");
562 }
563 event_base_dispatch(ctx->evbase);
564 if (OPTS_DEBUG(ctx->global)) {
565 log_dbg_printf("Main event loop stopped (reason=%i).\n",
566 ctx->loopbreak_reason);
567 }
568 return ctx->loopbreak_reason;
569 }
570
571 /*
572 * Break the loop of the proxy, causing the proxy_run to return, returning
573 * the reason given in reason (signal number, 0 for success, -1 for error).
574 */
575 void
proxy_loopbreak(proxy_ctx_t * ctx,int reason)576 proxy_loopbreak(proxy_ctx_t *ctx, int reason)
577 {
578 ctx->loopbreak_reason = reason;
579 event_base_loopbreak(ctx->evbase);
580 }
581
582 /*
583 * Free the proxy data structures.
584 */
585 void
proxy_free(proxy_ctx_t * ctx)586 proxy_free(proxy_ctx_t *ctx)
587 {
588 if (ctx->gcev) {
589 event_free(ctx->gcev);
590 }
591 if (ctx->lctx) {
592 proxy_listener_ctx_free(ctx->lctx);
593 }
594 for (size_t i = 0; i < (sizeof(ctx->sev) / sizeof(ctx->sev[0])); i++) {
595 if (ctx->sev[i]) {
596 event_free(ctx->sev[i]);
597 }
598 }
599 if (ctx->thrmgr) {
600 pxy_thrmgr_free(ctx->thrmgr);
601 }
602 if (ctx->evbase) {
603 event_base_free(ctx->evbase);
604 }
605 free(ctx);
606 }
607
608 /* vim: set noet ft=c: */
609