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