ports/81615: [maintainer update] security/doorman: Make doormand work on FreeBSD
Lupe Christoph
lupe at lupe-christoph.de
Sun May 29 09:20:11 UTC 2005
>Number: 81615
>Category: ports
>Synopsis: [maintainer update] security/doorman: Make doormand work on FreeBSD
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: maintainer-update
>Submitter-Id: current-users
>Arrival-Date: Sun May 29 09:20:10 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Lupe Christoph
>Release: FreeBSD 4.10-RELEASE i386
>Organization:
>Environment:
System: FreeBSD vmw-freebsd4.lupe-christoph.de 4.10-RELEASE FreeBSD 4.10-RELEASE #0: Tue May 25 22:47:12 GMT 2004 root at perseus.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
>Description:
Fix for PRs 78777 and 81367
This patch makes the daemon part, doormand, work under FreeBSD.
- For FreeBSD 4.x, it needs the libpcap port.
- pcap provides 4 bytes header even with 'no link-layer encapsulation'
- lsof output differs between FreeBSD and Linux
- pcap timeout semantics differ between Linux and FreeBSD
The IPFilter ("netBSD-style 'ipf' firewall") scripts don't work.
- replace ipf_add with ipf_add.atend and ipf_add.before_block
- replace ipf_delete with one that corresponds to these two.
Miscellaneous cleanups:
- only install binaries and "data" files from doorman's Makefile
- install manpages from port Makefile
- supply rc.d script to start and stop doormand
- remove Aaron's name from pkg-descr
- move pkg-message to files and run it through SUB_FILES
- Fix pkg-message to tell user about rc.conf doorman_enable="YES"
- Fix pkg-plist for ipf_... files, don't @dirrm etc/doormand
to avoid warning when the user configured doormand
>How-To-Repeat:
>Fix:
--- doorman-0.8_1.patch begins here ---
diff -ruN doorman/Makefile doorman-0.8_1/Makefile
--- doorman/Makefile Sat May 28 11:34:53 2005
+++ doorman-0.8_1/Makefile Sun May 29 10:43:11 2005
@@ -7,6 +7,7 @@
PORTNAME= doorman
PORTVERSION= 0.8
+PORTREVISION= 1
CATEGORIES= security
MASTER_SITES= ${MASTER_SITE_SOURCEFORGE}
MASTER_SITE_SUBDIR= doorman
@@ -18,13 +19,14 @@
BUILD_DEPENDS= lsof:${PORTSDIR}/sysutils/lsof
RUN_DEPENDS= ${BUILD_DEPENDS}
-IGNORE= does not work correctly, issues with the pcap library. Patches are under development
-
PKGMESSAGE= ${WRKDIR}/pkg-message
+PATCH_STRIP= -p1
# Default to db4
WITH_BDB_VER?= 4
+.include <bsd.port.pre.mk>
+
.if ${WITH_BDB_VER} == 2
LIB_DEPENDS= db2.0:${PORTSDIR}/databases/db2
.elif ${WITH_BDB_VER} == 3
@@ -39,11 +41,22 @@
.error WITH_BDB_VER must be one between 2, 3, 4, 41 and 42
.endif
+# doormand does not work with the FreeBSD 4.x version of libpcap.
+# Require the ports version.
+.if ${OSVERSION} < 500000
+BUILD_DEPENDS+= ${LOCALBASE}/lib/libpcap.a:${PORTSDIR}/net/libpcap
+.endif
+
+INSTALL_TARGET= installdirs install-exec install-data
+
MAN1= knock.1
MAN5= knockcf.5 doormand.cf.5 guestlist.5
MAN8= doormand.8
GNU_CONFIGURE= yes
+SUB_FILES= pkg-message doorman.sh
+SUB_LIST= RC_SUBR=${RC_SUBR}
+USE_RC_SUBR= YES
pre-everything::
@${ECHO_MSG}
@@ -55,10 +68,21 @@
@${ECHO_MSG} " CURRENTLY BUILDING WITH db${WITH_BDB_VER} "
@${ECHO_MSG}
-pre-install:
- @${SED} 's#%%PREFIX%%#${PREFIX}#' ${MASTERDIR}/pkg-message >${PKGMESSAGE}
-
post-install:
+ ${INSTALL_SCRIPT} ${WRKDIR}/doorman.sh ${PREFIX}/etc/rc.d/doorman.sh
+ ${RM} -f ${PREFIX}/etc/doormand/ipf_add
+ ${INSTALL_SCRIPT} files/ipf_add.atend ${PREFIX}/etc/doormand/ipf_add.atend
+ ${INSTALL_SCRIPT} files/ipf_add.before_block ${PREFIX}/etc/doormand/ipf_add.before_block
+ ${INSTALL_SCRIPT} files/ipf_delete ${PREFIX}/etc/doormand/ipf_delete
+ @for man in ${MAN1}; do \
+ ${INSTALL_MAN} -C ${WRKSRC}/$$man ${PREFIX}/man/man1; \
+ done
+ @for man in ${MAN5}; do \
+ ${INSTALL_MAN} -C ${WRKSRC}/$$man ${PREFIX}/man/man5; \
+ done
+ @for man in ${MAN8}; do \
+ ${INSTALL_MAN} -C ${WRKSRC}/$$man ${PREFIX}/man/man8; \
+ done
@${CAT} ${PKGMESSAGE}
-.include <bsd.port.mk>
+.include <bsd.port.post.mk>
diff -ruN doorman/files/doorman.sh.in doorman-0.8_1/files/doorman.sh.in
--- doorman/files/doorman.sh.in Thu Jan 1 01:00:00 1970
+++ doorman-0.8_1/files/doorman.sh.in Sun May 29 09:45:49 2005
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+
+# PROVIDE: doorman
+# REQUIRE: LOGIN
+# KEYWORD: FreeBSD
+
+#
+# Add the following lines to /etc/rc.conf to enable doorman:
+# doorman_enable (bool): Set to "NO" by default.
+# Set it to "YES" to enable doorman
+# doorman_config (path): Set to "%%PREFIX%%/etc/doormand/doormand.cf" by default.
+#
+
+. %%RC_SUBR%%
+
+name="doorman"
+rcvar=`set_rcvar`
+
+[ -z "$doorman_enable" ] && doorman_enable="NO"
+[ -z "$doorman_config" ] && doorman_config="%%PREFIX%%/etc/doormand/doormand.cf"
+
+[ -f "$doorman_config" ] || (echo "$doorman_config" does not exist.; exit)
+
+command=%%PREFIX%%/sbin/doormand
+pidfile=/var/run/doormand.pid
+command_args="-p $pidfile -f $doorman_config"
+
+load_rc_config $name
+run_rc_command "$1"
diff -ruN doorman/files/ipf_add.atend doorman-0.8_1/files/ipf_add.atend
--- doorman/files/ipf_add.atend Thu Jan 1 01:00:00 1970
+++ doorman-0.8_1/files/ipf_add.atend Sun May 29 09:24:26 2005
@@ -0,0 +1,73 @@
+#!/bin/sh
+#
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#
+# WARNING!
+#
+# This script has not been tested. The author does not run this kind
+# of firewall rules and is too lazy to build a firewall that does
+# just for testing.
+#
+# If you use this script and either find it *does* work (surprise!)
+# or have modifications that make it work, please send mail to
+# tke FreeBSD port maintainer. (See port Makefile).
+#
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+# *********************************************************************
+# This script is used with IPFilter if the ruleset (/etc/ipf.rules)
+# does not contain explicit drop rules that mask a rule added at the end.
+#
+# The script will add it's rules at the end.
+#
+# Note that it does not use locking, so concurrent accesses may
+# interfere with each other.
+# *********************************************************************
+#
+# file "ipf_add.atend"
+# IPFilter add script, called by "doormand".
+# This add "pass in quick" rules to the firewall.
+#
+# Called with five arguments:
+#
+# $1 : name of the interface (e.g. ne0)
+# $2 : source IP; i.e. dotted-decimal address of the 'knock' client
+# $3 : source port; when this script is called for the first time
+# for a connection (man 8 doormand), this argument will be set
+# to a single "0" (0x30) character. This means that the source
+# port is not yet known, and a broad rule allowing any source
+# port is required.
+# $4 : destination IP; that is, the IP address of the interface
+# in argument 1.
+# $5 : The port number of the requested service (e.g. 22 for ssh, etc.)
+#
+
+# This script expects the IPFilter ruleset to have two rules like this:
+inblock="block in log quick on $1 from any to any"
+outblock="block out log quick on $1 from any to any"
+# The new rules will be inserted just before these blocking rules.
+
+if [ $3 = 0 ]; then
+ inrule="pass in quick on $1 proto TCP from $2 to $4 port = $5"
+ outrule="pass out quick on $1 proto TCP from $4 port = $5 to $2"
+else
+ inrule="pass in quick on $1 proto TCP from $2 port = $3 to $4 port = $5"
+ outrule="pass out quick on $1 proto TCP from $4 port = $5 to $2 port = $3"
+fi
+
+#
+# acquire lock (not implemented)
+#
+
+# Insert new rules.
+ret=`(echo $inrule; echo $outrule) | /sbin/ipf -f - 2>&1`
+
+#
+# release lock (not implemented)
+#
+
+if [ -z "$ret" ]; then
+ echo 0
+else
+ echo -1 3 $ret
+fi
diff -ruN doorman/files/ipf_add.before_block doorman-0.8_1/files/ipf_add.before_block
--- doorman/files/ipf_add.before_block Thu Jan 1 01:00:00 1970
+++ doorman-0.8_1/files/ipf_add.before_block Sun May 29 09:19:46 2005
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# *********************************************************************
+# This script is used with IPFilter if the ruleset (/etc/ipf.rules)
+# contains an explicit drop rule that masks a rule added at the end.
+# It expects block rules for both input and output filters. This
+# works e.g. with rule sets generated by fwbuilder.
+#
+# The script will insert it's rule before the drop rule. The drop rules
+# are expected to look like the $inblock and $outblock variables
+# defined below.
+#
+# Note that it does not use locking, so concurrent accesses may
+# interfere with each other.
+# *********************************************************************
+#
+# file "ipf_add.before_block"
+# IPFilter add script, called by "doormand".
+# This add two "pass in quick" rules to the firewall.
+#
+# Called with five arguments:
+#
+# $1 : name of the interface (e.g. ne0)
+# $2 : source IP; i.e. dotted-decimal address of the 'knock' client
+# $3 : source port; when this script is called for the first time
+# for a connection (man 8 doormand), this argument will be set
+# to a single "0" (0x30) character. This means that the source
+# port is not yet known, and a broad rule allowing any source
+# port is required.
+# $4 : destination IP; that is, the IP address of the interface
+# in argument 1.
+# $5 : The port number of the requested service (e.g. 22 for ssh, etc.)
+#
+
+# This script expects the IPFilter ruleset to have two rules like this:
+inblock="block in log quick on $1 from any to any"
+outblock="block out log quick on $1 from any to any"
+# The new rules will be inserted just before these blocking rules.
+
+if [ $3 = 0 ]; then
+ inrule="pass in quick on $1 proto TCP from $2 to $4 port = $5"
+ outrule="pass out quick on $1 proto TCP from $4 port = $5 to $2"
+else
+ inrule="pass in quick on $1 proto TCP from $2 port = $3 to $4 port = $5"
+ outrule="pass out quick on $1 proto TCP from $4 port = $5 to $2 port = $3"
+fi
+
+#
+# acquire lock (not implemented)
+#
+
+# Find the rule numbers of the block rules.
+inruleno=`ipfstat -in | sed -n -e "s/@\([0-9]*\) $inblock/\1/p"`
+outruleno=`ipfstat -on | sed -n -e "s/@\([0-9]*\) $outblock/\1/p"`
+
+# Insert new rules.
+ret=`(echo @$inruleno $inrule; echo @$outruleno $outrule) | /sbin/ipf -f - 2>&1`
+
+#
+# release lock (not implemented)
+#
+
+if [ -z "$ret" ]; then
+ echo 0
+else
+ echo -1 3 $ret
+fi
diff -ruN doorman/files/ipf_delete doorman-0.8_1/files/ipf_delete
--- doorman/files/ipf_delete Thu Jan 1 01:00:00 1970
+++ doorman-0.8_1/files/ipf_delete Sun May 29 09:15:23 2005
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# file "ipf_delete"
+# IPFilter firewall-delete script, called by "doormand".
+# This removes the "pass in quick" rules from the firewall
+# that were added by one of the ipf_add scripts.
+#
+# Called with five arguments:
+#
+# $1 : name of the interface (e.g. ne0)
+# $2 : source IP; i.e. dotted-decimal address of the 'knock' client
+# $3 : source port; when this script is called for the first time
+# to delete a broad firewall rule, this argument will be set
+# to a single "0" (0x30) character. This means that the source
+# port was not known, and a broad rule allowing any source
+# port was set.
+# $4 : destination IP; that is, the IP address of the interface
+# in argument 1.
+# $5 : The port number of the requested service (e.g. 22 for ssh, etc.)
+#
+#
+if [ $3 = 0 ]; then
+ inrule="pass in quick on $1 proto TCP from $2 to $4 port = $5"
+ outrule="pass out quick on $1 proto TCP from $4 port = $5 to $2"
+else
+ inrule="pass in quick on $1 proto TCP from $2 port = $3 to $4 port = $5"
+ outrule="pass out quick on $1 proto TCP from $4 port = $5 to $2 port = $3"
+fi
+
+ret=`(echo @$inruleno $inrule; echo @$outruleno $outrule) | /sbin/ipf -r -f - 2>&1`
+
+if [ -z "$ret" ]
+then
+ echo 0
+else
+ echo -1 3 $ret
+fi
+
diff -ruN doorman/files/patch-doormand.c doorman-0.8_1/files/patch-doormand.c
--- doorman/files/patch-doormand.c Thu Jan 1 01:00:00 1970
+++ doorman-0.8_1/files/patch-doormand.c Sun May 29 09:08:25 2005
@@ -0,0 +1,165 @@
+--- doorman-0.8.orig/doormand.c Thu Jul 29 21:24:02 2004
++++ doorman-0.8/doormand.c Sun May 29 09:05:31 2005
+@@ -397,7 +397,11 @@
+ int datalink_header_lengths[] = {
+ // hdr len code data link type
+ // ------- --- ---------------------------
++#ifdef __FreeBSD__
++ 4, // 0 no link-layer encapsulation
++#else
+ 0, // 0 no link-layer encapsulation
++#endif
+ 14, // 1 Ethernet (10Mb)
+ -1, // 2 Experimental Ethernet (3Mb)
+ -1, // 3 Amateur Radio AX.25
+@@ -557,6 +561,14 @@
+ // more readable.
+ //
+
++/*
++// lsof on FreeBSD produces one more field.
++// This should be rewritten to use a regular expression, anyway.
++//
++// And who said using C++ style comments in C was good for portability?!?
++*/
++
++#ifdef __FreeBSD__
+ #define LSOF()\
+ sprintf (cmd, "lsof -Pn -iTCP@%s:%s", interface_ip_str, dport_string) ;\
+ \
+@@ -578,6 +590,7 @@
+ if ((p1 = token (&p2, " ")) == NULL) continue ;\
+ if ((p1 = token (&p2, " ")) == NULL) continue ;\
+ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
+ if ((p1 = token (&p2, " :")) == NULL) continue ;\
+ local_ip = inet_addr(p1) ;\
+ if ((p1 = token (&p2, "-")) == NULL) continue ;\
+@@ -602,7 +615,53 @@
+ }\
+ }\
+ pclose(f) ;
+-
++#else
++#define LSOF()\
++sprintf (cmd, "lsof -Pn -iTCP@%s:%s", interface_ip_str, dport_string) ;\
++\
++f = popen (cmd, "r") ;\
++if (f == NULL) {\
++ croak (errno, "Can't execute '%s'; exiting.", cmd) ;\
++}\
++\
++fgets(buffer, 254, f) ; /* throw away the first line. */ \
++while (fgets(buffer, 254, f)) {\
++ p2 = buffer ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ dname = p1 ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ pid = p1 ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ uname = p1 ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ if ((p1 = token (&p2, " :")) == NULL) continue ;\
++ local_ip = inet_addr(p1) ;\
++ if ((p1 = token (&p2, "-")) == NULL) continue ;\
++ local_port = atoi(p1) ;\
++ if ((p1 = token (&p2, "->:")) == NULL) continue ;\
++ aptr = p1 ;\
++ remote_ip = inet_addr(p1) ;\
++ if ((p1 = token (&p2, " ")) == NULL) continue ;\
++ pptr = p1 ;\
++ remote_port = atoi(p1) ;\
++ if ((p1 = token (&p2, " ()")) == NULL) continue ;\
++ status = p1 ;\
++\
++ if ((saddr == remote_ip) &&\
++ (daddr == local_ip) &&\
++ (sport == remote_port) &&\
++ (dport == local_port) && \
++ (strcmp(status, "ESTABLISHED") == 0))\
++ {\
++ connected = TRUE ;\
++ break ;\
++ }\
++}\
++pclose(f) ;
++#endif
+
+
+
+@@ -647,7 +706,11 @@
+ snprintf (cmd, 254, "tcp and dst port %s and src %s and dst %s",
+ dport_string, src_addr, interface_ip_str) ;
+ DEBUG "open a secondary pcap: '%s'", cmd) ;
++#ifdef __FreeBSD__
++ hdr_len = open_a_pcap (device, 1000, &cap, cmd) ;
++#else
+ hdr_len = open_a_pcap (device, 0, &cap, cmd) ;
++#endif
+
+ // set broad firewall rule
+ sprintf (G_fw_broad_rule, " %s %s 0 %s %s",
+@@ -659,7 +722,22 @@
+
+ for (;;) {
+
++#ifdef __FreeBSD__
++ {
++ int ret = 0;
++ struct pcap_pkthdr * packet_hdr_p;
++
++ while (ret == 0) {
++ ret = pcap_next_ex (cap, &packet_hdr_p, (const u_char **)&p) ;
++ packet_hdr = *packet_hdr_p;
++ if (ret < 0) {
++ p = NULL;
++ }
++ }
++ }
++#else
+ p = (unsigned char*)pcap_next (cap, &packet_hdr) ;
++#endif
+ if (p == NULL) {
+ WARNX "manage_firewall got null from 'pcap_next'. Exiting.") ;
+ exit (1) ;
+@@ -1222,9 +1300,13 @@
+ croak (errno, "Can't get interface address of %s", device) ;
+ }
+
++#ifdef __FreeBSD__
++ hdr_len = open_a_pcap (device, 1000, &G_cap, "udp and port %d and dst %s",
++ port, interface_ip) ;
++#else
+ hdr_len = open_a_pcap (device, 0, &G_cap, "udp and port %d and dst %s",
+ port, interface_ip) ;
+-
++#endif
+ if (G_reconfigure) {
+ G_reconfigure = FALSE ;
+ NOTICE "reconfigured.") ;
+@@ -1252,7 +1334,22 @@
+ char src_addr_buff[16] ;
+
+ errno = 0 ;
++#ifdef __FreeBSD__
++ {
++ int ret = 0;
++ struct pcap_pkthdr * packet_hdr_p;
++
++ while (ret == 0) {
++ ret = pcap_next_ex (G_cap, &packet_hdr_p, (const u_char **)&p) ;
++ packet_hdr = *packet_hdr_p;
++ if (ret < 0) {
++ p = NULL;
++ }
++ }
++ }
++#else
+ p = (unsigned char *)pcap_next (G_cap, &packet_hdr) ;
++#endif
+ if (G_reconfigure) {
+ if (daemonize) err_closelog() ;
+ goto reconfigure ;
diff -ruN doorman/files/pkg-message.in doorman-0.8_1/files/pkg-message.in
--- doorman/files/pkg-message.in Thu Jan 1 01:00:00 1970
+++ doorman-0.8_1/files/pkg-message.in Sun May 29 10:39:44 2005
@@ -0,0 +1,17 @@
+
+******************************************************************************
+
+To configure Doorman, please edit the files guestlist and doormand.cf found in
+%%PREFIX%%/etc/doormand. Documentation can be found using:
+
+ $ man guestlist
+ $ man doormand.cf
+
+or by visiting the Doorman website at http://doorman.sourceforge.net.
+
+The doormand daemon will *not* be started automatically. To allow it
+to start, put this line in /etc/rc.conf:
+
+doorman_enable="YES"
+
+******************************************************************************
diff -ruN doorman/pkg-descr doorman-0.8_1/pkg-descr
--- doorman/pkg-descr Thu Aug 12 19:27:31 2004
+++ doorman-0.8_1/pkg-descr Sun May 29 10:50:27 2005
@@ -4,6 +4,3 @@
WWW: http://doorman.sourceforge.net/
Author: Bruce Ward <bward2 at users.sourceforge.net>
-
-- Aaron Dalton
-aaron at daltons.ca
diff -ruN doorman/pkg-message doorman-0.8_1/pkg-message
--- doorman/pkg-message Thu Aug 12 19:27:31 2004
+++ doorman-0.8_1/pkg-message Thu Jan 1 01:00:00 1970
@@ -1,12 +0,0 @@
-
-******************************************************************************
-
-To configure Doorman, please edit the files guestlist and doormand.cf found in
-%%PREFIX%%/etc/doormand. Documentation can be found using:
-
- $ man guestlist
- $ man doormand.cf
-
-or by visiting the Doorman website at http://doorman.sourceforge.net.
-
-******************************************************************************
diff -ruN doorman/pkg-plist doorman-0.8_1/pkg-plist
--- doorman/pkg-plist Thu Aug 12 19:27:31 2004
+++ doorman-0.8_1/pkg-plist Sun May 29 10:49:06 2005
@@ -3,7 +3,8 @@
etc/doormand/guestlist.EXAMPLE
etc/doormand/ipchains_add
etc/doormand/ipchains_delete
-etc/doormand/ipf_add
+etc/doormand/ipf_add.atend
+etc/doormand/ipf_add.before_block
etc/doormand/ipf_delete
etc/doormand/ipfw_add
etc/doormand/ipfw_delete
@@ -11,5 +12,6 @@
etc/doormand/iptables_delete
etc/doormand/pfctl_add
etc/doormand/pfctl_delete
+etc/rc.d/doorman.sh
sbin/doormand
- at dirrm etc/doormand
+ at unexec rmdir %D/etc/doormand 2>/dev/null || true
--- doorman-0.8_1.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list