Date: Sun, 29 May 2005 11:17:31 +0200 (CEST) From: Lupe Christoph <lupe@lupe-christoph.de> To: FreeBSD-gnats-submit@FreeBSD.org Cc: aaron@daltons.ca, bward@nbnet.nb.ca Subject: ports/81615: [maintainer update] security/doorman: Make doormand work on FreeBSD Message-ID: <20050529091731.DED95A87F@vmw-freebsd4.lupe-christoph.de> Resent-Message-ID: <200505290920.j4T9KAm6020358@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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@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@users.sourceforge.net> - -- Aaron Dalton -aaron@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 -@dirrm etc/doormand +@unexec rmdir %D/etc/doormand 2>/dev/null || true --- doorman-0.8_1.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050529091731.DED95A87F>