This is the much-awaited cleaned up version of IPFW [ug]id support.

All relevant changes have been made (including ipfw.8).
This commit is contained in:
Brian Feldman 1999-06-19 18:43:33 +00:00
parent 6ea5bd80fe
commit 7a2aab80b0
6 changed files with 172 additions and 16 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 @@ non_ip: ip = NULL ;
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 @@ non_ip: ip = NULL ;
} \
} 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));

View File

@ -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

View File

@ -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

View File

@ -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));