diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2002-05-12 00:54:57 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2002-05-12 00:54:57 +0000 |
commit | 05de2ef6012d56fcdf31b2bc6ec425ea015011b4 (patch) | |
tree | ab1a9ae53e9c815f90c3ffb8c69e874f0bd0e6e9 | |
parent | e9ef1df3259dcdea5c753bb82ccb9abfad765439 (diff) |
Add gid based filtering, reduce to one (effective) uid, rename parser
keywords to 'user' and 'group'.
-rw-r--r-- | sbin/pfctl/parse.y | 121 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 27 | ||||
-rw-r--r-- | share/man/man5/pf.conf.5 | 26 | ||||
-rw-r--r-- | sys/net/pf.c | 65 | ||||
-rw-r--r-- | sys/net/pfvar.h | 14 |
5 files changed, 174 insertions, 79 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index d2fcc2552ca..85d9fd077d6 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.64 2002/05/10 14:09:53 dhartmei Exp $ */ +/* $OpenBSD: parse.y,v 1.65 2002/05/12 00:54:56 dhartmei Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -89,6 +89,12 @@ struct node_uid { struct node_uid *next; }; +struct node_gid { + gid_t gid[2]; + u_int8_t op; + struct node_gid *next; +}; + struct node_icmp { u_int8_t code; u_int8_t type; @@ -109,7 +115,7 @@ void expand_rule(struct pf_rule *, struct node_if *, struct node_proto *, struct node_host *, struct node_port *, struct node_host *, struct node_port *, - struct node_uid *, struct node_uid *, + struct node_uid *, struct node_gid *, struct node_icmp *); struct sym { @@ -147,6 +153,7 @@ typedef struct { struct node_host *host; struct node_port *port; struct node_uid *uid; + struct node_gid *gid; struct peer peer; struct { struct peer src, dst; @@ -171,12 +178,12 @@ typedef struct { %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF %token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO NO LABEL -%token NOROUTE FRAGMENT RUID EUID MAXMSS +%token NOROUTE FRAGMENT USER GROUP MAXMSS %token <v.string> STRING %token <v.number> NUMBER %token <v.i> PORTUNARY PORTBINARY %type <v.interface> interface if_list if_item_not if_item -%type <v.number> port icmptype icmp6type minttl uid maxmss +%type <v.number> port icmptype icmp6type minttl uid gid maxmss %type <v.i> no dir log quick af keep nodf allowopts fragment %type <v.b> action flag flags blockspec %type <v.range> dport rport @@ -186,7 +193,8 @@ typedef struct { %type <v.peer> ipportspec %type <v.host> ipspec xhost host address host_list IPV6ADDR %type <v.port> portspec port_list port_item -%type <v.uid> ruid euid uid_list uid_item +%type <v.uid> uids uid_list uid_item +%type <v.gid> gids gid_list gid_item %type <v.route> route %type <v.redirection> redirection %type <v.string> label @@ -213,7 +221,7 @@ varset : STRING PORTUNARY STRING } ; -pfrule : action dir log quick interface route af proto fromto ruid euid flags icmpspec keep fragment nodf minttl maxmss allowopts label +pfrule : action dir log quick interface route af proto fromto uids gids flags icmpspec keep fragment nodf minttl maxmss allowopts label { struct pf_rule r; @@ -644,14 +652,9 @@ port : NUMBER { } ; -ruid : /* empty */ { $$ = NULL; } - | RUID uid_item { $$ = $2; } - | RUID '{' uid_list '}' { $$ = $3; } - ; - -euid : /* empty */ { $$ = NULL; } - | EUID uid_item { $$ = $2; } - | EUID '{' uid_list '}' { $$ = $3; } +uids : /* empty */ { $$ = NULL; } + | USER uid_item { $$ = $2; } + | USER '{' uid_list '}' { $$ = $3; } ; uid_list : uid_item { $$ = $1; } @@ -709,6 +712,66 @@ uid : NUMBER { } ; +gids : /* empty */ { $$ = NULL; } + | GROUP gid_item { $$ = $2; } + | GROUP '{' gid_list '}' { $$ = $3; } + ; + +gid_list : gid_item { $$ = $1; } + | gid_list ',' gid_item { $3->next = $1; $$ = $3; } + ; + +gid_item : gid { + $$ = malloc(sizeof(struct node_gid)); + if ($$ == NULL) + err(1, "gid_item: malloc"); + $$->gid[0] = $1; + $$->gid[1] = $1; + $$->op = PF_OP_EQ; + $$->next = NULL; + } + | PORTUNARY gid { + $$ = malloc(sizeof(struct node_gid)); + if ($$ == NULL) + err(1, "gid_item: malloc"); + $$->gid[0] = $2; + $$->gid[1] = $2; + $$->op = $1; + $$->next = NULL; + } + | gid PORTBINARY gid { + $$ = malloc(sizeof(struct node_gid)); + if ($$ == NULL) + err(1, "gid_item: malloc"); + $$->gid[0] = $1; + $$->gid[1] = $3; + $$->op = $2; + $$->next = NULL; + } + ; + +gid : NUMBER { + if ($1 < 0 || $1 >= GID_MAX) { + yyerror("illegal gid value %d", $1); + YYERROR; + } + $$ = $1; + } + | STRING { + if (!strcmp($1, "unknown")) + $$ = GID_MAX; + else { + struct passwd *pw; + + if ((pw = getpwnam($1)) == NULL) { + yyerror("unknown group %s", $1); + YYERROR; + } + $$ = pw->pw_uid; + } + } + ; + flag : STRING { int f; @@ -1499,7 +1562,7 @@ expand_rule(struct pf_rule *r, struct node_if *interfaces, struct node_proto *protos, struct node_host *src_hosts, struct node_port *src_ports, struct node_host *dst_hosts, struct node_port *dst_ports, - struct node_uid *ruids, struct node_uid *euids, + struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types) { int nomatch = 0; @@ -1510,8 +1573,8 @@ expand_rule(struct pf_rule *r, CHECK_ROOT(struct node_port, src_ports); CHECK_ROOT(struct node_host, dst_hosts); CHECK_ROOT(struct node_port, dst_ports); - CHECK_ROOT(struct node_uid, ruids); - CHECK_ROOT(struct node_uid, euids); + CHECK_ROOT(struct node_uid, uids); + CHECK_ROOT(struct node_gid, gids); CHECK_ROOT(struct node_icmp, icmp_types); LOOP_THROUGH(struct node_if, interface, interfaces, @@ -1521,8 +1584,8 @@ expand_rule(struct pf_rule *r, LOOP_THROUGH(struct node_port, src_port, src_ports, LOOP_THROUGH(struct node_host, dst_host, dst_hosts, LOOP_THROUGH(struct node_port, dst_port, dst_ports, - LOOP_THROUGH(struct node_uid, ruid, ruids, - LOOP_THROUGH(struct node_uid, euid, euids, + LOOP_THROUGH(struct node_uid, uid, uids, + LOOP_THROUGH(struct node_gid, gid, gids, memcpy(r->ifname, interface->ifname, sizeof(r->ifname)); r->proto = proto->proto; @@ -1540,12 +1603,12 @@ expand_rule(struct pf_rule *r, r->dst.port[0] = dst_port->port[0]; r->dst.port[1] = dst_port->port[1]; r->dst.port_op = dst_port->op; - r->ruid.op = ruid->op; - r->ruid.uid[0] = ruid->uid[0]; - r->ruid.uid[1] = ruid->uid[1]; - r->euid.op = euid->op; - r->euid.uid[0] = euid->uid[0]; - r->euid.uid[1] = euid->uid[1]; + r->uid.op = uid->op; + r->uid.uid[0] = uid->uid[0]; + r->uid.uid[1] = uid->uid[1]; + r->gid.op = gid->op; + r->gid.gid[0] = gid->gid[0]; + r->gid.gid[1] = gid->gid[1]; r->type = icmp_type->type; r->code = icmp_type->code; @@ -1592,8 +1655,8 @@ expand_rule(struct pf_rule *r, FREE_LIST(struct node_port, src_ports); FREE_LIST(struct node_host, dst_hosts); FREE_LIST(struct node_port, dst_ports); - FREE_LIST(struct node_uid, ruids); - FREE_LIST(struct node_uid, euids); + FREE_LIST(struct node_uid, uids); + FREE_LIST(struct node_gid, gids); FREE_LIST(struct node_icmp, icmp_types); } @@ -1620,11 +1683,11 @@ lookup(char *s) { "block", BLOCK}, { "code", CODE}, { "dup-to", DUPTO}, - { "euid", EUID}, { "fastroute", FASTROUTE}, { "flags", FLAGS}, { "fragment", FRAGMENT}, { "from", FROM}, + { "group", GROUP}, { "icmp-type", ICMPTYPE}, { "in", IN}, { "inet", INET}, @@ -1653,10 +1716,10 @@ lookup(char *s) { "return-icmp6",RETURNICMP6}, { "return-rst", RETURNRST}, { "route-to", ROUTETO}, - { "ruid", RUID}, { "scrub", SCRUB}, { "state", STATE}, { "to", TO}, + { "user", USER}, }; const struct keywords *p; diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 9d8cba5e749..f84afef9593 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.69 2002/05/09 21:58:12 jasoni Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.70 2002/05/12 00:54:56 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -61,6 +61,7 @@ void print_seq (struct pf_state_peer *); void print_op (u_int8_t, const char *, const char *); void print_port (u_int8_t, u_int16_t, u_int16_t, char *); void print_uid (u_int8_t, uid_t, uid_t, const char *); +void print_gid (u_int8_t, gid_t, gid_t, const char *); void print_flags (u_int8_t); char *tcpflags = "FSRPAU"; @@ -405,6 +406,20 @@ print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t) } void +print_gid(u_int8_t op, gid_t g1, gid_t g2, const char *t) +{ + char a1[5], a2[5]; + + snprintf(a1, sizeof(a1), "%u", g1); + snprintf(a2, sizeof(a2), "%u", g2); + printf("%s ", t); + if (g1 == GID_MAX && (op == PF_OP_EQ || op == PF_OP_NE)) + print_op(op, "unknown", a2); + else + print_op(op, a1, a2); +} + +void print_flags(u_int8_t f) { int i; @@ -803,12 +818,10 @@ print_rule(struct pf_rule *r) r->dst.port[1], r->proto == IPPROTO_TCP ? "tcp" : "udp"); } - if (r->ruid.op) { - print_uid(r->ruid.op, r->ruid.uid[0], r->ruid.uid[1], "ruid"); - } - if (r->euid.op) { - print_uid(r->euid.op, r->euid.uid[0], r->euid.uid[1], "euid"); - } + if (r->uid.op) + print_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user"); + if (r->gid.op) + print_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group"); if (r->flags || r->flagset) { printf("flags "); print_flags(r->flags); diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index d05e4fb463d..eef2d49e932 100644 --- a/share/man/man5/pf.conf.5 +++ b/share/man/man5/pf.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pf.conf.5,v 1.44 2002/05/09 21:58:12 jasoni Exp $ +.\" $OpenBSD: pf.conf.5,v 1.45 2002/05/12 00:54:56 dhartmei Exp $ .\" .\" Copyright (c) 2001, Daniel Hartmeier .\" All rights reserved. @@ -51,7 +51,7 @@ rule = action ( "in" | "out" ) [ "proto" ( proto-name | proto-number | "{" proto-list "}" ) ] hosts - [ ruid ] [ euid ] [ flags ] + [ user ] [ group ] [ flags ] [ icmp-type | ipv6-icmp-type ] [ "keep state" ] [ "modulate state" ] [ "fragment" ] [ "no-df" ] [ "min-ttl" number ] @@ -84,8 +84,8 @@ address = ( interface-name | '(' interface-name ')' | host-name | host-list = host [ "," host-list ] . port = "port" ( unary-op | binary-op | "{" op-list "}" ) . -ruid = "ruid" ( unary-op | binary-op | "{" op-list "}" ) . -euid = "euid" ( unary-op | binary-op | "{" op-list "}" ) . +user = "user" ( unary-op | binary-op | "{" op-list "}" ) . +group = "group" ( unary-op | binary-op | "{" op-list "}" ) . unary-op = [ "=" | "!=" | "<" | "<=" | ">" | ">=" ] ( name | number ) . @@ -271,26 +271,28 @@ show: pass in proto tcp from any to any port 25 pass in proto tcp from 10.0.0.0/8 port > 1024 to ! 10.1.2.3 port != 22 .Ed -.Ss ruid <ruid> euid <euid> -The rule only applies to packets of sockets owned by the respective real -and effective user IDs. +.Ss user <user> group <group> +The rule only applies to packets of sockets owned by the specified user +and group. For outgoing connections initiated from the firewall, this is the user that opened the connection. For incoming connections to the firewall itself, this is the user that listens on the destination port. For forwarded connections, where the firewall isn't a connection endpoint, -the user is +the user and group are .Em unknown . All packets, both outgoing and incoming, of one connection are associated with the same user. Only TCP and UDP packets can be associated with users, for other protocols these parameters are ignored. -Note that user IDs are stored when a socket is created; +User and group refer to the effective (as opposed to the real) IDs, in +case the socket is created by a setuid/setgid process. +Note that user and group IDs are stored when a socket is created; when a process creates a listening socket as root (for instance, because it wants to bind to a privileged port) and subsequently sets another user ID (to drop privileges), the socket's uid remains root. -User IDs can be specified as either numbers or names, the syntax is -similar to the one for ports. +User and group IDs can be specified as either numbers or names, the +syntax is similar to the one for ports. The value .Em unknown matches packets of forwarded connections. @@ -298,7 +300,7 @@ Example: .Bd -literal # allow only specific users to open outgoing connections block out proto { tcp, udp } all - pass out proto { tcp, udp } all ruid { < 1000, dhartmei } keep state + pass out proto { tcp, udp } all user { < 1000, dhartmei } keep state .Ed .Ss flags <a> | <a>/<b> | /<b> The rule only applies to TCP packets that have the flags <a> set diff --git a/sys/net/pf.c b/sys/net/pf.c index 50400f337e5..910798a6cd6 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.206 2002/05/09 19:58:42 dhartmei Exp $ */ +/* $OpenBSD: pf.c,v 1.207 2002/05/12 00:54:56 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -276,7 +276,7 @@ int pf_normalize_tcp(int, struct ifnet *, struct mbuf *, int, int, void *, struct pf_pdesc *); void pf_route(struct mbuf **, struct pf_rule *, int); void pf_route6(struct mbuf **, struct pf_rule *, int); -int pf_user_lookup(uid_t *, uid_t *, int, int, int, +int pf_socket_lookup(uid_t *, gid_t *, int, int, int, struct pf_pdesc *); @@ -2972,7 +2972,7 @@ pf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p) } int -pf_match_uid(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t u) +pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u) { if (u == UID_MAX && op != PF_OP_EQ && op != PF_OP_NE) return (0); @@ -2980,6 +2980,14 @@ pf_match_uid(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t u) } int +pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g) +{ + if (g == GID_MAX && op != PF_OP_EQ && op != PF_OP_NE) + return (0); + return (pf_match(op, a1, a2, g)); +} + +int pf_chk_sport(struct pf_port_list *plist, u_int16_t port) { struct pf_port_node *pnode; @@ -3195,7 +3203,7 @@ pf_map_port_range(struct pf_rdr *rdr, u_int16_t port) } int -pf_user_lookup(uid_t *ruid, uid_t *euid, int direction, int af, int proto, +pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, int af, int proto, struct pf_pdesc *pd) { struct pf_addr *saddr, *daddr; @@ -3203,7 +3211,8 @@ pf_user_lookup(uid_t *ruid, uid_t *euid, int direction, int af, int proto, struct inpcbtable *tb; struct inpcb *inp; - *ruid = *euid = UID_MAX; + *uid = UID_MAX; + *gid = GID_MAX; if (af != AF_INET) return (0); switch (proto) { @@ -3239,8 +3248,8 @@ pf_user_lookup(uid_t *ruid, uid_t *euid, int direction, int af, int proto, if (inp == NULL) return (0); } - *ruid = inp->inp_socket->so_ruid; - *euid = inp->inp_socket->so_euid; + *uid = inp->inp_socket->so_euid; + *gid = inp->inp_socket->so_egid; return (1); } @@ -3254,8 +3263,9 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp, struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr; struct tcphdr *th = pd->hdr.tcp; u_int16_t bport, nport = 0, af = pd->af; - int xuid = -1; - uid_t ruid, euid; + int lookup = -1; + uid_t uid; + gid_t gid; struct pf_rule *r; u_short reason; int rewrite = 0, error; @@ -3348,15 +3358,15 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp, r = TAILQ_NEXT(r, entries); else if ((r->flagset & th->th_flags) != r->flags) r = TAILQ_NEXT(r, entries); - else if (r->ruid.op && (xuid != -1 || (xuid = - pf_user_lookup(&ruid, &euid, direction, af, IPPROTO_TCP, pd), - 1)) && !pf_match_uid(r->ruid.op, r->ruid.uid[0], - r->ruid.uid[1], ruid)) + else if (r->uid.op && (lookup != -1 || (lookup = + pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP, pd), + 1)) && !pf_match_uid(r->uid.op, r->uid.uid[0], + r->uid.uid[1], uid)) r = TAILQ_NEXT(r, entries); - else if (r->euid.op && (xuid != -1 || (xuid = - pf_user_lookup(&ruid, &euid, direction, af, IPPROTO_TCP, pd), - 1)) && !pf_match_uid(r->euid.op, r->euid.uid[0], - r->euid.uid[1], euid)) + else if (r->gid.op && (lookup != -1 || (lookup = + pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP, pd), + 1)) && !pf_match_gid(r->gid.op, r->gid.gid[0], + r->gid.gid[1], gid)) r = TAILQ_NEXT(r, entries); else { *rm = r; @@ -3500,8 +3510,9 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp, struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr; struct udphdr *uh = pd->hdr.udp; u_int16_t bport, nport = 0, af = pd->af; - int xuid = -1; - uid_t ruid, euid; + int lookup = -1; + uid_t uid; + gid_t gid; struct pf_rule *r; u_short reason; int rewrite = 0, error; @@ -3595,15 +3606,15 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp, r = r->skip[PF_SKIP_DST_PORT]; else if (r->rule_flag & PFRULE_FRAGMENT) r = TAILQ_NEXT(r, entries); - else if (r->ruid.op && (xuid != -1 || (xuid = - pf_user_lookup(&ruid, &euid, direction, af, IPPROTO_UDP, pd), - 1)) && !pf_match_uid(r->ruid.op, r->ruid.uid[0], - r->ruid.uid[1], ruid)) + else if (r->uid.op && (lookup != -1 || (lookup = + pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP, pd), + 1)) && !pf_match_uid(r->uid.op, r->uid.uid[0], + r->uid.uid[1], uid)) r = TAILQ_NEXT(r, entries); - else if (r->euid.op && (xuid != -1 || (xuid = - pf_user_lookup(&ruid, &euid, direction, af, IPPROTO_UDP, pd), - 1)) && !pf_match_uid(r->euid.op, r->euid.uid[0], - r->euid.uid[1], euid)) + else if (r->gid.op && (lookup != -1 || (lookup = + pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP, pd), + 1)) && !pf_match_gid(r->gid.op, r->gid.gid[0], + r->gid.gid[1], gid)) r = TAILQ_NEXT(r, entries); else { *rm = r; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index d6a7726144f..40ed54aefcb 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.71 2002/05/09 21:58:12 jasoni Exp $ */ +/* $OpenBSD: pfvar.h,v 1.72 2002/05/12 00:54:56 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -201,6 +201,11 @@ struct pf_rule_uid { u_int8_t op; }; +struct pf_rule_gid { + uid_t gid[2]; + u_int8_t op; +}; + struct pf_rule_addr { struct pf_addr_wrap addr; struct pf_addr mask; @@ -242,8 +247,8 @@ struct pf_rule { u_int16_t return_icmp; u_int16_t max_mss; - struct pf_rule_uid ruid; - struct pf_rule_uid euid; + struct pf_rule_uid uid; + struct pf_rule_gid gid; u_int8_t action; u_int8_t direction; @@ -626,7 +631,8 @@ int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *, struct pf_addr *, int); int pf_match(u_int8_t, u_int16_t, u_int16_t, u_int16_t); int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t); -int pf_match_uid(u_int8_t, u_int16_t, u_int16_t, u_int16_t); +int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t); +int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t); void pf_normalize_init(void); int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *); |