xref: /openbsd-src/usr.sbin/ftp-proxy/ftp-proxy.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: ftp-proxy.c,v 1.35 2016/09/15 16:16:03 jca Exp $ */
2 
3 /*
4  * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/queue.h>
20 #include <sys/types.h>
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 #include <sys/socket.h>
24 
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <net/if.h>
28 #include <net/pfvar.h>
29 
30 #include <err.h>
31 #include <errno.h>
32 #include <event.h>
33 #include <fcntl.h>
34 #include <netdb.h>
35 #include <paths.h>
36 #include <pwd.h>
37 #include <signal.h>
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <unistd.h>
44 #include <vis.h>
45 
46 #include "filter.h"
47 
48 #define CONNECT_TIMEOUT	30
49 #define MIN_PORT	1024
50 #define MAX_LINE	500
51 #define MAX_LOGLINE	300
52 #define NTOP_BUFS	3
53 #define TCP_BACKLOG	10
54 
55 #define CHROOT_DIR	"/var/empty"
56 #define NOPRIV_USER	"_ftp_proxy"
57 
58 /* pfctl standard NAT range. */
59 #define PF_NAT_PROXY_PORT_LOW	50001
60 #define PF_NAT_PROXY_PORT_HIGH	65535
61 
62 #define	sstosa(ss)	((struct sockaddr *)(ss))
63 
64 enum { CMD_NONE = 0, CMD_PORT, CMD_EPRT, CMD_PASV, CMD_EPSV };
65 
66 struct session {
67 	u_int32_t		 id;
68 	struct sockaddr_storage  client_ss;
69 	struct sockaddr_storage  proxy_ss;
70 	struct sockaddr_storage  server_ss;
71 	struct sockaddr_storage  orig_server_ss;
72 	struct bufferevent	*client_bufev;
73 	struct bufferevent	*server_bufev;
74 	int			 client_fd;
75 	int			 server_fd;
76 	char			 cbuf[MAX_LINE];
77 	size_t			 cbuf_valid;
78 	char			 sbuf[MAX_LINE];
79 	size_t			 sbuf_valid;
80 	int			 cmd;
81 	int			 client_rd;
82 	u_int16_t		 port;
83 	u_int16_t		 proxy_port;
84 	LIST_ENTRY(session)	 entry;
85 };
86 
87 LIST_HEAD(, session) sessions = LIST_HEAD_INITIALIZER(sessions);
88 
89 void	client_error(struct bufferevent *, short, void *);
90 int	client_parse(struct session *s);
91 int	client_parse_anon(struct session *s);
92 int	client_parse_cmd(struct session *s);
93 void	client_read(struct bufferevent *, void *);
94 int	drop_privs(void);
95 void	end_session(struct session *);
96 void	exit_daemon(void);
97 int	get_line(char *, size_t *);
98 void	handle_connection(const int, short, void *);
99 void	handle_signal(int, short, void *);
100 struct session * init_session(void);
101 void	logmsg(int, const char *, ...);
102 u_int16_t parse_port(int);
103 u_int16_t pick_proxy_port(void);
104 void	proxy_reply(int, struct sockaddr *, u_int16_t);
105 int	rdaemon(int);
106 void	server_error(struct bufferevent *, short, void *);
107 int	server_parse(struct session *s);
108 int	allow_data_connection(struct session *s);
109 void	server_read(struct bufferevent *, void *);
110 const char *sock_ntop(struct sockaddr *);
111 void	usage(void);
112 
113 char linebuf[MAX_LINE + 1];
114 size_t linelen;
115 
116 char ntop_buf[NTOP_BUFS][INET6_ADDRSTRLEN];
117 
118 struct event listen_ev, pause_accept_ev;
119 struct sockaddr_storage fixed_server_ss, fixed_proxy_ss;
120 char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port,
121     *qname, *tagname;
122 int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions,
123     rfc_mode, session_count, timeout, verbose;
124 extern char *__progname;
125 
126 void
127 client_error(struct bufferevent *bufev, short what, void *arg)
128 {
129 	struct session *s = arg;
130 
131 	if (what & EVBUFFER_EOF)
132 		logmsg(LOG_INFO, "#%d client close", s->id);
133 	else if (what == (EVBUFFER_ERROR | EVBUFFER_READ))
134 		logmsg(LOG_ERR, "#%d client reset connection", s->id);
135 	else if (what & EVBUFFER_TIMEOUT)
136 		logmsg(LOG_ERR, "#%d client timeout", s->id);
137 	else if (what & EVBUFFER_WRITE)
138 		logmsg(LOG_ERR, "#%d client write error: %d", s->id, what);
139 	else
140 		logmsg(LOG_ERR, "#%d abnormal client error: %d", s->id, what);
141 
142 	end_session(s);
143 }
144 
145 int
146 client_parse(struct session *s)
147 {
148 	/* Reset any previous command. */
149 	s->cmd = CMD_NONE;
150 	s->port = 0;
151 
152 	/* Commands we are looking for are at least 4 chars long. */
153 	if (linelen < 4)
154 		return (1);
155 
156 	if (linebuf[0] == 'P' || linebuf[0] == 'p' ||
157 	    linebuf[0] == 'E' || linebuf[0] == 'e') {
158 		if (!client_parse_cmd(s))
159 			return (0);
160 
161 		/*
162 		 * Allow active mode connections immediately, instead of
163 		 * waiting for a positive reply from the server.  Some
164 		 * rare servers/proxies try to probe or setup the data
165 		 * connection before an actual transfer request.
166 		 */
167 		if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT)
168 			return (allow_data_connection(s));
169 	}
170 
171 	if (anonymous_only && (linebuf[0] == 'U' || linebuf[0] == 'u'))
172 		return (client_parse_anon(s));
173 
174 	return (1);
175 }
176 
177 int
178 client_parse_anon(struct session *s)
179 {
180 	if (strcasecmp("USER ftp\r\n", linebuf) != 0 &&
181 	    strcasecmp("USER anonymous\r\n", linebuf) != 0) {
182 		snprintf(linebuf, sizeof linebuf,
183 		    "500 Only anonymous FTP allowed\r\n");
184 		logmsg(LOG_DEBUG, "#%d proxy: %s", s->id, linebuf);
185 
186 		/* Talk back to the client ourself. */
187 		linelen = strlen(linebuf);
188 		bufferevent_write(s->client_bufev, linebuf, linelen);
189 
190 		/* Clear buffer so it's not sent to the server. */
191 		linebuf[0] = '\0';
192 		linelen = 0;
193 	}
194 
195 	return (1);
196 }
197 
198 int
199 client_parse_cmd(struct session *s)
200 {
201 	if (strncasecmp("PASV", linebuf, 4) == 0)
202 		s->cmd = CMD_PASV;
203 	else if (strncasecmp("PORT ", linebuf, 5) == 0)
204 		s->cmd = CMD_PORT;
205 	else if (strncasecmp("EPSV", linebuf, 4) == 0)
206 		s->cmd = CMD_EPSV;
207 	else if (strncasecmp("EPRT ", linebuf, 5) == 0)
208 		s->cmd = CMD_EPRT;
209 	else
210 		return (1);
211 
212 	if (ipv6_mode && (s->cmd == CMD_PASV || s->cmd == CMD_PORT)) {
213 		logmsg(LOG_CRIT, "PASV and PORT not allowed with IPv6");
214 		return (0);
215 	}
216 
217 	if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) {
218 		s->port = parse_port(s->cmd);
219 		if (s->port < MIN_PORT) {
220 			logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id,
221 			    linebuf);
222 			return (0);
223 		}
224 		s->proxy_port = pick_proxy_port();
225 		proxy_reply(s->cmd, sstosa(&s->proxy_ss), s->proxy_port);
226 		logmsg(LOG_DEBUG, "#%d proxy: %s", s->id, linebuf);
227 	}
228 
229 	return (1);
230 }
231 
232 void
233 client_read(struct bufferevent *bufev, void *arg)
234 {
235 	struct session	*s = arg;
236 	size_t		 buf_avail, read;
237 	int		 n;
238 
239 	do {
240 		buf_avail = sizeof s->cbuf - s->cbuf_valid;
241 		read = bufferevent_read(bufev, s->cbuf + s->cbuf_valid,
242 		    buf_avail);
243 		s->cbuf_valid += read;
244 
245 		while ((n = get_line(s->cbuf, &s->cbuf_valid)) > 0) {
246 			logmsg(LOG_DEBUG, "#%d client: %s", s->id, linebuf);
247 			if (!client_parse(s)) {
248 				end_session(s);
249 				return;
250 			}
251 			bufferevent_write(s->server_bufev, linebuf, linelen);
252 		}
253 
254 		if (n == -1) {
255 			logmsg(LOG_ERR, "#%d client command too long or not"
256 			    " clean", s->id);
257 			end_session(s);
258 			return;
259 		}
260 	} while (read == buf_avail);
261 }
262 
263 int
264 drop_privs(void)
265 {
266 	struct passwd *pw;
267 
268 	pw = getpwnam(NOPRIV_USER);
269 	if (pw == NULL)
270 		return (0);
271 
272 	tzset();
273 	if (chroot(CHROOT_DIR) != 0 || chdir("/") != 0 ||
274 	    setgroups(1, &pw->pw_gid) != 0 ||
275 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0 ||
276 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0)
277 		return (0);
278 
279 	return (1);
280 }
281 
282 void
283 end_session(struct session *s)
284 {
285 	int err;
286 
287 	logmsg(LOG_INFO, "#%d ending session", s->id);
288 
289 	/* Flush output buffers. */
290 	if (s->client_bufev && s->client_fd != -1)
291 		evbuffer_write(s->client_bufev->output, s->client_fd);
292 	if (s->server_bufev && s->server_fd != -1)
293 		evbuffer_write(s->server_bufev->output, s->server_fd);
294 
295 	if (s->client_fd != -1)
296 		close(s->client_fd);
297 	if (s->server_fd != -1)
298 		close(s->server_fd);
299 
300 	if (s->client_bufev)
301 		bufferevent_free(s->client_bufev);
302 	if (s->server_bufev)
303 		bufferevent_free(s->server_bufev);
304 
305 	/* Remove rulesets by committing empty ones. */
306 	err = 0;
307 	if (prepare_commit(s->id) == -1)
308 		err = errno;
309 	else if (do_commit() == -1) {
310 		err = errno;
311 		do_rollback();
312 	}
313 	if (err)
314 		logmsg(LOG_ERR, "#%d pf rule removal failed: %s", s->id,
315 		    strerror(err));
316 
317 	LIST_REMOVE(s, entry);
318 	free(s);
319 	session_count--;
320 }
321 
322 void
323 exit_daemon(void)
324 {
325 	struct session *s, *next;
326 
327 	for (s = LIST_FIRST(&sessions); s != NULL; s = next) {
328 		next = LIST_NEXT(s, entry);
329 		end_session(s);
330 	}
331 
332 	if (daemonize)
333 		closelog();
334 
335 	exit(0);
336 }
337 
338 int
339 get_line(char *buf, size_t *valid)
340 {
341 	size_t i;
342 
343 	if (*valid > MAX_LINE)
344 		return (-1);
345 
346 	/* Copy to linebuf while searching for a newline. */
347 	for (i = 0; i < *valid; i++) {
348 		linebuf[i] = buf[i];
349 		if (buf[i] == '\0')
350 			return (-1);
351 		if (buf[i] == '\n')
352 			break;
353 	}
354 
355 	if (i == *valid) {
356 		/* No newline found. */
357 		linebuf[0] = '\0';
358 		linelen = 0;
359 		if (i < MAX_LINE)
360 			return (0);
361 		return (-1);
362 	}
363 
364 	linelen = i + 1;
365 	linebuf[linelen] = '\0';
366 	*valid -= linelen;
367 
368 	/* Move leftovers to the start. */
369 	if (*valid != 0)
370 		bcopy(buf + linelen, buf, *valid);
371 
372 	return ((int)linelen);
373 }
374 
375 void
376 handle_connection(const int listen_fd, short event, void *arg)
377 {
378 	struct sockaddr_storage tmp_ss;
379 	struct sockaddr *client_sa, *server_sa, *fixed_server_sa;
380 	struct sockaddr *proxy_to_server_sa;
381 	struct session *s;
382 	socklen_t len;
383 	int client_fd, fc, on;
384 
385 	event_add(&listen_ev, NULL);
386 
387 	if ((event & EV_TIMEOUT))
388 		/* accept() is no longer paused. */
389 		return;
390 
391 	/*
392 	 * We _must_ accept the connection, otherwise libevent will keep
393 	 * coming back, and we will chew up all CPU.
394 	 */
395 	client_sa = sstosa(&tmp_ss);
396 	len = sizeof(struct sockaddr_storage);
397 	if ((client_fd = accept(listen_fd, client_sa, &len)) < 0) {
398 		logmsg(LOG_CRIT, "accept() failed: %s", strerror(errno));
399 
400 		/*
401 		 * Pause accept if we are out of file descriptors, or
402 		 * libevent will haunt us here too.
403 		 */
404 		if (errno == ENFILE || errno == EMFILE) {
405 			struct timeval pause = { 1, 0 };
406 
407 			event_del(&listen_ev);
408 			evtimer_add(&pause_accept_ev, &pause);
409 		} else if (errno != EWOULDBLOCK && errno != EINTR &&
410 		    errno != ECONNABORTED)
411 			logmsg(LOG_CRIT, "accept() failed: %s", strerror(errno));
412 		return;
413 	}
414 
415 	/* Refuse connection if the maximum is reached. */
416 	if (session_count >= max_sessions) {
417 		logmsg(LOG_ERR, "client limit (%d) reached, refusing "
418 		    "connection from %s", max_sessions, sock_ntop(client_sa));
419 		close(client_fd);
420 		return;
421 	}
422 
423 	/* Allocate session and copy back the info from the accept(). */
424 	s = init_session();
425 	if (s == NULL) {
426 		logmsg(LOG_CRIT, "init_session failed");
427 		close(client_fd);
428 		return;
429 	}
430 	s->client_fd = client_fd;
431 	memcpy(sstosa(&s->client_ss), client_sa, client_sa->sa_len);
432 
433 	/* Cast it once, and be done with it. */
434 	client_sa = sstosa(&s->client_ss);
435 	server_sa = sstosa(&s->server_ss);
436 	proxy_to_server_sa = sstosa(&s->proxy_ss);
437 	fixed_server_sa = sstosa(&fixed_server_ss);
438 
439 	/* Log id/client early to ease debugging. */
440 	logmsg(LOG_DEBUG, "#%d accepted connection from %s", s->id,
441 	    sock_ntop(client_sa));
442 
443 	/*
444 	 * Find out the real server and port that the client wanted.
445 	 */
446 	len = sizeof(struct sockaddr_storage);
447 	if (getsockname(s->client_fd, server_sa, &len) < 0) {
448 		logmsg(LOG_CRIT, "#%d getsockname failed: %s", s->id,
449 		    strerror(errno));
450 		goto fail;
451 	}
452 	len = sizeof(s->client_rd);
453 	if (getsockopt(s->client_fd, SOL_SOCKET, SO_RTABLE, &s->client_rd,
454 	    &len) && errno != ENOPROTOOPT) {
455 		logmsg(LOG_CRIT, "#%d getsockopt failed: %s", s->id,
456 		    strerror(errno));
457 		goto fail;
458 	}
459 	if (fixed_server) {
460 		memcpy(sstosa(&s->orig_server_ss), server_sa,
461 		    server_sa->sa_len);
462 		memcpy(server_sa, fixed_server_sa, fixed_server_sa->sa_len);
463 	}
464 
465 	/* XXX: check we are not connecting to ourself. */
466 
467 	/*
468 	 * Setup socket and connect to server.
469 	 */
470 	if ((s->server_fd = socket(server_sa->sa_family, SOCK_STREAM,
471 	    IPPROTO_TCP)) < 0) {
472 		logmsg(LOG_CRIT, "#%d server socket failed: %s", s->id,
473 		    strerror(errno));
474 		goto fail;
475 	}
476 	if (fixed_proxy && bind(s->server_fd, sstosa(&fixed_proxy_ss),
477 	    fixed_proxy_ss.ss_len) != 0) {
478 		logmsg(LOG_CRIT, "#%d cannot bind fixed proxy address: %s",
479 		    s->id, strerror(errno));
480 		goto fail;
481 	}
482 
483 	/* Use non-blocking connect(), see CONNECT_TIMEOUT below. */
484 	if ((fc = fcntl(s->server_fd, F_GETFL)) == -1 ||
485 	    fcntl(s->server_fd, F_SETFL, fc | O_NONBLOCK) == -1) {
486 		logmsg(LOG_CRIT, "#%d cannot mark socket non-blocking: %s",
487 		    s->id, strerror(errno));
488 		goto fail;
489 	}
490 	if (connect(s->server_fd, server_sa, server_sa->sa_len) < 0 &&
491 	    errno != EINPROGRESS) {
492 		logmsg(LOG_CRIT, "#%d proxy cannot connect to server %s: %s",
493 		    s->id, sock_ntop(server_sa), strerror(errno));
494 		goto fail;
495 	}
496 
497 	len = sizeof(struct sockaddr_storage);
498 	if ((getsockname(s->server_fd, proxy_to_server_sa, &len)) < 0) {
499 		logmsg(LOG_CRIT, "#%d getsockname failed: %s", s->id,
500 		    strerror(errno));
501 		goto fail;
502 	}
503 
504 	logmsg(LOG_INFO, "#%d FTP session %d/%d started: client %s to server "
505 	    "%s via proxy %s", s->id, session_count, max_sessions,
506 	    sock_ntop(client_sa), sock_ntop(server_sa),
507 	    sock_ntop(proxy_to_server_sa));
508 
509 	/* Keepalive is nice, but don't care if it fails. */
510 	on = 1;
511 	setsockopt(s->client_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
512 	    sizeof on);
513 	setsockopt(s->server_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
514 	    sizeof on);
515 
516 	/*
517 	 * Setup buffered events.
518 	 */
519 	s->client_bufev = bufferevent_new(s->client_fd, &client_read, NULL,
520 	    &client_error, s);
521 	if (s->client_bufev == NULL) {
522 		logmsg(LOG_CRIT, "#%d bufferevent_new client failed", s->id);
523 		goto fail;
524 	}
525 	bufferevent_settimeout(s->client_bufev, timeout, 0);
526 	bufferevent_enable(s->client_bufev, EV_READ | EV_TIMEOUT);
527 
528 	s->server_bufev = bufferevent_new(s->server_fd, &server_read, NULL,
529 	    &server_error, s);
530 	if (s->server_bufev == NULL) {
531 		logmsg(LOG_CRIT, "#%d bufferevent_new server failed", s->id);
532 		goto fail;
533 	}
534 	bufferevent_settimeout(s->server_bufev, CONNECT_TIMEOUT, 0);
535 	bufferevent_enable(s->server_bufev, EV_READ | EV_TIMEOUT);
536 
537 	return;
538 
539  fail:
540 	end_session(s);
541 }
542 
543 void
544 handle_signal(int sig, short event, void *arg)
545 {
546 	/*
547 	 * Signal handler rules don't apply, libevent decouples for us.
548 	 */
549 
550 	logmsg(LOG_ERR, "exiting on signal %d", sig);
551 
552 	exit_daemon();
553 }
554 
555 
556 struct session *
557 init_session(void)
558 {
559 	struct session *s;
560 
561 	s = calloc(1, sizeof(struct session));
562 	if (s == NULL)
563 		return (NULL);
564 
565 	s->id = id_count++;
566 	s->client_fd = -1;
567 	s->server_fd = -1;
568 	s->cbuf[0] = '\0';
569 	s->cbuf_valid = 0;
570 	s->sbuf[0] = '\0';
571 	s->sbuf_valid = 0;
572 	s->client_bufev = NULL;
573 	s->server_bufev = NULL;
574 	s->cmd = CMD_NONE;
575 	s->port = 0;
576 
577 	LIST_INSERT_HEAD(&sessions, s, entry);
578 	session_count++;
579 
580 	return (s);
581 }
582 
583 void
584 logmsg(int pri, const char *message, ...)
585 {
586 	va_list	ap;
587 
588 	if (pri > loglevel)
589 		return;
590 
591 	va_start(ap, message);
592 
593 	if (daemonize)
594 		/* syslog does its own vissing. */
595 		vsyslog(pri, message, ap);
596 	else {
597 		char buf[MAX_LOGLINE];
598 		char visbuf[2 * MAX_LOGLINE];
599 
600 		/* We don't care about truncation. */
601 		vsnprintf(buf, sizeof buf, message, ap);
602 		strnvis(visbuf, buf, sizeof visbuf, VIS_CSTYLE | VIS_NL);
603 		fprintf(stderr, "%s\n", visbuf);
604 	}
605 
606 	va_end(ap);
607 }
608 
609 int
610 main(int argc, char *argv[])
611 {
612 	struct rlimit rlp;
613 	struct addrinfo hints, *res;
614 	struct event ev_sighup, ev_sigint, ev_sigterm;
615 	int ch, devnull, error, listenfd, on;
616 	const char *errstr;
617 
618 	/* Defaults. */
619 	anonymous_only	= 0;
620 	daemonize	= 1;
621 	fixed_proxy	= NULL;
622 	fixed_server	= NULL;
623 	fixed_server_port = "21";
624 	ipv6_mode	= 0;
625 	listen_ip	= NULL;
626 	listen_port	= "8021";
627 	loglevel	= LOG_NOTICE;
628 	max_sessions	= 100;
629 	qname		= NULL;
630 	rfc_mode	= 0;
631 	tagname		= NULL;
632 	timeout		= 24 * 3600;
633 	verbose		= 0;
634 
635 	/* Other initialization. */
636 	id_count	= 1;
637 	session_count	= 0;
638 
639 	while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rT:t:v")) != -1) {
640 		switch (ch) {
641 		case '6':
642 			ipv6_mode = 1;
643 			break;
644 		case 'A':
645 			anonymous_only = 1;
646 			break;
647 		case 'a':
648 			fixed_proxy = optarg;
649 			break;
650 		case 'b':
651 			listen_ip = optarg;
652 			break;
653 		case 'D':
654 			loglevel = strtonum(optarg, LOG_EMERG, LOG_DEBUG,
655 			    &errstr);
656 			if (errstr)
657 				errx(1, "loglevel %s", errstr);
658 			break;
659 		case 'd':
660 			daemonize = 0;
661 			break;
662 		case 'm':
663 			max_sessions = strtonum(optarg, 1, 500, &errstr);
664 			if (errstr)
665 				errx(1, "max sessions %s", errstr);
666 			break;
667 		case 'P':
668 			fixed_server_port = optarg;
669 			break;
670 		case 'p':
671 			listen_port = optarg;
672 			break;
673 		case 'q':
674 			if (strlen(optarg) >= PF_QNAME_SIZE)
675 				errx(1, "queuename too long");
676 			qname = optarg;
677 			break;
678 		case 'R':
679 			fixed_server = optarg;
680 			break;
681 		case 'r':
682 			rfc_mode = 1;
683 			break;
684 		case 'T':
685 			if (strlen(optarg) >= PF_TAG_NAME_SIZE)
686 				errx(1, "tagname too long");
687 			tagname = optarg;
688 			break;
689 		case 't':
690 			timeout = strtonum(optarg, 0, 86400, &errstr);
691 			if (errstr)
692 				errx(1, "timeout %s", errstr);
693 			break;
694 		case 'v':
695 			verbose++;
696 			if (verbose > 2)
697 				usage();
698 			break;
699 		default:
700 			usage();
701 		}
702 	}
703 
704 	if (listen_ip == NULL)
705 		listen_ip = ipv6_mode ? "::1" : "127.0.0.1";
706 
707 	/* Check for root to save the user from cryptic failure messages. */
708 	if (getuid() != 0)
709 		errx(1, "needs to start as root");
710 
711 	if (getpwnam(NOPRIV_USER) == NULL)
712 		errx(1, "unknown user %s", NOPRIV_USER);
713 
714 	/* Raise max. open files limit to satisfy max. sessions. */
715 	rlp.rlim_cur = rlp.rlim_max = (2 * max_sessions) + 10;
716 	if (setrlimit(RLIMIT_NOFILE, &rlp) == -1)
717 		err(1, "setrlimit");
718 
719 	if (fixed_proxy) {
720 		memset(&hints, 0, sizeof hints);
721 		hints.ai_flags = AI_NUMERICHOST;
722 		hints.ai_family = ipv6_mode ? AF_INET6 : AF_INET;
723 		hints.ai_socktype = SOCK_STREAM;
724 		error = getaddrinfo(fixed_proxy, NULL, &hints, &res);
725 		if (error)
726 			errx(1, "getaddrinfo fixed proxy address failed: %s",
727 			    gai_strerror(error));
728 		memcpy(&fixed_proxy_ss, res->ai_addr, res->ai_addrlen);
729 		logmsg(LOG_INFO, "using %s to connect to servers",
730 		    sock_ntop(sstosa(&fixed_proxy_ss)));
731 		freeaddrinfo(res);
732 	}
733 
734 	if (fixed_server) {
735 		memset(&hints, 0, sizeof hints);
736 		hints.ai_family = ipv6_mode ? AF_INET6 : AF_INET;
737 		hints.ai_socktype = SOCK_STREAM;
738 		error = getaddrinfo(fixed_server, fixed_server_port, &hints,
739 		    &res);
740 		if (error)
741 			errx(1, "getaddrinfo fixed server address failed: %s",
742 			    gai_strerror(error));
743 		memcpy(&fixed_server_ss, res->ai_addr, res->ai_addrlen);
744 		logmsg(LOG_INFO, "using fixed server %s",
745 		    sock_ntop(sstosa(&fixed_server_ss)));
746 		freeaddrinfo(res);
747 	}
748 
749 	/* Setup listener. */
750 	memset(&hints, 0, sizeof hints);
751 	hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
752 	hints.ai_family = ipv6_mode ? AF_INET6 : AF_INET;
753 	hints.ai_socktype = SOCK_STREAM;
754 	error = getaddrinfo(listen_ip, listen_port, &hints, &res);
755 	if (error)
756 		errx(1, "getaddrinfo listen address failed: %s",
757 		    gai_strerror(error));
758 	if ((listenfd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
759 		errx(1, "socket failed");
760 	on = 1;
761 	if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
762 	    sizeof on) != 0)
763 		err(1, "setsockopt failed");
764 	if (bind(listenfd, (struct sockaddr *)res->ai_addr,
765 	    (socklen_t)res->ai_addrlen) != 0)
766 	    	err(1, "bind failed");
767 	if (listen(listenfd, TCP_BACKLOG) != 0)
768 		err(1, "listen failed");
769 	freeaddrinfo(res);
770 
771 	/* Initialize pf. */
772 	init_filter(qname, tagname, verbose);
773 
774 	if (daemonize) {
775 		devnull = open(_PATH_DEVNULL, O_RDWR, 0);
776 		if (devnull == -1)
777 			err(1, "open(%s)", _PATH_DEVNULL);
778 	}
779 
780 	if (!drop_privs())
781 		err(1, "cannot drop privileges");
782 
783 	if (daemonize) {
784 		if (rdaemon(devnull) == -1)
785 			err(1, "cannot daemonize");
786 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
787 	}
788 
789 	/* Use logmsg for output from here on. */
790 
791 	event_init();
792 
793 	/* Setup signal handler. */
794 	signal(SIGPIPE, SIG_IGN);
795 	signal_set(&ev_sighup, SIGHUP, handle_signal, NULL);
796 	signal_set(&ev_sigint, SIGINT, handle_signal, NULL);
797 	signal_set(&ev_sigterm, SIGTERM, handle_signal, NULL);
798 	signal_add(&ev_sighup, NULL);
799 	signal_add(&ev_sigint, NULL);
800 	signal_add(&ev_sigterm, NULL);
801 
802 	event_set(&listen_ev, listenfd, EV_READ, handle_connection, NULL);
803 	event_add(&listen_ev, NULL);
804 	evtimer_set(&pause_accept_ev, handle_connection, NULL);
805 
806 	logmsg(LOG_NOTICE, "listening on %s port %s", listen_ip, listen_port);
807 
808 	/*  Vroom, vroom.  */
809 	event_dispatch();
810 
811 	logmsg(LOG_ERR, "event_dispatch error: %s", strerror(errno));
812 	exit_daemon();
813 
814 	/* NOTREACHED */
815 	return (1);
816 }
817 
818 u_int16_t
819 parse_port(int mode)
820 {
821 	unsigned int	 port, v[6];
822 	int		 n;
823 	char		*p;
824 
825 	/* Find the last space or left-parenthesis. */
826 	for (p = linebuf + linelen; p > linebuf; p--)
827 		if (*p == ' ' || *p == '(')
828 			break;
829 	if (p == linebuf)
830 		return (0);
831 
832 	switch (mode) {
833 	case CMD_PORT:
834 		n = sscanf(p, " %u,%u,%u,%u,%u,%u", &v[0], &v[1], &v[2],
835 		    &v[3], &v[4], &v[5]);
836 		if (n == 6 && v[0] < 256 && v[1] < 256 && v[2] < 256 &&
837 		    v[3] < 256 && v[4] < 256 && v[5] < 256)
838 			return ((v[4] << 8) | v[5]);
839 		break;
840 	case CMD_PASV:
841 		n = sscanf(p, "(%u,%u,%u,%u,%u,%u)", &v[0], &v[1], &v[2],
842 		    &v[3], &v[4], &v[5]);
843 		if (n == 6 && v[0] < 256 && v[1] < 256 && v[2] < 256 &&
844 		    v[3] < 256 && v[4] < 256 && v[5] < 256)
845 			return ((v[4] << 8) | v[5]);
846 		break;
847 	case CMD_EPSV:
848 		n = sscanf(p, "(|||%u|)", &port);
849 		if (n == 1 && port < 65536)
850 			return (port);
851 		break;
852 	case CMD_EPRT:
853 		n = sscanf(p, " |1|%u.%u.%u.%u|%u|", &v[0], &v[1], &v[2],
854 		    &v[3], &port);
855 		if (n == 5 && v[0] < 256 && v[1] < 256 && v[2] < 256 &&
856 		    v[3] < 256 && port < 65536)
857 			return (port);
858 		n = sscanf(p, " |2|%*[a-fA-F0-9:]|%u|", &port);
859 		if (n == 1 && port < 65536)
860 			return (port);
861 		break;
862 	default:
863 		return (0);
864 	}
865 
866 	return (0);
867 }
868 
869 u_int16_t
870 pick_proxy_port(void)
871 {
872 	/* Random should be good enough for avoiding port collisions. */
873 	return (IPPORT_HIFIRSTAUTO +
874 	    arc4random_uniform(IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO));
875 }
876 
877 void
878 proxy_reply(int cmd, struct sockaddr *sa, u_int16_t port)
879 {
880 	int i, r;
881 
882 	switch (cmd) {
883 	case CMD_PORT:
884 		r = snprintf(linebuf, sizeof linebuf,
885 		    "PORT %s,%u,%u\r\n", sock_ntop(sa), port / 256,
886 		    port % 256);
887 		break;
888 	case CMD_PASV:
889 		r = snprintf(linebuf, sizeof linebuf,
890 		    "227 Entering Passive Mode (%s,%u,%u)\r\n", sock_ntop(sa),
891 		        port / 256, port % 256);
892 		break;
893 	case CMD_EPRT:
894 		if (sa->sa_family == AF_INET)
895 			r = snprintf(linebuf, sizeof linebuf,
896 			    "EPRT |1|%s|%u|\r\n", sock_ntop(sa), port);
897 		else if (sa->sa_family == AF_INET6)
898 			r = snprintf(linebuf, sizeof linebuf,
899 			    "EPRT |2|%s|%u|\r\n", sock_ntop(sa), port);
900 		break;
901 	case CMD_EPSV:
902 		r = snprintf(linebuf, sizeof linebuf,
903 		    "229 Entering Extended Passive Mode (|||%u|)\r\n", port);
904 		break;
905 	}
906 
907 	if (r < 0 || r >= sizeof linebuf) {
908 		logmsg(LOG_ERR, "proxy_reply failed: %d", r);
909 		linebuf[0] = '\0';
910 		linelen = 0;
911 		return;
912 	}
913 	linelen = (size_t)r;
914 
915 	if (cmd == CMD_PORT || cmd == CMD_PASV) {
916 		/* Replace dots in IP address with commas. */
917 		for (i = 0; i < linelen; i++)
918 			if (linebuf[i] == '.')
919 				linebuf[i] = ',';
920 	}
921 }
922 
923 void
924 server_error(struct bufferevent *bufev, short what, void *arg)
925 {
926 	struct session *s = arg;
927 
928 	if (what & EVBUFFER_EOF)
929 		logmsg(LOG_INFO, "#%d server close", s->id);
930 	else if (what == (EVBUFFER_ERROR | EVBUFFER_READ))
931 		logmsg(LOG_ERR, "#%d server refused connection", s->id);
932 	else if (what & EVBUFFER_WRITE)
933 		logmsg(LOG_ERR, "#%d server write error: %d", s->id, what);
934 	else if (what & EVBUFFER_TIMEOUT)
935 		logmsg(LOG_NOTICE, "#%d server timeout", s->id);
936 	else
937 		logmsg(LOG_ERR, "#%d abnormal server error: %d", s->id, what);
938 
939 	end_session(s);
940 }
941 
942 int
943 server_parse(struct session *s)
944 {
945 	if (s->cmd == CMD_NONE || linelen < 4 || linebuf[0] != '2')
946 		goto out;
947 
948 	if ((s->cmd == CMD_PASV && strncmp("227 ", linebuf, 4) == 0) ||
949 	    (s->cmd == CMD_EPSV && strncmp("229 ", linebuf, 4) == 0))
950 		return (allow_data_connection(s));
951 
952  out:
953 	s->cmd = CMD_NONE;
954 	s->port = 0;
955 
956 	return (1);
957 }
958 
959 int
960 allow_data_connection(struct session *s)
961 {
962 	struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
963 	int prepared = 0;
964 
965 	/*
966 	 * The pf rules below do quite some NAT rewriting, to keep up
967 	 * appearances.  Points to keep in mind:
968 	 * 1)  The client must think it's talking to the real server,
969 	 *     for both control and data connections.  Transparently.
970 	 * 2)  The server must think that the proxy is the client.
971 	 * 3)  Source and destination ports are rewritten to minimize
972 	 *     port collisions, to aid security (some systems pick weak
973 	 *     ports) or to satisfy RFC requirements (source port 20).
974 	 */
975 
976 	/* Cast this once, to make code below it more readable. */
977 	client_sa = sstosa(&s->client_ss);
978 	server_sa = sstosa(&s->server_ss);
979 	proxy_sa = sstosa(&s->proxy_ss);
980 	if (fixed_server)
981 		/* Fixed server: data connections must appear to come
982 		   from / go to the original server, not the fixed one. */
983 		orig_sa = sstosa(&s->orig_server_ss);
984 	else
985 		/* Server not fixed: orig_server == server. */
986 		orig_sa = sstosa(&s->server_ss);
987 
988 	/* Passive modes. */
989 	if (s->cmd == CMD_PASV || s->cmd == CMD_EPSV) {
990 		s->port = parse_port(s->cmd);
991 		if (s->port < MIN_PORT) {
992 			logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id,
993 			    linebuf);
994 			return (0);
995 		}
996 		s->proxy_port = pick_proxy_port();
997 		logmsg(LOG_INFO, "#%d passive: client to server port %d"
998 		    " via port %d", s->id, s->port, s->proxy_port);
999 
1000 		if (prepare_commit(s->id) == -1)
1001 			goto fail;
1002 		prepared = 1;
1003 
1004 		proxy_reply(s->cmd, orig_sa, s->proxy_port);
1005 		logmsg(LOG_DEBUG, "#%d proxy: %s", s->id, linebuf);
1006 
1007 		/* pass in from $client to $orig_server port $proxy_port
1008 		    rdr-to $server port $port */
1009 		if (add_rdr(s->id, client_sa, s->client_rd, orig_sa,
1010 		    s->proxy_port, server_sa, s->port, getrtable()) == -1)
1011 			goto fail;
1012 
1013 		/* pass out from $client to $server port $port nat-to $proxy */
1014 		if (add_nat(s->id, client_sa, getrtable(), server_sa,
1015 		    s->port, proxy_sa, PF_NAT_PROXY_PORT_LOW,
1016 		    PF_NAT_PROXY_PORT_HIGH) == -1)
1017 			goto fail;
1018 	}
1019 
1020 	/* Active modes. */
1021 	if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) {
1022 		logmsg(LOG_INFO, "#%d active: server to client port %d"
1023 		    " via port %d", s->id, s->port, s->proxy_port);
1024 
1025 		if (prepare_commit(s->id) == -1)
1026 			goto fail;
1027 		prepared = 1;
1028 
1029 		/* pass in from $server to $proxy port $proxy_port
1030 		    rdr-to $client port $port */
1031 		if (add_rdr(s->id, server_sa, getrtable(), proxy_sa,
1032 		    s->proxy_port, client_sa, s->port, s->client_rd) == -1)
1033 			goto fail;
1034 
1035 		/* pass out from $server to $client port $port
1036 		    nat-to $orig_server port $natport */
1037 		if (rfc_mode && s->cmd == CMD_PORT) {
1038 			/* Rewrite sourceport to RFC mandated 20. */
1039 			if (add_nat(s->id, server_sa, s->client_rd, client_sa,
1040 			    s->port, orig_sa, 20, 20) == -1)
1041 				goto fail;
1042 		} else {
1043 			/* Let pf pick a source port from the standard range. */
1044 			if (add_nat(s->id, server_sa, s->client_rd, client_sa,
1045 			    s->port, orig_sa, PF_NAT_PROXY_PORT_LOW,
1046 			    PF_NAT_PROXY_PORT_HIGH) == -1)
1047 			    	goto fail;
1048 		}
1049 	}
1050 
1051 	/* Commit rules if they were prepared. */
1052 	if (prepared && (do_commit() == -1)) {
1053 		if (errno != EBUSY)
1054 			goto fail;
1055 		/* One more try if busy. */
1056 		usleep(5000);
1057 		if (do_commit() == -1)
1058 			goto fail;
1059 	}
1060 
1061 	s->cmd = CMD_NONE;
1062 	s->port = 0;
1063 
1064 	return (1);
1065 
1066  fail:
1067 	logmsg(LOG_CRIT, "#%d pf operation failed: %s", s->id, strerror(errno));
1068 	if (prepared)
1069 		do_rollback();
1070 	return (0);
1071 }
1072 
1073 void
1074 server_read(struct bufferevent *bufev, void *arg)
1075 {
1076 	struct session	*s = arg;
1077 	size_t		 buf_avail, read;
1078 	int		 n;
1079 
1080 	bufferevent_settimeout(bufev, timeout, 0);
1081 
1082 	do {
1083 		buf_avail = sizeof s->sbuf - s->sbuf_valid;
1084 		read = bufferevent_read(bufev, s->sbuf + s->sbuf_valid,
1085 		    buf_avail);
1086 		s->sbuf_valid += read;
1087 
1088 		while ((n = get_line(s->sbuf, &s->sbuf_valid)) > 0) {
1089 			logmsg(LOG_DEBUG, "#%d server: %s", s->id, linebuf);
1090 			if (!server_parse(s)) {
1091 				end_session(s);
1092 				return;
1093 			}
1094 			bufferevent_write(s->client_bufev, linebuf, linelen);
1095 		}
1096 
1097 		if (n == -1) {
1098 			logmsg(LOG_ERR, "#%d server reply too long or not"
1099 			    " clean", s->id);
1100 			end_session(s);
1101 			return;
1102 		}
1103 	} while (read == buf_avail);
1104 }
1105 
1106 const char *
1107 sock_ntop(struct sockaddr *sa)
1108 {
1109 	static int n = 0;
1110 
1111 	/* Cycle to next buffer. */
1112 	n = (n + 1) % NTOP_BUFS;
1113 	ntop_buf[n][0] = '\0';
1114 
1115 	if (sa->sa_family == AF_INET) {
1116 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1117 
1118 		return (inet_ntop(AF_INET, &sin->sin_addr, ntop_buf[n],
1119 		    sizeof ntop_buf[0]));
1120 	}
1121 
1122 	if (sa->sa_family == AF_INET6) {
1123 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
1124 
1125 		return (inet_ntop(AF_INET6, &sin6->sin6_addr, ntop_buf[n],
1126 		    sizeof ntop_buf[0]));
1127 	}
1128 
1129 	return (NULL);
1130 }
1131 
1132 void
1133 usage(void)
1134 {
1135 	fprintf(stderr, "usage: %s [-6Adrv] [-a address] [-b address]"
1136 	    " [-D level] [-m maxsessions]\n                 [-P port]"
1137 	    " [-p port] [-q queue] [-R address] [-T tag]\n"
1138             "                 [-t timeout]\n", __progname);
1139 	exit(1);
1140 }
1141 
1142 int
1143 rdaemon(int devnull)
1144 {
1145 
1146 	switch (fork()) {
1147 	case -1:
1148 		return (-1);
1149 	case 0:
1150 		break;
1151 	default:
1152 		_exit(0);
1153 	}
1154 
1155 	if (setsid() == -1)
1156 		return (-1);
1157 
1158 	(void)dup2(devnull, STDIN_FILENO);
1159 	(void)dup2(devnull, STDOUT_FILENO);
1160 	(void)dup2(devnull, STDERR_FILENO);
1161 	if (devnull > 2)
1162 		(void)close(devnull);
1163 
1164 	return (0);
1165 }
1166