Subject: allowing unpriv users to bind to priv ports
To: None <tech-kern@netbsd.org>
From: Joe Reed <jnr@po.cwru.edu>
List: tech-kern
Date: 09/25/2002 15:26:51
--------------Boundary-00=_R0E0V6F8GI09TRS3UL8Z
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 8bit
hi all,
i've been working on a utility to allow unprivilaged users to bind to
privilaged ports on a per user/group basis. the rules are similiar to ipf
rules and allow for daemons to be run as unprivilaged users, but still bind
to the proper port (without losing any restriction for any other user), with
a specific protocol. these rules only work for ports less than the reserved
port. and superuser is always allowed to bind, regardless of rules.
the ports that have rules are stored in a linked list, with their rules in a
set of lists as well (allow and deny). i used the linked lists for
simplicity and proof of concept. still lookup time is (worst case) O(p+a)
for allow and O(p+d) for deny case. where p = number of ports that have
rules, a,d= number of allow,deny rules respectively. so if there is no rule
for that user/group on that port, the worst possible search time is O(p+d+a).
which is not too horrible.
i've modified netinet/in_pcb.c and netinet6/in6_pcb.c to check in this
fashion.
i placed the kernel code in sys/net/ because i felt that it was more closely
tied to the network. and the userland code in usr.sbin/sfilter/. if it
should go elsewhere, please let me know.
i have not tied this into the rc scripts yet, because i'm not sure on a few
things:
1) how early the rules should get loaded (i think early, before any net
daemons start, perhaps around the time of ipf)
2) exactly how to tie in the startup.
i've attched a diff of my changes. it's from my own personal cvs repository,
but it only differs from anoncvs's -current in what's listed here. i've
imported this morning's src before creating the diff.
please let me know what you think. i'd like to get this as good as possible
before i send-pr it.
--joe
--------------Boundary-00=_R0E0V6F8GI09TRS3UL8Z
Content-Type: text/x-diff;
charset="us-ascii";
name="log.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="log.diff"
Index: lib/libc/sys/Makefile.inc
===================================================================
RCS file: /cvsroot/NetBSD/current/lib/libc/sys/Makefile.inc,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 Makefile.inc
--- lib/libc/sys/Makefile.inc 2002/09/25 17:15:00 1.1.1.3
+++ lib/libc/sys/Makefile.inc 2002/09/25 18:49:07
@@ -64,7 +64,8 @@
sendto.S setegid.S seteuid.S setgid.S setgroups.S setitimer.S \
setpgid.S setpriority.S setregid.S setreuid.S setrlimit.S \
setsid.S setsockopt.S setuid.S \
- __shmctl13.S shmdt.S shmget.S shutdown.S \
+ __shmctl13.S shmdt.S shmget.S shutdown.S sfilter_insrule.S \
+ sfilter_clrrule.S \
__sigaltstack14.S __sigpending14.S __sigprocmask14.S __sigsuspend14.S \
__sigaction_sigtramp.S socket.S socketpair.S __stat13.S statfs.S \
swapctl.S symlink.S umask.S undelete.S unlink.S \
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/conf/files,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 files
--- sys/conf/files 2002/09/25 17:13:09 1.1.1.3
+++ sys/conf/files 2002/09/25 18:49:37
@@ -1162,6 +1162,8 @@
file net/route.c
file net/rtsock.c
file net/slcompress.c sl | ppp | strip | irip
+file net/sfilter.c
+file net/sfilter_syscalls.c
file net/zlib.c (ppp & ppp_deflate) | ipsec
file netatalk/aarp.c netatalk
file netatalk/at_control.c netatalk
Index: sys/kern/init_main.c
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/kern/init_main.c,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- sys/kern/init_main.c 2002/09/22 16:35:50 1.1.1.2
+++ sys/kern/init_main.c 2002/09/22 22:31:21 1.3
@@ -119,6 +119,9 @@
#include <dev/cons.h>
#include <net/if.h>
+#ifdef SOCKFILTER
+#include <net/sfilter.h>
+#endif
#include <net/raw_cb.h>
const char copyright[] =
@@ -521,6 +524,15 @@
#ifndef PIPE_SOCKETPAIR
/* Initialize pipe structures */
pipe_init();
+#endif
+
+ /*
+ * initialize sockfilter
+ */
+#ifdef SOCKFILTER
+ printf("sfilter initialize . . . ");
+ sfilter_init();
+ printf("done.\n");
#endif
/*
Index: sys/kern/init_sysent.c
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/kern/init_sysent.c,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- sys/kern/init_sysent.c 2002/09/22 16:35:50 1.1.1.2
+++ sys/kern/init_sysent.c 2002/09/22 22:31:21 1.3
@@ -1,4 +1,4 @@
-/* $NetBSD: init_sysent.c,v 1.133 2002/09/04 07:46:25 jdolecek Exp $ */
+/* $NetBSD$ */
/*
* System call switch table.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_sysent.c,v 1.133 2002/09/04 07:46:25 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD$");
#include "opt_ktrace.h"
#include "opt_nfsserver.h"
@@ -468,10 +468,17 @@
{ 0, 0, 0,
sys_nosys }, /* 176 = excluded ntp_adjtime */
#endif
+#if defined(SOCKFILTER)
+ { 3, s(struct sys_sfilter_insrule_args), 0,
+ sys_sfilter_insrule }, /* 177 = sfilter_insrule */
+ { 1, s(struct sys_sfilter_clrrule_args), 0,
+ sys_sfilter_clrrule }, /* 178 = sfilter_clrrule */
+#else
{ 0, 0, 0,
sys_nosys }, /* 177 = unimplemented */
{ 0, 0, 0,
sys_nosys }, /* 178 = unimplemented */
+#endif
{ 0, 0, 0,
sys_nosys }, /* 179 = unimplemented */
{ 0, 0, 0,
Index: sys/kern/syscalls.c
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/kern/syscalls.c,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- sys/kern/syscalls.c 2002/09/22 16:35:52 1.1.1.2
+++ sys/kern/syscalls.c 2002/09/22 22:31:21 1.3
@@ -1,4 +1,4 @@
-/* $NetBSD: syscalls.c,v 1.128 2002/09/04 07:46:25 jdolecek Exp $ */
+/* $NetBSD$ */
/*
* System call names.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.128 2002/09/04 07:46:25 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD$");
#if defined(_KERNEL_OPT)
#include "opt_ktrace.h"
@@ -240,8 +240,13 @@
#else
"#176 (excluded ntp_adjtime)", /* 176 = excluded ntp_adjtime */
#endif
+#if defined(SOCKFILTER)
+ "sfilter_insrule", /* 177 = sfilter_insrule */
+ "sfilter_clrrule", /* 178 = sfilter_clrrule */
+#else
"#177 (unimplemented)", /* 177 = unimplemented */
"#178 (unimplemented)", /* 178 = unimplemented */
+#endif
"#179 (unimplemented)", /* 179 = unimplemented */
"#180 (unimplemented)", /* 180 = unimplemented */
"setgid", /* 181 = setgid */
Index: sys/kern/syscalls.master
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/kern/syscalls.master,v
retrieving revision 1.1.1.2
retrieving revision 1.5
diff -u -r1.1.1.2 -r1.5
--- sys/kern/syscalls.master 2002/09/22 16:35:52 1.1.1.2
+++ sys/kern/syscalls.master 2002/09/22 22:31:21 1.5
@@ -364,8 +364,13 @@
#else
176 EXCL ntp_adjtime
#endif
-177 UNIMPL
-178 UNIMPL
+#if defined(SOCKFILTER)
+177 STD { int sys_sfilter_insrule(uint16_t port, void *rule, int8_t type);}
+178 STD { int sys_sfilter_clrrule(uint16_t port); }
+#else
+177 UNIMPL
+178 UNIMPL
+#endif
179 UNIMPL
180 UNIMPL
Index: sys/net/Makefile
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/net/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- sys/net/Makefile 2002/08/15 16:17:51 1.1.1.1
+++ sys/net/Makefile 2002/08/27 23:47:39 1.2
@@ -9,6 +9,6 @@
if_ppp.h if_pppvar.h if_pppoe.h if_slvar.h if_sppp.h if_stf.h \
if_stripvar.h if_token.h if_tun.h if_types.h if_vlanvar.h \
netisr.h pfil.h pfkeyv2.h ppp-comp.h ppp_defs.h radix.h \
- raw_cb.h route.h slcompress.h slip.h zlib.h
+ raw_cb.h route.h sfilter.h slcompress.h slip.h zlib.h
.include <bsd.kinc.mk>
Index: sys/net/sfilter.c
===================================================================
RCS file: sfilter.c
diff -N sfilter.c
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091aw Wed Sep 25 14:56:29 2002
@@ -0,0 +1,130 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sfilter.c $");
+
+#include <net/sfilter.h>
+
+#include <sys/malloc.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+
+struct rule_list rule_list_head =
+ SLIST_HEAD_INITIALIZER (rule_list_head);
+
+struct rule_list *rlist;
+
+/*
+ * initializes the data structures
+ */
+int
+sfilter_init(void)
+{
+ rlist = &rule_list_head;
+
+ if (rlist == 0)
+ /* XXX should i printf() && return instead??? */
+ panic ("sockfilter: malloc() failed");
+
+ /* initialize the list head */
+ SLIST_INIT((struct rule_list *)rlist);
+
+ return (0);
+}
+
+/*
+ * determine if the user/group is allowed to bind to the port or not
+ */
+int
+sfilter_isallowed(port, p, flags, privmax)
+ uint16_t port;
+ struct proc *p;
+ uint16_t flags;
+ uint16_t privmax;
+{
+ struct rule_list_entry *entry;
+ struct rule_slist_entry *sptr;
+
+ /* first, i deal with the easy cases (port unrestricted, or suser privs*/
+ if (port >= privmax || suser(p->p_ucred,&p->p_acflag) == 0)
+ return (1);
+
+ /* easy part done, now to find the port's entry in our list */
+ SFILTER_FIND_PORT(port,entry);
+
+ if (entry != NULL) {
+ SLIST_FOREACH(sptr,entry->deny,next) {
+ if (SFILTER_PROT_TYPE(sptr->rule.flags) & flags ) { /*protocol*/
+ if (sptr->rule.flags & SFILTER_CHKUID) { /*chk uid*/
+ if (sptr->rule.uid == p->p_ucred->cr_uid) {
+ if (sptr->rule.flags & SFILTER_CHKGID) { /*if both*/
+ if (groupmember(sptr->rule.gid,p->p_ucred))
+ return (0);
+ } else /*only uid*/
+ return (0);
+ }
+ } else if (sptr->rule.flags & SFILTER_CHKGID) {
+ if (groupmember(sptr->rule.gid,p->p_ucred))
+ return (0);
+ }
+ }
+ } /*end deny list loop*/
+
+ SLIST_FOREACH(sptr,entry->allow,next) {
+ if (SFILTER_PROT_TYPE(sptr->rule.flags) & flags ) { /*protocol*/
+ if (sptr->rule.flags & SFILTER_ALLOWALL)
+ return (1);
+ else if (sptr->rule.flags & SFILTER_CHKUID) { /*chk uid*/
+ if (sptr->rule.uid == p->p_ucred->cr_uid) {
+ if (sptr->rule.flags & SFILTER_CHKGID) { /*if both*/
+ if (groupmember(sptr->rule.gid,p->p_ucred))
+ return (1);
+ } else /*only uid*/
+ return (1);
+ }
+ } else if (sptr->rule.flags & SFILTER_CHKGID) {
+ if (groupmember(sptr->rule.gid,p->p_ucred))
+ return (1);
+ }
+ }
+ } /*end allow list loop*/
+ }
+
+ return (0); /*default to deny */
+}
Index: sys/net/sfilter.h
===================================================================
RCS file: sfilter.h
diff -N sfilter.h
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091ax Wed Sep 25 14:56:29 2002
@@ -0,0 +1,212 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * public interfaces to socketfilter. by Joe Reed
+ */
+
+#ifndef _NET_SFILTER_H_
+#define _NET_SFILTER_H_
+
+#include <sys/types.h>
+
+/*
+ * needed both in and out of kernel
+ */
+
+/* flags */
+#define SFILTER_PROT_TCP 0x0001 /* rule applies to tcp/ip */
+#define SFILTER_PROT_UDP 0x0002 /* rule applies to udp */
+#define SFILTER_PROT_ICMP 0x0004 /* rule applies to tcmp */
+#define SFILTER_PROT_ALL (SFILTER_PROT_TCP|SFILTER_PROT_UDP|SFILTER_PROT_ICMP)
+#define SFILTER_PROT_MASK 0x0007
+
+/* bits 0x00f8 not used yet */
+
+#define SFILTER_IPV4 0x0100 /* ip version 4 */
+#define SFILTER_IPV6 0x0200 /* ip version 6 */
+#define SFILTER_IPALL (SFILTER_IPV4 | SFILTER_IPV6)
+
+/* bits 0x0c00 not used yet */
+
+#define SFILTER_CHKUID 0x1000 /* check the user id */
+#define SFILTER_CHKGID 0x2000 /* check the group id */
+#define SFILTER_ALLOWALL 0x4000 /* allow all users and groups */
+#define SFILTER_CHKMASK (SFILTER_CHKUID | SFILTER_CHKGID | SFILTER_ALLOWALL)
+
+
+/* useful macros for flags */
+#define SFILTER_IPVERSION(x) (x & SFILTER_IPALL)
+#define SFILTER_PROT_TYPE(x) (x & SFILTER_PROT_MASK)
+
+/* rule types */
+#define SFILTER_ALLOWRULE 0x10 /* rule allows connections */
+#define SFILTER_DENYRULE 0x20 /* rule deny's connections */
+#define SFILTER_TYPEMASK 0x30
+
+struct sfilter_rule {
+ uid_t uid;
+ gid_t gid;
+ u_int16_t flags;
+};
+
+/*
+ * only needed in-kernel
+ */
+#ifdef _KERNEL
+//XXX #include <netinet/in.h> /* XXX should this go here or on top? */
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+
+/* macros for ipv{4,6} wrapping -- use these */
+ /* XXX
+ * When NOPRIVPORTS becomes a sysctl, delete this,
+ * and use (privports{,6} ? sfilter_isallowed(....) : 1)
+ * !! don't forget to include ip_var.h and ip6_var.h !!
+ */
+#ifdef NOPRIVPORTS
+ #define ISALLOWED_IPV4(port, proc, flags) (1)
+ #define ISALLOWED_IPV6(port, proc, flags) (1)
+
+#else
+ #define ISALLOWED_IPV4(port, proc, flags) \
+ sfilter_isallowed(port,proc,flags,IPPORT_RESERVED)
+
+//XXX #ifdef IPV6PORT_RESERVED /* ip version 6 is included */
+ #define ISALLOWED_IPV6(port, proc, flags) \
+ sfilter_isallowed(port,proc,flags,IPV6PORT_RESERVED)
+//XXX #endif /* IPV6PORT_RESERVED */
+#endif /* NOPRIVPORTS */
+
+/*
+ * macros for rulelist manipulation
+ */
+
+#define SFILTER_RULE_LIST_INIT(x) do { \
+ x = malloc(sizeof(struct rule_slist_entry),M_MBUF,M_WAITOK|M_ZERO); \
+ SLIST_INIT(x); \
+} while(0)
+
+#define SFILTER_INSERT_RULE(list,r) do { \
+ struct rule_slist_entry *n = \
+ malloc (sizeof(struct rule_slist_entry),M_MBUF,M_WAITOK|M_ZERO); \
+ memcpy (&(n->rule), r, sizeof(struct sfilter_rule)); \
+ SLIST_INSERT_HEAD(list,n,next); \
+} while (0)
+
+#define SFILTER_INSERT_PORT(list) SLIST_INSERT_HEAD((struct rule_list *)rlist, \
+ list,next)
+
+ /* params: uint16_t port, SLIST_ENTRY(rule_list_entry) *dat_ptr */
+#define SFILTER_FIND_PORT(port,dat_ptr) do { \
+ struct rule_list_entry *tmp; \
+ dat_ptr = NULL; \
+ SLIST_FOREACH(tmp,rlist,next){ \
+ if (tmp->port == port){ \
+ dat_ptr = tmp; \
+ break; \
+ } \
+ } \
+} while(0)
+
+#define SFILTER_REM_PORT_RULES(rlst) do { \
+ struct rule_slist_entry *r; \
+ while (!SLIST_EMPTY(rlst)) { \
+ r = SLIST_FIRST (rlst); \
+ SLIST_REMOVE_HEAD (rlst,next); \
+ free(r,M_MBUF); \
+ } \
+}while (0)
+
+#define SFILTER_REM_PORT(port_ptr) do { \
+ SFILTER_REM_PORT_RULES (port_ptr->allow); \
+ SFILTER_REM_PORT_RULES (port_ptr->deny); \
+ SLIST_REMOVE(rlist, port_ptr, rule_list_entry, next); \
+ free(port_ptr,M_MBUF); \
+} while (0)
+
+/*
+ * data structures used in the linked lists holding the rule list
+ */
+struct rule_slist_entry {
+ /* node for the allow/deny lists */
+ struct sfilter_rule rule;
+ SLIST_ENTRY(rule_slist_entry) next;
+};
+
+SLIST_HEAD(rule_sublist,rule_slist_entry) _tmp1;
+
+struct rule_list_entry {
+ /* node for each port */
+ uint16_t port;
+ struct rule_sublist *allow,
+ *deny;
+ SLIST_ENTRY(rule_list_entry) next;
+};
+
+SLIST_HEAD(rule_list,rule_list_entry);
+
+extern struct rule_list *rlist; /* list head */
+
+/*
+ * initialize the rulelist
+ */
+int
+sfilter_initalize(void);
+
+/*
+ * check to see if a binding is allowed by the ruleset.
+ */
+int
+sfilter_init(void);
+int
+sfilter_isallowed(uint16_t port, struct proc *p,
+ u_int16_t flags, uint16_t privmax);
+
+/*
+ * only needed out of kernel
+ */
+#else
+
+/* system call prototypes */
+int
+sfilter_insrule(uint16_t port, void *rule, uint16_t type);
+int
+sfilter_clrrule(uint16_t port);
+
+#endif /* _KERNEL */
+
+#endif /* _NET_SFILTER_H_ */
Index: sys/net/sfilter_syscalls.c
===================================================================
RCS file: sfilter_syscalls.c
diff -N sfilter_syscalls.c
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091ay Wed Sep 25 14:56:29 2002
@@ -0,0 +1,153 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * system call interface definitions for sockfilter. by: Joe Reed
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sfilter_syscalls.c $");
+
+#include <net/sfilter.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#include <netinet/in.h>
+
+int
+sys_sfilter_insrule (p, v, rv)
+ struct proc *p;
+ void *v;
+ register_t *rv;
+{
+ struct sys_sfilter_insrule_args /* {
+ syscallarg(uint16_t) port;
+ syscallarg(void *) rule;
+ syscallarg(int8_t) type;
+ } */ *args = v;
+
+ struct rule_list_entry *p_lst;
+ struct sfilter_rule *newrule = SCARG(args,rule);
+ uint16_t port = SCARG(args,port);
+
+ /* if process doesn't have superser privs, return EACCES */
+ if ( suser(p->p_ucred,&p->p_acflag) == EPERM) {
+ *rv = -1;
+ return (EPERM);
+ }
+
+ /* be sure the port's in restricted range */
+ if (port > ( (newrule->flags & SFILTER_PROT_MASK) & SFILTER_IPV4
+ ? IPPORT_RESERVED : IPV6PORT_RESERVED) ) {
+ *rv = -1;
+ return (EDOM); /* XXX i should add an errno to cover this, i think 8 */
+ }
+
+
+ SFILTER_FIND_PORT(port,p_lst);
+
+ /* if the port does not have any rules, we need to add the port */
+ if (p_lst == NULL) {
+ p_lst = malloc (sizeof(struct rule_list_entry),M_MBUF,M_WAITOK|M_ZERO);
+/* XXX error check malloc! */
+ p_lst->port = SCARG(args,port);
+
+ SFILTER_RULE_LIST_INIT(p_lst->deny);
+ SFILTER_RULE_LIST_INIT(p_lst->allow);
+
+ SFILTER_INSERT_PORT(p_lst);
+ }
+
+ switch (SCARG(args,type) & SFILTER_TYPEMASK) {
+ case SFILTER_ALLOWRULE:
+ SFILTER_INSERT_RULE(p_lst->allow,newrule);break;
+ case SFILTER_DENYRULE:
+ SFILTER_INSERT_RULE(p_lst->deny,newrule);break;
+ default:
+ *rv = -1;
+ return (EINVAL);
+ }
+
+ *rv = 0;
+ return (0);
+}
+
+/*
+ * clear the allow/deny lists for the specified port. if the port is 0
+ * remove all the entries
+ */
+int
+sys_sfilter_clrrule(p, v, rv)
+ struct proc *p;
+ void *v;
+ register_t *rv;
+{
+ struct sys_sfilter_clrrule_args /* {
+ syscallarg(uint16_t) port;
+ } */ *args = v;
+
+ struct rule_list_entry *p_lst;
+ uint16_t port = SCARG(args,port);
+
+ /* if process doesn't have superser privs, return EACCES */
+ if ( suser(p->p_ucred,&p->p_acflag) == EPERM) {
+ *rv = -1;
+ return (EPERM);
+ }
+
+ if (port) { /* the port is >0, only remove that port's entries */
+ SFILTER_FIND_PORT(port,p_lst);
+
+ if (p_lst != NULL)
+ SFILTER_REM_PORT(p_lst);
+
+ } else { /* remove rules for all ports */
+ while (!SLIST_EMPTY(rlist)) {
+ p_lst = SLIST_FIRST(rlist);
+ SFILTER_REM_PORT (p_lst);
+ }
+ }
+
+ *rv = 0;
+ return (0);
+}
Index: sys/netinet/in_pcb.c
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/netinet/in_pcb.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- sys/netinet/in_pcb.c 2002/08/15 16:17:54 1.1.1.1
+++ sys/netinet/in_pcb.c 2002/09/08 01:15:04 1.2
@@ -120,6 +120,7 @@
#include <sys/proc.h>
#include <net/if.h>
+#include <net/sfilter.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -265,10 +266,28 @@
if (lport) {
struct inpcb *t;
#ifndef IPNOPRIVPORTS
+ switch (so->so_proto->pr_protocol) {
+ case IPPROTO_TCP:
+ if (! ISALLOWED_IPV4(ntohs(lport),p->p_ucred->cr_uid,
+ p->p_ucred->cr_gid,SFILTER_IPV4|SFILTER_PROT_TCP))
+ return (EACCES);
+ break;
+ case IPPROTO_UDP:
+ if (! ISALLOWED_IPV4(ntohs(lport),p->p_ucred->cr_uid,
+ p->p_ucred->cr_gid,SFILTER_IPV4|SFILTER_PROT_UDP))
+ return (EACCES);
+ break;
+ case IPPROTO_ICMP:
+ if (! ISALLOWED_IPV4(ntohs(lport),p->p_ucred->cr_uid,
+ p->p_ucred->cr_gid,SFILTER_IPV4|SFILTER_PROT_ICMP))
+ return (EACCES);
+ break;
+ default:
/* GROSS */
- if (ntohs(lport) < IPPORT_RESERVED &&
- (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))))
- return (EACCES);
+ if (ntohs(lport) < IPPORT_RESERVED &&
+ (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))))
+ return (EACCES);
+ }
#endif
if (so->so_uid && !IN_MULTICAST(sin->sin_addr.s_addr)) {
t = in_pcblookup_port(table, sin->sin_addr, lport, 1);
Index: sys/netinet6/in6_pcb.c
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/netinet6/in6_pcb.c,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- sys/netinet6/in6_pcb.c 2002/09/22 16:36:01 1.1.1.2
+++ sys/netinet6/in6_pcb.c 2002/09/22 22:31:21 1.3
@@ -84,6 +84,7 @@
#include <net/if.h>
#include <net/route.h>
+#include <net/sfilter.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
@@ -250,10 +251,28 @@
* NOTE: all operating systems use suser() for
* privilege check! do not rewrite it into SS_PRIV.
*/
- priv = (p && !suser(p->p_ucred, &p->p_acflag)) ? 1 : 0;
- /* GROSS */
- if (ntohs(lport) < IPV6PORT_RESERVED && !priv)
- return (EACCES);
+ switch (so->so_proto->pr_protocol) {
+ case IPPROTO_TCP:
+ if (! ISALLOWED_IPV6(ntohs(lport),p->p_ucred->cr_uid,
+ p->p_ucred->cr_gid,SFILTER_IPV6|SFILTER_PROT_TCP))
+ return (EACCES);
+ break;
+ case IPPROTO_UDP:
+ if (! ISALLOWED_IPV6(ntohs(lport),p->p_ucred->cr_uid,
+ p->p_ucred->cr_gid,SFILTER_IPV6|SFILTER_PROT_UDP))
+ return (EACCES);
+ break;
+ case IPPROTO_ICMPV6:
+ if (! ISALLOWED_IPV6(ntohs(lport),p->p_ucred->cr_uid,
+ p->p_ucred->cr_gid,SFILTER_IPV6|SFILTER_PROT_ICMP))
+ return (EACCES);
+ break;
+ default:
+ priv = (p && !suser(p->p_ucred, &p->p_acflag)) ? 1 : 0;
+ /* GROSS */
+ if (ntohs(lport) < IPV6PORT_RESERVED && !priv)
+ return(EACCES);
+ }
#endif
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
Index: sys/sys/syscall.h
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/sys/syscall.h,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- sys/sys/syscall.h 2002/09/22 16:36:05 1.1.1.2
+++ sys/sys/syscall.h 2002/09/22 22:31:21 1.3
@@ -1,4 +1,4 @@
-/* $NetBSD: syscall.h,v 1.126 2002/09/04 07:46:26 jdolecek Exp $ */
+/* $NetBSD$ */
/*
* System call numbers.
@@ -442,6 +442,12 @@
#define SYS_ntp_adjtime 176
/* 176 is excluded ntp_adjtime */
+/* syscall: "sfilter_insrule" ret: "int" args: "uint16_t" "void *" "int8_t" */
+#define SYS_sfilter_insrule 177
+
+/* syscall: "sfilter_clrrule" ret: "int" args: "uint16_t" */
+#define SYS_sfilter_clrrule 178
+
/* syscall: "setgid" ret: "int" args: "gid_t" */
#define SYS_setgid 181
Index: sys/sys/syscallargs.h
===================================================================
RCS file: /cvsroot/NetBSD/current/sys/sys/syscallargs.h,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- sys/sys/syscallargs.h 2002/09/22 16:36:05 1.1.1.2
+++ sys/sys/syscallargs.h 2002/09/22 22:31:21 1.3
@@ -1,4 +1,4 @@
-/* $NetBSD: syscallargs.h,v 1.108 2002/09/04 07:46:27 jdolecek Exp $ */
+/* $NetBSD$ */
/*
* System call argument lists.
@@ -780,6 +780,16 @@
syscallarg(struct timex *) tp;
};
+struct sys_sfilter_insrule_args {
+ syscallarg(uint16_t) port;
+ syscallarg(void *) rule;
+ syscallarg(int8_t) type;
+};
+
+struct sys_sfilter_clrrule_args {
+ syscallarg(uint16_t) port;
+};
+
struct sys_setgid_args {
syscallarg(gid_t) gid;
};
@@ -1433,6 +1443,11 @@
int sys_ntp_gettime(struct proc *, void *, register_t *);
#if defined(NTP) || !defined(_KERNEL)
int sys_ntp_adjtime(struct proc *, void *, register_t *);
+#else
+#endif
+#if defined(SOCKFILTER)
+int sys_sfilter_insrule(struct proc *, void *, register_t *);
+int sys_sfilter_clrrule(struct proc *, void *, register_t *);
#else
#endif
int sys_setgid(struct proc *, void *, register_t *);
Index: usr.sbin/sfilter/Makefile
===================================================================
RCS file: Makefile
diff -N Makefile
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091bh Wed Sep 25 14:57:18 2002
@@ -0,0 +1,9 @@
+# $NetBSD $
+
+PROG= sfilter
+SRCS= sfilter.c
+LINKS= ${BINDIR}/sfilter
+
+MAN= sfilter.conf.5 sfilter.8
+
+.include <bsd.prog.mk>
Index: usr.sbin/sfilter/defaults.h
===================================================================
RCS file: defaults.h
diff -N defaults.h
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091bi Wed Sep 25 14:57:18 2002
@@ -0,0 +1,46 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * default values used in sfilter
+ */
+
+#ifndef NET_SFILTER_DEFAULTS_H
+#define NET_SFILTER_DEFAULTS_H
+
+#define SFILTER_RULELEN 256
+#define SFILTER_CONF_FILE "/etc/sfilter.conf"
+
+#endif /* NET_SFILTER_DEFAULTS_H */
Index: usr.sbin/sfilter/sfilter.8
===================================================================
RCS file: sfilter.8
diff -N sfilter.8
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091bj Wed Sep 25 14:57:18 2002
@@ -0,0 +1,81 @@
+.\" $NetBSD: sfilter.8,v 1.14 2001/04/21 14:42:32 wiz Exp $
+.\"
+.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the NetBSD
+.\" Foundation, Inc. and its contributors.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd September 18, 2002
+.Dt SFILTER 8 i386
+.Os
+.Sh NAME
+.Nm sfilter
+.Nd allows unprivileged users to bind to privileged ports
+.Sh SYNOPSIS
+.Nm ""
+.Op Fl i
+.Op Fl f Ar filename
+.Nm ""
+.Op Fl c Ar port
+.Nm ""
+.Op Fl C
+.Nm ""
+.Op Fl h
+.Ek
+.Sh DESCRIPTION
+SocketFilter interprets rules in a config file, and adds them to the kernel's
+rulelist.
+With no flags,
+.Nm
+clears the current rulelist, then read in and add the rules contained in
+/etc/sfilter.conf.
+.Pp
+Available command-line flags are:
+.Bl -tag -width indent -compat
+.It Fl i
+Insert rules without clearing first.
+.It Fl f Ar filename
+Use filename instead of the default (/etc/sfilter.conf)
+.It Fl c Ar port
+Clear all rules for port.
+.It Fl C
+Clear all rules for all ports.
+.It Fl h
+Prints some help text
+.El
+.Sh FILES
+.Pa /etc/sfilter.conf /usr/sbin/sfilter
+.Sh SEE ALSO
+.Xr sfilter 2
+.Xr sfilter.conf 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Nx 1.6 .
Index: usr.sbin/sfilter/sfilter.c
===================================================================
RCS file: sfilter.c
diff -N sfilter.c
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091bk Wed Sep 25 14:57:18 2002
@@ -0,0 +1,281 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * utility to add/clear rules to sockfilter
+ */
+
+/* usage:
+ sfilter -i [-f filename] | -c port | -C
+ i: insert rules
+ f: use file instead of defaultfile
+ c: clear all rules for port
+ C: clear all rules
+*/
+#define OPTS "if:c:Ch"
+#define SEPS " \t"
+
+#include <net/sfilter.h>
+
+#include <ctype.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "defaults.h"
+#include "sfilter.h"
+
+
+extern char *optarg;
+
+void usage (void);
+int main (int, char **);
+
+void usage ()
+{
+ fprintf(stderr,"usage: %s\n\t%s\n\t%s%s\n\t%s\n\t%s\n\t%s\n",
+ "sfilter [-i] [-f filename] | -c port | -C | -h",
+ "i: insert rules without clearing existing ones",
+ "f: insert rules contained in filename, instead of ",SFILTER_CONF_FILE,
+ "c: clear all rules for port",
+ "C: clear all rules",
+ "h: print this help menu");
+}
+
+int main (argc,argv)
+ int argc;
+ char **argv;
+{
+ int c,cnt,ln;
+ FILE *conf = NULL;
+ struct sfilter_rule newrule;
+ char *line,
+ *rule;
+
+ cnt = ln = 0;
+ while ((c = getopt(argc,argv,OPTS)) != -1) {
+ switch (c)
+ {
+ case 'i':
+ cnt = 1; /* using this as a flag temporarily */
+ break;
+ case 'f':
+ if ( (conf = fopen (optarg,"r")) == NULL) {
+ fprintf(stderr,"cannot open %s: \n",optarg);
+ perror("");
+ CLEANUP(2,conf);
+ }
+ break;
+ case 'c':
+ if (sfilter_clrrule( atoi(optarg) ) == -1) {
+ perror("Cannot clear rules");
+ CLEANUP(2,conf);
+ }
+ printf("Port %d rules cleared successfully\n", atoi(optarg));
+ CLEANUP(0,conf);
+ case 'C':
+ if (sfilter_clrrule( 0 ) == -1) {
+ perror("Cannot clear rules");
+ CLEANUP(2,conf);
+ }
+ printf("All rules cleared successfully\n");
+ CLEANUP(0,conf);
+ default:
+ usage();
+ CLEANUP(1,conf);
+ }
+ } /* end while() getopt loop */
+
+ if (cnt == 0)
+ if (sfilter_clrrule(0) == -1) {
+ perror("Cannot clear rules\n");
+ exit(3);
+ }
+
+ /* make sure rule file's open */
+ if (conf == NULL)
+ if ((conf = fopen(SFILTER_CONF_FILE,"r")) == NULL) {
+ fprintf (stderr,"cannot open %s: ",SFILTER_CONF_FILE);
+ perror("");
+ CLEANUP(2,conf);
+ }
+
+
+ for (line=fgetln(conf,&c),cnt=0,ln=0; !feof(conf); line=fgetln(conf,&c)) {
+ char *p,type;
+ uint16_t port;
+ size_t len = c +(line[c]=='\n'?0:1); /*leave room for \0 if needed*/
+
+ ln++;
+
+ if (*line == '#')
+ continue;
+
+ /* clear new rule struct */
+ memset(&newrule,0,sizeof(struct sfilter_rule));
+ type = '\0';
+
+ /* make working copy of string (with a terminating NULL) */
+ rule = malloc(len);
+ if (rule == NULL) {
+ perror ("malloc failed!");
+ CLEANUP (3,conf);
+ }
+
+ bcopy (line,rule,len);
+ rule[len] = '\0';
+
+ /* get rid of ending whitespace */
+ p = rule + len-1;
+ do {
+ switch (*p)
+ {
+ case '\n':
+ case '\r':
+ *p = '\0';
+ default:
+ break;
+ }
+ p--;
+ } while (!isalpha(*p));
+
+ /*
+ * now parse the rule
+ */
+ /* {allow,deny} */
+ p = strtok(rule,SEPS);
+ if (strncasecmp(p,"allow",5) == 0) /* allow rule */
+ type |= SFILTER_ALLOWRULE;
+ else if (strncasecmp(p,"deny",4) == 0) /* deny rule */
+ type |= SFILTER_DENYRULE;
+ else
+ QUIT(conf,rule,"Invalid rule syntax on line %d\n",ln);
+
+ /* {user,group} id | all */
+ p = strtok(NULL,SEPS);
+ if (strncasecmp(p,"user",4) == 0) {
+ if ( (p = strtok(NULL,SEPS)) != NULL) {
+ struct passwd *pwd = getpwnam(p);
+
+ if (pwd == NULL)
+ QUIT(conf,rule,"Username lookup failed from line %d\n",ln);
+
+ newrule.uid = pwd->pw_uid;
+ newrule.flags |= SFILTER_CHKUID;
+
+ } else
+ QUIT(conf,rule,"Invalid rule syntax on line %d\n",ln);
+
+ } else if (strncasecmp(p,"group",5) == 0) {
+ if ( (p = strtok(NULL,SEPS)) != NULL) {
+ struct group *grp = getgrnam(p);
+
+ if (grp == NULL)
+ QUIT(conf,rule,"Group lookup failed from line %d\n",ln);
+
+ newrule.gid = grp->gr_gid;
+ newrule.flags |= SFILTER_CHKGID;
+
+ } else
+ QUIT(conf,rule,"Invalid rule syntax on line %d\n",ln);
+
+ } else if (strncasecmp(p,"all",3) == 0)
+ newrule.flags |= SFILTER_ALLOWALL;
+
+ else
+ QUIT(conf,rule,"Invalid rule syntax on line %d\n",ln);
+
+ /* on | NULL */
+ p = strtok(NULL,SEPS);
+ if (strncasecmp(p,"on",2) == 0)
+ p = strtok(NULL,SEPS);
+
+ /* port portno */
+ if (strncasecmp(p,"port",4) == 0) {
+ p = strtok(NULL,SEPS);
+
+ if ( (port = (uint16_t) atoi(p)) == 0)
+ QUIT(conf,rule,"Invalid port number on line %d\n",ln);
+ } else
+ QUIT(conf,rule,"Invalid rule syntax on line %d\n",ln);
+
+
+ /* proto {tcp,udp,icmp,all}{,4,6} */
+ p = strtok(NULL,SEPS);
+ if (strncasecmp(p,"proto",5) == 0) {
+ p = strtok(NULL,SEPS);
+ if (strncasecmp(p,"tcp",3) == 0)
+ newrule.flags |= SFILTER_PROT_TCP;
+ else if (strncmp(p,"udp",3) == 0)
+ newrule.flags |= SFILTER_PROT_UDP;
+ else if (strncmp(p,"icmp",4) == 0)
+ newrule.flags |= SFILTER_PROT_ICMP;
+ else if (strncmp(p,"all",3) == 0)
+ newrule.flags |= SFILTER_PROT_ALL;
+ else
+ QUIT(conf,rule,"Invalid protocol type on line %d\n",ln);
+
+ switch (p[strlen(p)-1]) {
+ case '4':
+ newrule.flags |= SFILTER_IPV4;
+ break;
+ case '6':
+ newrule.flags |= SFILTER_IPV6;
+ break;
+ default:
+ newrule.flags |= SFILTER_IPALL;
+ }
+ } else
+ QUIT (conf,rule,"Invalid rule syntax on line %d\n",ln);
+
+ if (sfilter_insrule(port,&newrule,type) == -1)
+ perror("Rule insertion failed\n");
+ else
+ cnt++;
+
+ free (rule);
+ } /* end line loop */
+
+ /* now cleanup */
+ fclose (conf);
+
+ printf ("%d rules successfully added\n",cnt);
+ exit (0);
+}
+
+
Index: usr.sbin/sfilter/sfilter.conf.5
===================================================================
RCS file: sfilter.conf.5
diff -N sfilter.conf.5
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091bl Wed Sep 25 14:57:18 2002
@@ -0,0 +1,71 @@
+.\" $NetBSD: ipnat.5,v 1.8 2002/06/16 14:43:46 wiz Exp $
+.\"
+.TH SFILTER 5
+.SH NAME
+sfilter, sfilter.conf \- Socket Filter file format
+.SH DESCRIPTION
+The format for files accepted by sfilter is described by the following grammar:
+.LP
+.nf
+rule :: = type id on port protocol comment | comment .
+
+type ::= allow | deny .
+id ::= "user" uid | "group" gid
+on ::= "on" | NULL
+port ::= "port" portnum
+protocol ::= "proto" prototype
+comment ::= "#"{PRINTABLE_ASCII} | NULL
+
+uid ::= letter {letters}
+gid ::= letter {letters}
+portnumber ::= number { numbers } .
+prototype ::= "tcp"{,4,6} | "udp"{,4,6} | "icmp"{,4,6} | "all"{,4,6} .
+
+numbers ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .
+letters ::= 'A' - 'Z' | 'a' - 'z' .
+
+.fi
+.PP
+In addition to this, # is used to mark the start of a comment and may
+appear at the end of a line with a NAT rule (as described above) or on its
+own lines. Blank lines are ignored.
+.PP
+All deny rules are processed before any allow rules.
+.PP
+Currently, the uid and gid fields must map to valid usernames and groups,
+respectively. They may NOT be the actual uid/gid's.
+.SH Allowing users / groups
+.PP
+To allow a user (websrv) to bind to a privilaged port (80), the rule
+could be written as:
+.LP
+.nf
+allow user websrv on port 80 proto tcp
+.fi
+.LP
+or to specifically set ipv4 and ipv6 as
+.LP
+.nf
+allow user websrv on port 80 proto tcp4
+allow user websrv on port 80 proto tcp6
+.fi
+.PP
+To allow a group to bind to port 21, but only on ipv6 the rule could be
+written as follows:
+.LP
+.nf
+allow group ftp on 21 proto all6
+.fi
+.LP
+The deny rules follow the same syntax, just beginning with a deny,
+instead of an allow.
+.LP
+.SH FILES
+/usr/sbin/sfilter
+.br
+/etc/sfilter.conf
+.br
+.SH SEE ALSO
+sfilter (2)
+.br
+sfilter (8)
Index: usr.sbin/sfilter/sfilter.h
===================================================================
RCS file: sfilter.h
diff -N sfilter.h
--- /dev/null Wed Sep 25 14:55:07 2002
+++ /tmp/cvs18091bm Wed Sep 25 14:57:18 2002
@@ -0,0 +1,54 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * default values used in sfilter
+ */
+
+#ifndef SFILTER_H
+#define SFILTER_H
+
+#define CLEANUP(x,f) do{ \
+ if (f != NULL) fclose (f); \
+ exit (x); \
+} while(0)
+
+#define QUIT(f,r,s,c) do { \
+ free (r); \
+ printf(s,c); \
+ CLEANUP(3,f); \
+} while(0)
+
+#endif /* SFILTER_H */
--------------Boundary-00=_R0E0V6F8GI09TRS3UL8Z--