Date: Thu, 8 Oct 2009 22:33:19 +0000 (UTC) From: Ermal Luçi <eri@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r197884 - in user/eri/pf45/head/contrib/pf: authpf ftp-proxy libevent man pfctl pflogd tftp-proxy Message-ID: <200910082233.n98MXJK6035533@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: eri Date: Thu Oct 8 22:33:19 2009 New Revision: 197884 URL: http://svn.freebsd.org/changeset/base/197884 Log: Import manually the vendor part of pf(4). Added: user/eri/pf45/head/contrib/pf/man/pflow.4 (contents, props changed) Modified: user/eri/pf45/head/contrib/pf/authpf/authpf.8 user/eri/pf45/head/contrib/pf/authpf/authpf.c user/eri/pf45/head/contrib/pf/authpf/pathnames.h user/eri/pf45/head/contrib/pf/ftp-proxy/filter.c user/eri/pf45/head/contrib/pf/ftp-proxy/filter.h user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.8 user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.c user/eri/pf45/head/contrib/pf/libevent/buffer.c user/eri/pf45/head/contrib/pf/libevent/evbuffer.c user/eri/pf45/head/contrib/pf/libevent/event-internal.h user/eri/pf45/head/contrib/pf/libevent/event.c user/eri/pf45/head/contrib/pf/libevent/event.h user/eri/pf45/head/contrib/pf/libevent/evsignal.h user/eri/pf45/head/contrib/pf/libevent/kqueue.c user/eri/pf45/head/contrib/pf/libevent/log.c user/eri/pf45/head/contrib/pf/libevent/log.h user/eri/pf45/head/contrib/pf/libevent/poll.c user/eri/pf45/head/contrib/pf/libevent/select.c user/eri/pf45/head/contrib/pf/libevent/signal.c user/eri/pf45/head/contrib/pf/man/pf.4 user/eri/pf45/head/contrib/pf/man/pf.conf.5 user/eri/pf45/head/contrib/pf/man/pf.os.5 user/eri/pf45/head/contrib/pf/man/pflog.4 user/eri/pf45/head/contrib/pf/man/pfsync.4 user/eri/pf45/head/contrib/pf/pfctl/parse.y user/eri/pf45/head/contrib/pf/pfctl/pf_print_state.c user/eri/pf45/head/contrib/pf/pfctl/pfctl.8 user/eri/pf45/head/contrib/pf/pfctl/pfctl.c user/eri/pf45/head/contrib/pf/pfctl/pfctl.h user/eri/pf45/head/contrib/pf/pfctl/pfctl_altq.c user/eri/pf45/head/contrib/pf/pfctl/pfctl_optimize.c user/eri/pf45/head/contrib/pf/pfctl/pfctl_osfp.c user/eri/pf45/head/contrib/pf/pfctl/pfctl_parser.c user/eri/pf45/head/contrib/pf/pfctl/pfctl_parser.h user/eri/pf45/head/contrib/pf/pfctl/pfctl_qstats.c user/eri/pf45/head/contrib/pf/pfctl/pfctl_radix.c user/eri/pf45/head/contrib/pf/pfctl/pfctl_table.c user/eri/pf45/head/contrib/pf/pflogd/pflogd.8 user/eri/pf45/head/contrib/pf/pflogd/pflogd.c user/eri/pf45/head/contrib/pf/pflogd/pflogd.h user/eri/pf45/head/contrib/pf/pflogd/privsep.c user/eri/pf45/head/contrib/pf/pflogd/privsep_fdpass.c user/eri/pf45/head/contrib/pf/tftp-proxy/filter.c user/eri/pf45/head/contrib/pf/tftp-proxy/filter.h user/eri/pf45/head/contrib/pf/tftp-proxy/tftp-proxy.8 user/eri/pf45/head/contrib/pf/tftp-proxy/tftp-proxy.c Modified: user/eri/pf45/head/contrib/pf/authpf/authpf.8 ============================================================================== --- user/eri/pf45/head/contrib/pf/authpf/authpf.8 Thu Oct 8 22:31:19 2009 (r197883) +++ user/eri/pf45/head/contrib/pf/authpf/authpf.8 Thu Oct 8 22:33:19 2009 (r197884) @@ -1,5 +1,4 @@ -.\" $FreeBSD$ -.\" $OpenBSD: authpf.8,v 1.43 2007/02/24 17:21:04 beck Exp $ +.\" $OpenBSD: authpf.8,v 1.46 2008/03/18 23:03:14 merdely Exp $ .\" .\" Copyright (c) 1998-2007 Bob Beck (beck@openbsd.org>. All rights reserved. .\" @@ -15,14 +14,16 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd March 28, 2006 +.Dd $Mdocdate: March 18 2008 $ .Dt AUTHPF 8 .Os .Sh NAME -.Nm authpf +.Nm authpf , +.Nm authpf-noip .Nd authenticating gateway user shell .Sh SYNOPSIS .Nm authpf +.Nm authpf-noip .Sh DESCRIPTION .Nm is a user shell for authenticating gateways. @@ -31,47 +32,63 @@ It is used to change rules when a user authenticates and starts a session with .Xr sshd 8 and to undo these changes when the user's session exits. -It is designed for changing filter and translation rules for an individual -source IP address as long as a user maintains an active -.Xr ssh 1 -session. Typical use would be for a gateway that authenticates users before allowing them Internet use, or a gateway that allows different users into different places. +Combined with properly set up filter rules and secure switches, .Nm -logs the successful start and end of a session to -.Xr syslogd 8 . -This, combined with properly set up filter rules and secure switches, can be used to ensure users are held accountable for their network traffic. -.Pp -.Nm -can add filter and translation rules using the syntax described in -.Xr pf.conf 5 . -.Nm -requires that the +It is meant to be used with users who can connect via +.Xr ssh 1 +only, and requires the .Xr pf 4 -system be enabled and a -.Xr fdescfs 5 -file system be mounted at -.Pa /dev/fd -before use. +subsystem to be enabled. +.Pp +.Nm authpf-noip +is a user shell +which allows multiple connections to take +place from the same IP address. +It is useful primarily in cases where connections are tunneled via +the gateway system, and can be directly associated with the user name. +It cannot ensure accountability when +classifying connections by IP address; +in this case the client's IP address +is not provided to the packet filter via the +.Ar client_ip +macro or the +.Ar authpf_users +table. +Additionally, states associated with the client IP address +are not purged when the session is ended. +.Pp +To use either .Nm -can also maintain the list of IP address of connected users -in the "authpf_users" -.Pa table . +or +.Nm authpf-noip , +the user's shell needs to be set to +.Pa /usr/sbin/authpf +or +.Pa /usr/sbin/authpf-noip . .Pp .Nm -is meant to be used with users who can connect via +uses the +.Xr pf.conf 5 +syntax to change filter and translation rules for an individual +user or client IP address as long as a user maintains an active .Xr ssh 1 -only. -On startup, +session, and logs the successful start and end of a session to +.Xr syslogd 8 . .Nm retrieves the client's connecting IP address via the .Ev SSH_CLIENT environment variable and, after performing additional access checks, reads a template file to determine what filter and translation rules -(if any) to add. -On session exit the same rules that were added at startup are removed. +(if any) to add, and +maintains the list of IP addresses of connected users in the +.Ar authpf_users +table. +On session exit the same rules and table entries that were added at startup +are removed, and all states associated with the client's IP address are purged. .Pp Each .Nm @@ -185,6 +202,9 @@ It is also possible to configure to only allow specific users access. This is done by listing their login names, one per line, in .Pa /etc/authpf/authpf.allow . +A group of users can also be indicated by prepending "%" to the group name, +and all members of a login class can be indicated by prepending "@" to the +login class name. If "*" is found on a line, then all usernames match. If .Nm @@ -297,7 +317,8 @@ They have a wireless network which they would like to protect from unauthorized use. To accomplish this, they create the file .Pa /etc/authpf/authpf.allow -which lists their login ids, one per line. +which lists their login ids, group prepended with "%", or login class +prepended with "@", one per line. At this point, even if eve could authenticate to .Xr sshd 8 , she would not be allowed to use the gateway. @@ -501,6 +522,31 @@ table <authpf_users> persist anchor "authpf/*" from <authpf_users> rdr-anchor "authpf/*" from <authpf_users> .Ed +.Pp +.Sy Tunneled users +\- normally +.Nm +allows only one session per client IP address. +However in some cases, such as when connections are tunneled via +.Xr ssh 1 +or +.Xr ipsec 4 , +the connections can be authorized based on the userid of the user instead of +the client IP address. +In this case it is appropriate to use +.Nm authpf-noip +to allow multiple users behind a NAT gateway to connect. +In the +.Pa /etc/authpf/authpf.rules +example below, the remote user could tunnel a remote desktop session to their +workstation: +.Bd -literal +internal_if="bge0" +workstation_ip="10.2.3.4" + +pass out on $internal_if from (self) to $workstation_ip port 3389 \e + user $user_id +.Ed .Sh FILES .Bl -tag -width "/etc/authpf/authpf.conf" -compact .It Pa /etc/authpf/authpf.conf @@ -512,7 +558,6 @@ rdr-anchor "authpf/*" from <authpf_users .Sh SEE ALSO .Xr pf 4 , .Xr pf.conf 5 , -.Xr fdescfs 5 , .Xr securelevel 7 , .Xr ftp-proxy 8 .Sh HISTORY Modified: user/eri/pf45/head/contrib/pf/authpf/authpf.c ============================================================================== --- user/eri/pf45/head/contrib/pf/authpf/authpf.c Thu Oct 8 22:31:19 2009 (r197883) +++ user/eri/pf45/head/contrib/pf/authpf/authpf.c Thu Oct 8 22:33:19 2009 (r197884) @@ -1,4 +1,4 @@ -/* $OpenBSD: authpf.c,v 1.104 2007/02/24 17:35:08 beck Exp $ */ +/* $OpenBSD: authpf.c,v 1.111 2009/01/10 17:17:32 todd Exp $ */ /* * Copyright (C) 1998 - 2007 Bob Beck (beck@openbsd.org). @@ -16,10 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> +#include <sys/types.h> #include <sys/file.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -33,11 +30,9 @@ __FBSDID("$FreeBSD$"); #include <err.h> #include <errno.h> -#ifdef __FreeBSD__ -#include <inttypes.h> -#endif #include <login_cap.h> #include <pwd.h> +#include <grp.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -49,9 +44,10 @@ __FBSDID("$FreeBSD$"); static int read_config(FILE *); static void print_message(char *); -static int allowed_luser(char *); +static int allowed_luser(struct passwd *); static int check_luser(char *, char *); static int remove_stale_rulesets(void); +static int recursive_ruleset_purge(char *, char *); static int change_filter(int, const char *, const char *); static int change_table(int, const char *); static void authpf_kill_states(void); @@ -60,8 +56,10 @@ int dev; /* pf device */ char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf"; char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2]; char tablename[PF_TABLE_NAME_SIZE] = "authpf_users"; +int user_ip = 1; /* controls whether $user_ip is set */ FILE *pidfp; +int pidfd = -1; char luser[MAXLOGNAME]; /* username */ char ipsrc[256]; /* ip as a string */ char pidfile[MAXPATHLEN]; /* we save pid in this file. */ @@ -70,11 +68,8 @@ struct timeval Tstart, Tend; /* start an volatile sig_atomic_t want_death; static void need_death(int signo); -#ifdef __FreeBSD__ -static __dead2 void do_death(int); -#else static __dead void do_death(int); -#endif +extern char *__progname; /* program name */ /* * User shell for authenticating gateways. Sole purpose is to allow @@ -85,7 +80,7 @@ static __dead void do_death(int); int main(int argc, char *argv[]) { - int lockcnt = 0, n, pidfd; + int lockcnt = 0, n; FILE *config; struct in6_addr ina; struct passwd *pw; @@ -95,9 +90,12 @@ main(int argc, char *argv[]) char *shell; login_cap_t *lc; + if (strcmp(__progname, "-authpf-noip") == 0) + user_ip = 0; + config = fopen(PATH_CONFFILE, "r"); if (config == NULL) { - syslog(LOG_ERR, "can not open %s (%m)", PATH_CONFFILE); + syslog(LOG_ERR, "cannot open %s (%m)", PATH_CONFFILE); exit(1); } @@ -142,14 +140,15 @@ main(int argc, char *argv[]) } if ((lc = login_getclass(pw->pw_class)) != NULL) - shell = (char *)login_getcapstr(lc, "shell", pw->pw_shell, + shell = login_getcapstr(lc, "shell", pw->pw_shell, pw->pw_shell); else shell = pw->pw_shell; login_close(lc); - if (strcmp(shell, PATH_AUTHPF_SHELL)) { + if (strcmp(shell, PATH_AUTHPF_SHELL) && + strcmp(shell, PATH_AUTHPF_SHELL_NOIP)) { syslog(LOG_ERR, "wrong shell for user %s, uid %u", pw->pw_name, pw->pw_uid); if (shell != pw->pw_shell) @@ -181,13 +180,22 @@ main(int argc, char *argv[]) } - /* Make our entry in /var/authpf as /var/authpf/ipaddr */ - n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc); + /* Make our entry in /var/authpf as ipaddr or username */ + n = snprintf(pidfile, sizeof(pidfile), "%s/%s", + PATH_PIDFILE, user_ip ? ipsrc : luser); if (n < 0 || (u_int)n >= sizeof(pidfile)) { syslog(LOG_ERR, "path to pidfile too long"); goto die; } + signal(SIGTERM, need_death); + signal(SIGINT, need_death); + signal(SIGALRM, need_death); + signal(SIGPIPE, need_death); + signal(SIGHUP, need_death); + signal(SIGQUIT, need_death); + signal(SIGTSTP, need_death); + /* * If someone else is already using this ip, then this person * wants to switch users - so kill the old process and exit @@ -241,15 +249,17 @@ main(int argc, char *argv[]) } /* - * we try to kill the previous process and acquire the lock + * We try to kill the previous process and acquire the lock * for 10 seconds, trying once a second. if we can't after - * 10 attempts we log an error and give up + * 10 attempts we log an error and give up. */ - if (++lockcnt > 10) { - syslog(LOG_ERR, "cannot kill previous authpf (pid %d)", - otherpid); + if (want_death || ++lockcnt > 10) { + if (!want_death) + syslog(LOG_ERR, "cannot kill previous authpf (pid %d)", + otherpid); fclose(pidfp); pidfp = NULL; + pidfd = -1; goto dogdeath; } sleep(1); @@ -260,6 +270,7 @@ main(int argc, char *argv[]) */ fclose(pidfp); pidfp = NULL; + pidfd = -1; } while (1); /* whack the group list */ @@ -277,7 +288,7 @@ main(int argc, char *argv[]) } openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON); - if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) { + if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(pw)) { syslog(LOG_INFO, "user %s prohibited", luser); do_death(0); } @@ -302,19 +313,12 @@ main(int argc, char *argv[]) printf("Unable to modify filters\r\n"); do_death(0); } - if (change_table(1, ipsrc) == -1) { + if (user_ip && change_table(1, ipsrc) == -1) { printf("Unable to modify table\r\n"); change_filter(0, luser, ipsrc); do_death(0); } - signal(SIGTERM, need_death); - signal(SIGINT, need_death); - signal(SIGALRM, need_death); - signal(SIGPIPE, need_death); - signal(SIGHUP, need_death); - signal(SIGQUIT, need_death); - signal(SIGTSTP, need_death); while (1) { printf("\r\nHello %s. ", luser); printf("You are authenticated from host \"%s\"\r\n", ipsrc); @@ -337,8 +341,6 @@ dogdeath: sleep(180); /* them lusers read reaaaaal slow */ die: do_death(0); - - /* NOTREACHED */ } /* @@ -361,6 +363,8 @@ read_config(FILE *f) } i++; len = strlen(buf); + if (len == 0) + continue; if (buf[len - 1] != '\n' && !feof(f)) { syslog(LOG_ERR, "line %d too long in %s", i, PATH_CONFFILE); @@ -436,6 +440,7 @@ print_message(char *filename) * allowed_luser checks to see if user "luser" is allowed to * use this gateway by virtue of being listed in an allowed * users file, namely /etc/authpf/authpf.allow . + * Users may be listed by <username>, %<group>, or @<login_class>. * * If /etc/authpf/authpf.allow does not exist, then we assume that * all users who are allowed in by sshd(8) are permitted to @@ -444,7 +449,7 @@ print_message(char *filename) * the session terminates in the same manner as being banned. */ static int -allowed_luser(char *luser) +allowed_luser(struct passwd *pw) { char *buf, *lbuf; int matched; @@ -476,8 +481,14 @@ allowed_luser(char *luser) * "public" gateway, such as it is, so let * everyone use it. */ + int gl_init = 0, ngroups = NGROUPS + 1; + gid_t groups[NGROUPS + 1]; + lbuf = NULL; + matched = 0; + while ((buf = fgetln(f, &len))) { + if (buf[len - 1] == '\n') buf[len - 1] = '\0'; else { @@ -488,7 +499,40 @@ allowed_luser(char *luser) buf = lbuf; } - matched = strcmp(luser, buf) == 0 || strcmp("*", buf) == 0; + if (buf[0] == '@') { + /* check login class */ + if (strcmp(pw->pw_class, buf + 1) == 0) + matched++; + } else if (buf[0] == '%') { + /* check group membership */ + int cnt; + struct group *group; + + if ((group = getgrnam(buf + 1)) == NULL) { + syslog(LOG_ERR, + "invalid group '%s' in %s (%s)", + buf + 1, PATH_ALLOWFILE, + strerror(errno)); + return (0); + } + + if (!gl_init) { + (void) getgrouplist(pw->pw_name, + pw->pw_gid, groups, &ngroups); + gl_init++; + } + + for ( cnt = 0; cnt < ngroups; cnt++) { + if (group->gr_gid == groups[cnt]) { + matched++; + break; + } + } + } else { + /* check username and wildcard */ + matched = strcmp(pw->pw_name, buf) == 0 || + strcmp("*", buf) == 0; + } if (lbuf != NULL) { free(lbuf); @@ -496,10 +540,10 @@ allowed_luser(char *luser) } if (matched) - return (1); /* matched an allowed username */ + return (1); /* matched an allowed user/group */ } syslog(LOG_INFO, "denied access to %s: not listed in %s", - luser, PATH_ALLOWFILE); + pw->pw_name, PATH_ALLOWFILE); /* reuse buf */ buf = "\n\nSorry, you are not allowed to use this facility!\n"; @@ -581,7 +625,7 @@ static int remove_stale_rulesets(void) { struct pfioc_ruleset prs; - u_int32_t nr, mnr; + u_int32_t nr; memset(&prs, 0, sizeof(prs)); strlcpy(prs.path, anchorname, sizeof(prs.path)); @@ -592,13 +636,12 @@ remove_stale_rulesets(void) return (1); } - mnr = prs.nr; - nr = 0; - while (nr < mnr) { + nr = prs.nr; + while (nr) { char *s, *t; pid_t pid; - prs.nr = nr; + prs.nr = nr - 1; if (ioctl(dev, DIOCGETRULESET, &prs)) return (1); errno = 0; @@ -610,119 +653,159 @@ remove_stale_rulesets(void) if (!prs.name[0] || errno || (*s && (t == prs.name || *s != ')'))) return (1); - if (kill(pid, 0) && errno != EPERM) { - int i; - struct pfioc_trans_e t_e[PF_RULESET_MAX+1]; - struct pfioc_trans t; - - bzero(&t, sizeof(t)); - bzero(t_e, sizeof(t_e)); - t.size = PF_RULESET_MAX+1; - t.esize = sizeof(t_e[0]); - t.array = t_e; - for (i = 0; i < PF_RULESET_MAX+1; ++i) { - t_e[i].rs_num = i; - snprintf(t_e[i].anchor, sizeof(t_e[i].anchor), - "%s/%s", anchorname, prs.name); - } - t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE; - if ((ioctl(dev, DIOCXBEGIN, &t) || - ioctl(dev, DIOCXCOMMIT, &t)) && - errno != EINVAL) + if ((kill(pid, 0) && errno != EPERM) || pid == getpid()) { + if (recursive_ruleset_purge(anchorname, prs.name)) return (1); - mnr--; - } else - nr++; + } + nr--; } return (0); } +static int +recursive_ruleset_purge(char *an, char *rs) +{ + struct pfioc_trans_e *t_e = NULL; + struct pfioc_trans *t = NULL; + struct pfioc_ruleset *prs = NULL; + int i; + + + /* purge rules */ + errno = 0; + if ((t = calloc(1, sizeof(struct pfioc_trans))) == NULL) + goto no_mem; + if ((t_e = calloc(PF_RULESET_MAX+1, + sizeof(struct pfioc_trans_e))) == NULL) + goto no_mem; + t->size = PF_RULESET_MAX+1; + t->esize = sizeof(struct pfioc_trans_e); + t->array = t_e; + for (i = 0; i < PF_RULESET_MAX+1; ++i) { + t_e[i].rs_num = i; + snprintf(t_e[i].anchor, sizeof(t_e[i].anchor), "%s/%s", an, rs); + } + t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE; + if ((ioctl(dev, DIOCXBEGIN, t) || + ioctl(dev, DIOCXCOMMIT, t)) && + errno != EINVAL) + goto cleanup; + + /* purge any children */ + if ((prs = calloc(1, sizeof(struct pfioc_ruleset))) == NULL) + goto no_mem; + snprintf(prs->path, sizeof(prs->path), "%s/%s", an, rs); + if (ioctl(dev, DIOCGETRULESETS, prs)) { + if (errno != EINVAL) + goto cleanup; + errno = 0; + } else { + int nr = prs->nr; + + while (nr) { + prs->nr = 0; + if (ioctl(dev, DIOCGETRULESET, prs)) + goto cleanup; + + if (recursive_ruleset_purge(prs->path, prs->name)) + goto cleanup; + nr--; + } + } + +no_mem: + if (errno == ENOMEM) + syslog(LOG_ERR, "calloc failed"); + +cleanup: + free(t); + free(t_e); + free(prs); + return (errno); +} + /* * Add/remove filter entries for user "luser" from ip "ipsrc" */ static int change_filter(int add, const char *luser, const char *ipsrc) { - char *pargv[13] = { - "pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset", - "-D", "user_ip=X", "-D", "user_id=X", "-f", - "file", NULL - }; char *fdpath = NULL, *userstr = NULL, *ipstr = NULL; char *rsn = NULL, *fn = NULL; pid_t pid; gid_t gid; int s; - if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) { - syslog(LOG_ERR, "invalid luser/ipsrc"); - goto error; - } - - if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1) - goto no_mem; - if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1) - goto no_mem; - if (asprintf(&ipstr, "user_ip=%s", ipsrc) == -1) - goto no_mem; - if (asprintf(&userstr, "user_id=%s", luser) == -1) - goto no_mem; - if (add) { struct stat sb; + char *pargv[13] = { + "pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset", + "-D", "user_id=X", "-D", "user_ip=X", "-f", "file", NULL + }; + + if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) { + syslog(LOG_ERR, "invalid luser/ipsrc"); + goto error; + } - if (asprintf(&fn, "%s/%s/authpf.rules", PATH_USER_DIR, luser) - == -1) + if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1) + goto no_mem; + if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1) + goto no_mem; + if (asprintf(&ipstr, "user_ip=%s", ipsrc) == -1) + goto no_mem; + if (asprintf(&userstr, "user_id=%s", luser) == -1) + goto no_mem; + if (asprintf(&fn, "%s/%s/authpf.rules", + PATH_USER_DIR, luser) == -1) goto no_mem; if (stat(fn, &sb) == -1) { free(fn); if ((fn = strdup(PATH_PFRULES)) == NULL) goto no_mem; } - } - pargv[2] = fdpath; - pargv[5] = rsn; - pargv[7] = userstr; - pargv[9] = ipstr; - if (!add) - pargv[11] = "/dev/null"; - else - pargv[11] = fn; + pargv[2] = fdpath; + pargv[5] = rsn; + pargv[7] = userstr; + if (user_ip) { + pargv[9] = ipstr; + pargv[11] = fn; + } else { + pargv[8] = "-f"; + pargv[9] = fn; + pargv[10] = NULL; + } - switch (pid = fork()) { - case -1: - syslog(LOG_ERR, "fork failed"); - goto error; - case 0: - /* revoke group privs before exec */ - gid = getgid(); - if (setregid(gid, gid) == -1) { - err(1, "setregid"); - } - execvp(PATH_PFCTL, pargv); - warn("exec of %s failed", PATH_PFCTL); - _exit(1); - } - - /* parent */ - waitpid(pid, &s, 0); - if (s != 0) { - syslog(LOG_ERR, "pfctl exited abnormally"); - goto error; - } + switch (pid = fork()) { + case -1: + syslog(LOG_ERR, "fork failed"); + goto error; + case 0: + /* revoke group privs before exec */ + gid = getgid(); + if (setregid(gid, gid) == -1) { + err(1, "setregid"); + } + execvp(PATH_PFCTL, pargv); + warn("exec of %s failed", PATH_PFCTL); + _exit(1); + } + + /* parent */ + waitpid(pid, &s, 0); + if (s != 0) { + syslog(LOG_ERR, "pfctl exited abnormally"); + goto error; + } - if (add) { gettimeofday(&Tstart, NULL); syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser); } else { + remove_stale_rulesets(); + gettimeofday(&Tend, NULL); -#ifdef __FreeBSD__ - syslog(LOG_INFO, "removed %s, user %s - duration %jd seconds", - ipsrc, luser, (intmax_t)(Tend.tv_sec - Tstart.tv_sec)); -#else syslog(LOG_INFO, "removed %s, user %s - duration %ld seconds", ipsrc, luser, Tend.tv_sec - Tstart.tv_sec); -#endif } return (0); no_mem: @@ -829,22 +912,19 @@ need_death(int signo) /* * function that removes our stuff when we go away. */ -#ifdef __FreeBSD__ -static __dead2 void -#else static __dead void -#endif do_death(int active) { int ret = 0; if (active) { change_filter(0, luser, ipsrc); - change_table(0, ipsrc); - authpf_kill_states(); - remove_stale_rulesets(); + if (user_ip) { + change_table(0, ipsrc); + authpf_kill_states(); + } } - if (pidfile[0] && (pidfp != NULL)) + if (pidfile[0] && pidfd != -1) if (unlink(pidfile) == -1) syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile); exit(ret); Modified: user/eri/pf45/head/contrib/pf/authpf/pathnames.h ============================================================================== --- user/eri/pf45/head/contrib/pf/authpf/pathnames.h Thu Oct 8 22:31:19 2009 (r197883) +++ user/eri/pf45/head/contrib/pf/authpf/pathnames.h Thu Oct 8 22:33:19 2009 (r197884) @@ -35,4 +35,5 @@ #define PATH_DEVFILE "/dev/pf" #define PATH_PIDFILE "/var/authpf" #define PATH_AUTHPF_SHELL "/usr/sbin/authpf" +#define PATH_AUTHPF_SHELL_NOIP "/usr/sbin/authpf-noip" #define PATH_PFCTL "/sbin/pfctl" Modified: user/eri/pf45/head/contrib/pf/ftp-proxy/filter.c ============================================================================== --- user/eri/pf45/head/contrib/pf/ftp-proxy/filter.c Thu Oct 8 22:31:19 2009 (r197883) +++ user/eri/pf45/head/contrib/pf/ftp-proxy/filter.c Thu Oct 8 22:33:19 2009 (r197884) @@ -1,4 +1,4 @@ -/* $OpenBSD: filter.c,v 1.5 2006/12/01 07:31:21 camield Exp $ */ +/* $OpenBSD: filter.c,v 1.7 2008/02/26 18:52:53 henning Exp $ */ /* * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> @@ -53,7 +53,7 @@ static struct pfioc_rule pfr; static struct pfioc_trans pft; static struct pfioc_trans_e pfte[TRANS_SIZE]; static int dev, rule_log; -static char *qname; +static char *qname, *tagname; int add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src, @@ -159,11 +159,12 @@ do_rollback(void) } void -init_filter(char *opt_qname, int opt_verbose) +init_filter(char *opt_qname, char *opt_tagname, int opt_verbose) { struct pf_status status; qname = opt_qname; + tagname = opt_tagname; if (opt_verbose == 1) rule_log = PF_LOG; @@ -172,7 +173,7 @@ init_filter(char *opt_qname, int opt_ver dev = open("/dev/pf", O_RDWR); if (dev == -1) - err(1, "/dev/pf"); + err(1, "open /dev/pf"); if (ioctl(dev, DIOCGETSTATUS, &status) == -1) err(1, "DIOCGETSTATUS"); if (!status.running) @@ -280,9 +281,9 @@ prepare_rule(u_int32_t id, int rs_num, s switch (rs_num) { case PF_RULESET_FILTER: /* - * pass quick [log] inet[6] proto tcp \ + * pass [quick] [log] inet[6] proto tcp \ * from $src to $dst port = $d_port flags S/SA keep state - * (max 1) [queue qname] + * (max 1) [queue qname] [tag tagname] */ pfr.rule.action = PF_PASS; pfr.rule.quick = 1; @@ -293,6 +294,11 @@ prepare_rule(u_int32_t id, int rs_num, s pfr.rule.max_states = 1; if (qname != NULL) strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname); + if (tagname != NULL) { + pfr.rule.quick = 0; + strlcpy(pfr.rule.tagname, tagname, + sizeof pfr.rule.tagname); + } break; case PF_RULESET_NAT: /* Modified: user/eri/pf45/head/contrib/pf/ftp-proxy/filter.h ============================================================================== --- user/eri/pf45/head/contrib/pf/ftp-proxy/filter.h Thu Oct 8 22:31:19 2009 (r197883) +++ user/eri/pf45/head/contrib/pf/ftp-proxy/filter.h Thu Oct 8 22:33:19 2009 (r197884) @@ -26,6 +26,6 @@ int add_rdr(u_int32_t, struct sockaddr * struct sockaddr *, u_int16_t); int do_commit(void); int do_rollback(void); -void init_filter(char *, int); +void init_filter(char *, char *, int); int prepare_commit(u_int32_t); int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *); Modified: user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.8 ============================================================================== --- user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.8 Thu Oct 8 22:31:19 2009 (r197883) +++ user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.8 Thu Oct 8 22:33:19 2009 (r197884) @@ -1,4 +1,4 @@ -.\" $OpenBSD: ftp-proxy.8,v 1.7 2006/12/30 13:01:54 camield Exp $ +.\" $OpenBSD: ftp-proxy.8,v 1.10 2007/08/01 15:45:41 jmc Exp $ .\" .\" Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> .\" @@ -14,16 +14,15 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" $FreeBSD$ -.\" -.Dd November 28, 2004 +.Dd $Mdocdate$ .Dt FTP-PROXY 8 .Os .Sh NAME .Nm ftp-proxy .Nd Internet File Transfer Protocol proxy daemon .Sh SYNOPSIS -.Nm ftp-proxy +.Nm +.Bk -words .Op Fl 6Adrv .Op Fl a Ar address .Op Fl b Ar address @@ -33,7 +32,9 @@ .Op Fl p Ar port .Op Fl q Ar queue .Op Fl R Ar address +.Op Fl T Ar tag .Op Fl t Ar timeout +.Ek .Sh DESCRIPTION .Nm is a proxy for the Internet File Transfer Protocol. @@ -58,7 +59,7 @@ facility for this. Assuming the FTP control connection is from $client to $server, the proxy connected to the server using the $proxy source address, and $port is negotiated, then -.Nm ftp-proxy +.Nm adds the following rules to the various anchors. (These example rules use inet, but the proxy also supports inet6.) .Pp @@ -130,6 +131,20 @@ connections to another proxy. .It Fl r Rewrite sourceport to 20 in active mode to suit ancient clients that insist on this RFC property. +.It Fl T Ar tag +The filter rules will add tag +.Ar tag +to data connections, and not match quick. +This way alternative rules that use the +.Ar tagged +keyword can be implemented following the +.Nm +anchor. +These rules can use special +.Xr pf 4 +features like route-to, reply-to, label, rtable, overload, etc. that +.Nm +does not implement itself. .It Fl t Ar timeout Number of seconds that the control connection can be idle, before the proxy will disconnect. @@ -172,7 +187,7 @@ does not allow the ruleset to be modifie .Xr securelevel 7 higher than 1. At that level -.Nm ftp-proxy +.Nm cannot add rules to the anchors and FTP data connections may get blocked. .Pp Negotiated data connection ports below 1024 are not allowed. @@ -181,5 +196,5 @@ The negotiated IP address for active mod reasons. This makes third party file transfers impossible. .Pp -.Nm ftp-proxy +.Nm chroots to "/var/empty" and changes to user "proxy" to drop privileges. Modified: user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.c ============================================================================== --- user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.c Thu Oct 8 22:31:19 2009 (r197883) +++ user/eri/pf45/head/contrib/pf/ftp-proxy/ftp-proxy.c Thu Oct 8 22:33:19 2009 (r197884) @@ -1,4 +1,4 @@ -/* $OpenBSD: ftp-proxy.c,v 1.13 2006/12/30 13:24:00 camield Exp $ */ +/* $OpenBSD: ftp-proxy.c,v 1.18 2008/04/22 02:22:22 joel Exp $ */ /* * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> @@ -16,9 +16,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/queue.h> #include <sys/types.h> #include <sys/time.h> @@ -94,7 +91,7 @@ int client_parse_cmd(struct session *s); void client_read(struct bufferevent *, void *); int drop_privs(void); void end_session(struct session *); -int exit_daemon(void); +void exit_daemon(void); int getline(char *, size_t *); void handle_connection(const int, short, void *); void handle_signal(int, short, void *); @@ -105,6 +102,7 @@ u_int16_t pick_proxy_port(void); void proxy_reply(int, struct sockaddr *, u_int16_t); void server_error(struct bufferevent *, short, void *); int server_parse(struct session *s); +int allow_data_connection(struct session *s); void server_read(struct bufferevent *, void *); const char *sock_ntop(struct sockaddr *); void usage(void); @@ -116,7 +114,7 @@ char ntop_buf[NTOP_BUFS][INET6_ADDRSTRLE struct sockaddr_storage fixed_server_ss, fixed_proxy_ss; char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port, - *qname; + *qname, *tagname; int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions, rfc_mode, session_count, timeout, verbose; extern char *__progname; @@ -152,8 +150,19 @@ client_parse(struct session *s) return (1); if (linebuf[0] == 'P' || linebuf[0] == 'p' || - linebuf[0] == 'E' || linebuf[0] == 'e') - return (client_parse_cmd(s)); + linebuf[0] == 'E' || linebuf[0] == 'e') { + if (!client_parse_cmd(s)) + return (0); + + /* + * Allow active mode connections immediately, instead of + * waiting for a positive reply from the server. Some + * rare servers/proxies try to probe or setup the data + * connection before an actual transfer request. + */ + if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) + return (allow_data_connection(s)); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910082233.n98MXJK6035533>