1Upstream-Status: Backport 2 3Path: news.porcupine.org!news.porcupine.org!not-for-mail 4From: Wietse Venema <wietse@((no)(spam)(please))wzv.win.tue.nl> 5Newsgroups: comp.mail.sendmail,comp.security.unix 6Subject: TCP Wrapper Blacklist Extension 7Followup-To: poster 8Date: 8 Sep 1997 18:53:13 -0400 9Organization: Wietse's hangout while on sabattical in the USA 10Lines: 147 11Sender: wietse@spike.porcupine.org 12Message-ID: <5v1vkp$h4f$1@spike.porcupine.org> 13NNTP-Posting-Host: spike.porcupine.org 14Xref: news.porcupine.org comp.mail.sendmail:3541 comp.security.unix:7158 15 16The patch below adds a new host pattern to the TCP Wrapper access 17control language. Instead of a host name or address pattern, you 18can specify an external /file/name with host name or address 19patterns. The feature can be used recursively. 20 21The /file/name extension makes it easy to blacklist bad sites, for 22example, to block unwanted electronic mail when libwrap is linked 23into sendmail. Adding hosts to a simple text file is much easier 24than having to edit a more complex hosts.allow/deny file. 25 26I developed this a year or so ago as a substitute for NIS netgroups. 27At that time, I did not consider it of sufficient interest for 28inclusion in the TCP Wrapper distribution. How times have changed. 29 30The patch is relative to TCP Wrappers version 7.6. The main archive 31site is ftp://ftp.win.tue.nl/pub/security/tcp_wrappers_7.6.tar.gz 32 33Thanks to the Debian LINUX folks for expressing their interest in 34this patch. 35 36 Wietse 37 38 39[diff updated by Md] 40 41diff -ruN tcp_wrappers_7.6.orig/hosts_access.5 tcp_wrappers_7.6/hosts_access.5 42--- tcp_wrappers_7.6.orig/hosts_access.5 2004-04-10 19:28:09.000000000 +0200 43+++ tcp_wrappers_7.6/hosts_access.5 2004-04-10 19:28:01.000000000 +0200 44@@ -97,6 +97,13 @@ 45 `[3ffe:505:2:1::]/64\' matches every address in the range 46 `3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'. 47 .IP \(bu 48+A string that begins with a `/\' character is treated as a file 49+name. A host name or address is matched if it matches any host name 50+or address pattern listed in the named file. The file format is 51+zero or more lines with zero or more host name or address patterns 52+separated by whitespace. A file name pattern can be used anywhere 53+a host name or address pattern can be used. 54+.IP \(bu 55 Wildcards `*\' and `?\' can be used to match hostnames or IP addresses. This 56 method of matching cannot be used in conjunction with `net/mask\' matching, 57 hostname matching beginning with `.\' or IP address matching ending with `.\'. 58diff -ruN tcp_wrappers_7.6.orig/hosts_access.c tcp_wrappers_7.6/hosts_access.c 59--- tcp_wrappers_7.6.orig/hosts_access.c 2004-04-10 19:28:09.000000000 +0200 60+++ tcp_wrappers_7.6/hosts_access.c 2004-04-10 19:27:05.000000000 +0200 61@@ -253,6 +253,26 @@ 62 } 63 } 64 65+/* hostfile_match - look up host patterns from file */ 66+ 67+static int hostfile_match(path, host) 68+char *path; 69+struct hosts_info *host; 70+{ 71+ char tok[BUFSIZ]; 72+ int match = NO; 73+ FILE *fp; 74+ 75+ if ((fp = fopen(path, "r")) != 0) { 76+ while (fscanf(fp, "%s", tok) == 1 && !(match = host_match(tok, host))) 77+ /* void */ ; 78+ fclose(fp); 79+ } else if (errno != ENOENT) { 80+ tcpd_warn("open %s: %m", path); 81+ } 82+ return (match); 83+} 84+ 85 /* host_match - match host name and/or address against pattern */ 86 87 static int host_match(tok, host) 88@@ -280,6 +300,8 @@ 89 tcpd_warn("netgroup support is disabled"); /* not tcpd_jump() */ 90 return (NO); 91 #endif 92+ } else if (tok[0] == '/') { /* /file hack */ 93+ return (hostfile_match(tok, host)); 94 } else if (STR_EQ(tok, "KNOWN")) { /* check address and name */ 95 char *name = eval_hostname(host); 96 return (STR_NE(eval_hostaddr(host), unknown) && HOSTNAME_KNOWN(name)); 97diff -ruN tcp_wrappers_7.6.orig/tcpdchk.c tcp_wrappers_7.6/tcpdchk.c 98--- tcp_wrappers_7.6.orig/tcpdchk.c 2004-04-10 19:28:09.000000000 +0200 99+++ tcp_wrappers_7.6/tcpdchk.c 2004-04-10 19:27:05.000000000 +0200 100@@ -353,6 +353,8 @@ 101 { 102 if (pat[0] == '@') { 103 tcpd_warn("%s: daemon name begins with \"@\"", pat); 104+ } else if (pat[0] == '/') { 105+ tcpd_warn("%s: daemon name begins with \"/\"", pat); 106 } else if (pat[0] == '.') { 107 tcpd_warn("%s: daemon name begins with dot", pat); 108 } else if (pat[strlen(pat) - 1] == '.') { 109@@ -385,6 +387,8 @@ 110 { 111 if (pat[0] == '@') { /* @netgroup */ 112 tcpd_warn("%s: user name begins with \"@\"", pat); 113+ } else if (pat[0] == '/') { 114+ tcpd_warn("%s: user name begins with \"/\"", pat); 115 } else if (pat[0] == '.') { 116 tcpd_warn("%s: user name begins with dot", pat); 117 } else if (pat[strlen(pat) - 1] == '.') { 118@@ -430,8 +434,13 @@ 119 static int check_host(pat) 120 char *pat; 121 { 122+ char buf[BUFSIZ]; 123 char *mask; 124 int addr_count = 1; 125+ FILE *fp; 126+ struct tcpd_context saved_context; 127+ char *cp; 128+ char *wsp = " \t\r\n"; 129 130 if (pat[0] == '@') { /* @netgroup */ 131 #ifdef NO_NETGRENT 132@@ -450,6 +459,21 @@ 133 tcpd_warn("netgroup support disabled"); 134 #endif 135 #endif 136+ } else if (pat[0] == '/') { /* /path/name */ 137+ if ((fp = fopen(pat, "r")) != 0) { 138+ saved_context = tcpd_context; 139+ tcpd_context.file = pat; 140+ tcpd_context.line = 0; 141+ while (fgets(buf, sizeof(buf), fp)) { 142+ tcpd_context.line++; 143+ for (cp = strtok(buf, wsp); cp; cp = strtok((char *) 0, wsp)) 144+ check_host(cp); 145+ } 146+ tcpd_context = saved_context; 147+ fclose(fp); 148+ } else if (errno != ENOENT) { 149+ tcpd_warn("open %s: %m", pat); 150+ } 151 } else if (mask = split_at(pat, '/')) { /* network/netmask */ 152 #ifdef INET6 153 int mask_len; 154