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