Date: Sat, 29 May 1999 01:20:44 -0400 (EDT) From: Brian Feldman <green@unixhelp.org> To: hackers@freebsd.org Subject: proposed socket change (IPFW too? :) Message-ID: <Pine.BSF.4.10.9905290052410.77444-100000@janus.syracuse.net>
next in thread | raw e-mail | index | archive | help
I'd like to propose a change in struct socket, which should increase its
functionality. It should first be noted that, along with my IPFW UID/GID
code (which would be nice to have merged into HEAD too, and if I must, I'll
clean up the ugly switch part), I included this change. Implementation time
would be nil, as would testing.
The change itself would be to store a pointer to struct pcred in each
struct socket. The changes are already done, but I'd like to get rid of the
so_uid too (if possible). Following the cred changes, I'd like to make
a sysctl to find out a socket's credentials. After that, a decent identd to
be shipped with FreeBSD (under the FreeBSD license, of course).
How does all of this sound? I'm including the latest IPFW UID/GID patches,
which have the so_cred functionality.
Brian Feldman _ __ ___ ____ ___ ___ ___
green@unixhelp.org _ __ ___ | _ ) __| \
FreeBSD: The Power to Serve! _ __ | _ \ _ \ |) |
http://www.freebsd.org _ |___)___/___/
--- src/sbin/ipfw/ipfw.c.orig Thu Jan 21 20:46:32 1999
+++ src/sbin/ipfw/ipfw.c Wed Apr 21 07:41:03 1999
@@ -30,8 +30,10 @@
#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>
@@ -333,6 +335,24 @@
}
}
+ 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");
@@ -586,6 +606,8 @@
" 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"
@@ -1185,6 +1207,32 @@
}
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;
--- src/sys/sys/socketvar.h.orig Tue Apr 20 23:27:58 1999
+++ src/sys/sys/socketvar.h Tue Apr 20 23:27:15 1999
@@ -109,6 +109,7 @@
/* NB: generation count must not be first; easiest to make it last. */
so_gen_t so_gencnt; /* generation count */
void *so_emuldata; /* private data for emulators */
+ struct pcred *so_cred; /* user credentials */
};
/*
--- uipc_socket.c.orig Fri May 28 17:19:58 1999
+++ uipc_socket.c Sat May 29 01:12:43 1999
@@ -36,13 +36,14 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/proc.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/poll.h>
+#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@@ -124,8 +125,11 @@
TAILQ_INIT(&so->so_incomp);
TAILQ_INIT(&so->so_comp);
so->so_type = type;
- if (p != 0)
- so->so_uid = p->p_ucred->cr_uid;
+ if (p) {
+ so->so_cred = p->p_cred;
+ so->so_cred->p_refcnt++;
+ so->so_uid = so->so_cred->pc_ucred->cr_uid;
+ } else so->so_cred = NULL;
so->so_proto = prp;
error = (*prp->pr_usrreqs->pru_attach)(so, proto, p);
if (error) {
@@ -156,6 +160,10 @@
struct socket *so;
{
so->so_gencnt = ++so_gencnt;
+ if (so->so_cred && --so->so_cred->p_refcnt == 0) {
+ crfree(so->so_cred->pc_ucred);
+ FREE(so->so_cred, M_SUBPROC);
+ }
zfreei(so->so_zone, so);
}
--- uipc_socket2.c.orig Fri May 28 17:19:58 1999
+++ uipc_socket2.c Sat May 29 00:57:56 1999
@@ -214,6 +214,9 @@
so->so_proto = head->so_proto;
so->so_timeo = head->so_timeo;
so->so_uid = head->so_uid;
+ so->so_cred = head->so_cred;
+ if (so->so_cred)
+ so->so_cred->p_refcnt++;
(void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
--- src/sys/netinet/ip_fw.c.orig Tue Apr 20 10:29:59 1999
+++ src/sys/netinet/ip_fw.c Wed Apr 21 00:20:50 1999
@@ -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 */
@@ -608,13 +612,14 @@
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 uid, 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
@@ -634,6 +639,88 @@
} \
} 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) &&
+ P->inp_socket->so_cred->p_ruid != f->fw_uid)
+ continue;
+ if ((f->fw_flg & IP_FW_F_GID) &&
+ !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) &&
+ P->inp_socket->so_cred->p_ruid != f->fw_uid)
+ continue;
+ if ((f->fw_flg & IP_FW_F_GID) &&
+ !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:
@@ -654,7 +741,8 @@
break;
}
- PULLUP_TO(hlen + 14);
+ if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)))
+ PULLUP_TO(hlen + 14);
tcp = (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f))
continue;
@@ -673,12 +761,13 @@
* rule specifies a port, we consider the rule
* a non-match.
*/
- if (f->fw_nports != 0)
+ if (f->fw_nports)
continue;
break;
}
- PULLUP_TO(hlen + 4);
+ if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)))
+ PULLUP_TO(hlen + 4);
udp = (struct udphdr *) ((u_int32_t *)ip + ip->ip_hl);
src_port = ntohs(udp->uh_sport);
dst_port = ntohs(udp->uh_dport);
@@ -1121,6 +1210,8 @@
#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));
--- src/sys/netinet/ip_fw.h.orig Tue Apr 20 09:32:05 1999
+++ src/sys/netinet/ip_fw.h Wed Apr 21 01:02:58 1999
@@ -81,6 +81,8 @@
/* 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 @@
#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
--- src/sys/netinet/udp_var.h.orig Sun Apr 4 22:47:21 1999
+++ src/sys/netinet/udp_var.h Sun Apr 4 22:50:44 1999
@@ -103,6 +103,7 @@
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));
--- src/sys/netinet/udp_usrreq.c.orig Sun Apr 4 22:51:26 1999
+++ src/sys/netinet/udp_usrreq.c Sun Apr 4 22:51:31 1999
@@ -78,7 +78,7 @@
&log_in_vain, 0, "");
static struct inpcbhead udb; /* from udp_var.h */
-static struct inpcbinfo udbinfo;
+struct inpcbinfo udbinfo;
#ifndef UDBHASHSIZE
#define UDBHASHSIZE 16
--- src/sbin/ipfw/ipfw.8.orig Fri Apr 23 22:26:55 1999
+++ src/sbin/ipfw/ipfw.8 Fri Apr 23 22:37:04 1999
@@ -258,6 +258,18 @@
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
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.9905290052410.77444-100000>
