diff options
-rw-r--r-- | sbin/ipfw/ipfw.8 | 14 | ||||
-rw-r--r-- | sbin/ipfw/ipfw.c | 50 | ||||
-rw-r--r-- | sys/netinet/ip_fw.c | 107 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 10 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 4 | ||||
-rw-r--r-- | sys/netinet/udp_var.h | 3 |
6 files changed, 172 insertions, 16 deletions
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 1d89956..ba3da16 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -1,5 +1,5 @@ .\" -.\" $Id: ipfw.8,v 1.52 1999/05/29 08:12:37 kris Exp $ +.\" $Id: ipfw.8,v 1.53 1999/06/15 12:56:38 ru Exp $ .\" .Dd July 20, 1996 .Dt IPFW 8 @@ -384,6 +384,18 @@ Skip all subsequent rules numbered less than The search continues with the first rule numbered .Ar number or higher. +.It Ar uid user +Match all TCP or UDP packets sent by or received for a +.Ar user . +A +.Ar user +may be matched by name or identification number. +.It Ar gid group +Match all TCP or UDP packets sent by or received for a +.Ar group . +A +.Ar group +may be matched by name or identification number. .El .Pp If a packet matches more than one diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c index 86a4eab..78d5474 100644 --- a/sbin/ipfw/ipfw.c +++ b/sbin/ipfw/ipfw.c @@ -20,7 +20,7 @@ #ifndef lint static const char rcsid[] = - "$Id: ipfw.c,v 1.69 1999/06/04 11:20:59 ru Exp $"; + "$Id: ipfw.c,v 1.70 1999/06/11 09:43:53 ru Exp $"; #endif /* not lint */ @@ -33,8 +33,10 @@ static const char rcsid[] = #include <ctype.h> #include <err.h> #include <errno.h> +#include <grp.h> #include <limits.h> #include <netdb.h> +#include <pwd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -334,6 +336,24 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) } } + if (chain->fw_flg & IP_FW_F_UID) { + struct passwd *pwd = getpwuid(chain->fw_uid); + + if (pwd) + printf(" uid %s", pwd->pw_name); + else + printf(" uid %u", chain->fw_uid); + } + + if (chain->fw_flg & IP_FW_F_GID) { + struct group *grp = getgrgid(chain->fw_gid); + + if (grp) + printf(" gid %s", grp->gr_name); + else + printf(" gid %u", chain->fw_gid); + } + /* Direction */ if ((chain->fw_flg & IP_FW_F_IN) && !(chain->fw_flg & IP_FW_F_OUT)) printf(" in"); @@ -589,6 +609,8 @@ show_usage(const char *fmt, ...) " src: from [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" " dst: to [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" " extras:\n" +" uid {user id}\n" +" gid {group id}\n" " fragment (may not be used with ports or tcpflags)\n" " in\n" " out\n" @@ -1215,6 +1237,32 @@ add(ac,av) } while (ac) { + if (!strncmp(*av,"uid",strlen(*av))) { + struct passwd *pwd; + + rule.fw_flg |= IP_FW_F_UID; + ac--; av++; + if (!ac) + show_usage("``uid'' requires argument"); + + rule.fw_uid = (pwd = getpwnam(*av)) ? pwd->pw_uid + : strtoul(*av, NULL, 0); + ac--; av++; + continue; + } + if (!strncmp(*av,"gid",strlen(*av))) { + struct group *grp; + + rule.fw_flg |= IP_FW_F_GID; + ac--; av++; + if (!ac) + show_usage("``gid'' requires argument"); + + rule.fw_gid = (grp = getgrnam(*av)) ? (gid_t)grp->gr_gid + : strtoul(*av, NULL, 0); + ac--; av++; + continue; + } if (!strncmp(*av,"in",strlen(*av))) { rule.fw_flg |= IP_FW_F_IN; av++; ac--; continue; diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 2375cac..49c7110 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -12,7 +12,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.c,v 1.112 1999/05/24 10:01:15 luigi Exp $ + * $Id: ip_fw.c,v 1.113 1999/06/11 11:27:35 ru Exp $ */ /* @@ -34,18 +34,21 @@ #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/kernel.h> +#include <sys/proc.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> +#include <sys/ucred.h> #include <net/if.h> +#include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> +#include <netinet/in_pcb.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #include <netinet/ip_fw.h> #ifdef DUMMYNET -#include <net/route.h> #include <netinet/ip_dummynet.h> #endif #include <netinet/tcp.h> @@ -53,6 +56,7 @@ #include <netinet/tcp_var.h> #include <netinet/tcpip.h> #include <netinet/udp.h> +#include <netinet/udp_var.h> #include <netinet/if_ether.h> /* XXX ethertype_ip */ @@ -615,13 +619,14 @@ again: if (f->fw_ipopt != f->fw_ipnopt && !ipopts_match(ip, f)) continue; - /* Check protocol; if wildcard, match */ - if (f->fw_prot == IPPROTO_IP) - goto got_match; - - /* If different, don't match */ - if (ip->ip_p != f->fw_prot) - continue; + /* Check protocol; if wildcard, and no [ug]id, match */ + if (f->fw_prot == IPPROTO_IP) { + if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID))) + goto got_match; + } else + /* If different, don't match */ + if (ip->ip_p != f->fw_prot) + continue; /* * here, pip==NULL for bridged pkts -- they include the ethernet @@ -641,6 +646,88 @@ again: } \ } while (0) + /* Protocol specific checks for uid only */ + if (f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)) { + switch (ip->ip_p) { + case IPPROTO_TCP: + { + struct tcphdr *tcp; + struct inpcb *P; + + if (offset == 1) /* cf. RFC 1858 */ + goto bogusfrag; + if (offset != 0) + continue; + + PULLUP_TO(hlen + 14); + tcp =(struct tcphdr *)((u_int32_t *)ip + ip->ip_hl); + + if (oif) + P = in_pcblookup_hash(&tcbinfo, ip->ip_dst, + tcp->th_dport, ip->ip_src, tcp->th_sport, 0); + else + P = in_pcblookup_hash(&tcbinfo, ip->ip_src, + tcp->th_sport, ip->ip_dst, tcp->th_dport, 0); + + if (P && P->inp_socket && P->inp_socket->so_cred) { + if (f->fw_flg & IP_FW_F_UID) { + if (P->inp_socket->so_cred->p_ruid != + f->fw_uid) + continue; + } else if (!groupmember(f->fw_gid, + P->inp_socket->so_cred->pc_ucred)) + continue; + } else continue; + + break; + } + + case IPPROTO_UDP: + { + struct udphdr *udp; + struct inpcb *P; + + if (offset != 0) + continue; + + PULLUP_TO(hlen + 4); + udp =(struct udphdr *)((u_int32_t *)ip + ip->ip_hl); + + if (oif) + P = in_pcblookup_hash(&udbinfo, ip->ip_dst, + udp->uh_dport, ip->ip_src, udp->uh_sport, 1); + else + P = in_pcblookup_hash(&udbinfo, ip->ip_src, + udp->uh_sport, ip->ip_dst, udp->uh_dport, 1); + + if (P && P->inp_socket && P->inp_socket->so_cred) { + if (f->fw_flg & IP_FW_F_UID) { + if (P->inp_socket->so_cred->p_ruid != + f->fw_uid) + continue; + } else if (!groupmember(f->fw_gid, + P->inp_socket->so_cred->pc_ucred)) + continue; + } else continue; + + break; + } + + default: + continue; +/* + * XXX Shouldn't GCC be allowing two bogusfrag labels if they're both inside + * separate blocks? Hmm.... It seems it's got incorrect behavior here. + */ +#if 0 +bogusfrag: + if (fw_verbose) + ipfw_report(NULL, ip, rif, oif); + goto dropit; +#endif + } + } + /* Protocol specific checks */ switch (ip->ip_p) { case IPPROTO_TCP: @@ -1134,6 +1221,8 @@ check_ipfw_struct(struct ip_fw *frwl) #ifdef IPFIREWALL_FORWARD case IP_FW_F_FWD: #endif + case IP_FW_F_UID: + case IP_FW_F_GID: break; default: dprintf(("%s invalid command\n", err_prefix)); diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 3dc3c0e..ba15dbd 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -11,7 +11,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.h,v 1.36 1998/12/14 18:09:13 luigi Exp $ + * $Id: ip_fw.h,v 1.37 1999/04/20 13:32:05 peter Exp $ */ #ifndef _IP_FW_H @@ -81,6 +81,8 @@ struct ip_fw { /* count of 0 means match all ports) */ void *pipe_ptr; /* Pipe ptr in case of dummynet pipe */ void *next_rule_ptr ; /* next rule in case of match */ + uid_t fw_uid; /* uid to match */ + gid_t fw_gid; /* gid to match */ }; #define IP_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f) @@ -144,7 +146,11 @@ struct ip_fw_chain { #define IP_FW_F_ICMPBIT 0x00100000 /* ICMP type bitmap is valid */ -#define IP_FW_F_MASK 0x001FFFFF /* All possible flag bits mask */ +#define IP_FW_F_UID 0x00200000 /* filter by uid */ + +#define IP_FW_F_GID 0x00400000 /* filter by uid */ + +#define IP_FW_F_MASK 0x007FFFFF /* All possible flag bits mask */ /* * For backwards compatibility with rules specifying "via iface" but diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index b0d293c..fac3405 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 - * $Id: udp_usrreq.c,v 1.50 1999/04/28 11:37:51 phk Exp $ + * $Id: udp_usrreq.c,v 1.51 1999/05/03 23:57:32 billf Exp $ */ #include <sys/param.h> @@ -78,7 +78,7 @@ SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW, &log_in_vain, 0, "Log all incoming UDP packets"); static struct inpcbhead udb; /* from udp_var.h */ -static struct inpcbinfo udbinfo; +struct inpcbinfo udbinfo; #ifndef UDBHASHSIZE #define UDBHASHSIZE 16 diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index 2615e9c..4784a35 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 - * $Id: udp_var.h,v 1.16 1998/11/17 10:53:37 dfr Exp $ + * $Id: udp_var.h,v 1.17 1999/02/16 10:49:52 dfr Exp $ */ #ifndef _NETINET_UDP_VAR_H_ @@ -103,6 +103,7 @@ struct udpstat { SYSCTL_DECL(_net_inet_udp); extern struct pr_usrreqs udp_usrreqs; +extern struct inpcbinfo udbinfo; void udp_ctlinput __P((int, struct sockaddr *, void *)); void udp_init __P((void)); |