1Upstream-Status: Backport
2
3See https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=17847
4
5diff -ruN tcp_wrappers_7.6.orig/hosts_access.5 tcp_wrappers_7.6/hosts_access.5
6--- tcp_wrappers_7.6.orig/hosts_access.5	2004-04-10 18:54:33.000000000 +0200
7+++ tcp_wrappers_7.6/hosts_access.5	2004-04-10 18:54:27.000000000 +0200
8@@ -89,6 +89,10 @@
9 bitwise AND of the address and the `mask\'. For example, the net/mask
10 pattern `131.155.72.0/255.255.254.0\' matches every address in the
11 range `131.155.72.0\' through `131.155.73.255\'.
12+.IP \(bu
13+Wildcards `*\' and `?\' can be used to match hostnames or IP addresses.  This
14+method of matching cannot be used in conjunction with `net/mask\' matching,
15+hostname matching beginning with `.\' or IP address matching ending with `.\'.
16 .SH WILDCARDS
17 The access control language supports explicit wildcards:
18 .IP ALL
19diff -ruN tcp_wrappers_7.6.orig/hosts_access.c tcp_wrappers_7.6/hosts_access.c
20--- tcp_wrappers_7.6.orig/hosts_access.c	1997-02-12 02:13:23.000000000 +0100
21+++ tcp_wrappers_7.6/hosts_access.c	2004-04-10 18:52:21.000000000 +0200
22@@ -289,6 +289,11 @@
23 {
24     int     n;
25
26+#ifndef DISABLE_WILDCARD_MATCHING
27+    if (strchr(tok, '*') || strchr(tok,'?')) {  /* contains '*' or '?' */
28+        return (match_pattern_ylo(string,tok));
29+    } else
30+#endif
31     if (tok[0] == '.') {			/* suffix */
32 	n = strlen(string) - strlen(tok);
33 	return (n > 0 && STR_EQ(tok, string + n));
34@@ -329,3 +334,71 @@
35     }
36     return ((addr & mask) == net);
37 }
38+
39+#ifndef DISABLE_WILDCARD_MATCHING
40+/* Note: this feature has been adapted in a pretty straightforward way
41+   from Tatu Ylonen's last SSH version under free license by
42+   Pekka Savola <pekkas@netcore.fi>.
43+
44+   Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
45+*/
46+
47+/* Returns true if the given string matches the pattern (which may contain
48+   ? and * as wildcards), and zero if it does not match. */
49+
50+int match_pattern_ylo(const char *s, const char *pattern)
51+{
52+  while (1)
53+    {
54+      /* If at end of pattern, accept if also at end of string. */
55+      if (!*pattern)
56+        return !*s;
57+
58+      /* Process '*'. */
59+      if (*pattern == '*')
60+        {
61+	  /* Skip the asterisk. */
62+	  pattern++;
63+
64+	  /* If at end of pattern, accept immediately. */
65+          if (!*pattern)
66+            return 1;
67+
68+	  /* If next character in pattern is known, optimize. */
69+          if (*pattern != '?' && *pattern != '*')
70+            {
71+	      /* Look instances of the next character in pattern, and try
72+		 to match starting from those. */
73+              for (; *s; s++)
74+                if (*s == *pattern &&
75+                    match_pattern_ylo(s + 1, pattern + 1))
76+                  return 1;
77+	      /* Failed. */
78+              return 0;
79+            }
80+
81+	  /* Move ahead one character at a time and try to match at each
82+	     position. */
83+          for (; *s; s++)
84+            if (match_pattern_ylo(s, pattern))
85+              return 1;
86+	  /* Failed. */
87+          return 0;
88+        }
89+
90+      /* There must be at least one more character in the string.  If we are
91+	 at the end, fail. */
92+      if (!*s)
93+        return 0;
94+
95+      /* Check if the next character of the string is acceptable. */
96+      if (*pattern != '?' && *pattern != *s)
97+	return 0;
98+
99+      /* Move to the next character, both in string and in pattern. */
100+      s++;
101+      pattern++;
102+    }
103+  /*NOTREACHED*/
104+}
105+#endif /* DISABLE_WILDCARD_MATCHING */
106