| See https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=17847 |
| (Though the original code needs to be patched to be case-insensitive.) |
| |
| --- a/hosts_access.5 |
| +++ b/hosts_access.5 |
| @@ -89,6 +89,10 @@ An expression of the form `n.n.n.n/m.m.m |
| bitwise AND of the address and the `mask\'. For example, the net/mask |
| pattern `131.155.72.0/255.255.254.0\' matches every address in the |
| range `131.155.72.0\' through `131.155.73.255\'. |
| +.IP \(bu |
| +Wildcards `*\' and `?\' can be used to match hostnames or IP addresses. This |
| +method of matching cannot be used in conjunction with `net/mask\' matching, |
| +hostname matching beginning with `.\' or IP address matching ending with `.\'. |
| .SH WILDCARDS |
| The access control language supports explicit wildcards: |
| .IP ALL |
| --- a/hosts_access.c |
| +++ b/hosts_access.c |
| @@ -82,6 +82,7 @@ static int client_match(); |
| static int host_match(); |
| static int string_match(); |
| static int masked_match(); |
| +static int match_pattern_ylo(); |
| |
| /* Size of logical line buffer. */ |
| |
| @@ -289,6 +290,11 @@ char *string; |
| { |
| int n; |
| |
| +#ifndef DISABLE_WILDCARD_MATCHING |
| + if (strchr(tok, '*') || strchr(tok,'?')) { /* contains '*' or '?' */ |
| + return (match_pattern_ylo(string,tok)); |
| + } else |
| +#endif |
| if (tok[0] == '.') { /* suffix */ |
| n = strlen(string) - strlen(tok); |
| return (n > 0 && STR_EQ(tok, string + n)); |
| @@ -329,3 +335,78 @@ char *string; |
| } |
| return ((addr & mask) == net); |
| } |
| + |
| +#ifndef DISABLE_WILDCARD_MATCHING |
| +/* Note: this feature has been adapted in a pretty straightforward way |
| + from Tatu Ylonen's last SSH version under free license by |
| + Pekka Savola <pekkas@netcore.fi>. |
| + |
| + Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
| +*/ |
| + |
| +/* Returns true if the given string matches the pattern (which may contain |
| + ? and * as wildcards), and zero if it does not match. */ |
| + |
| +static int match_pattern_ylo(const char *s, const char *pattern) |
| +{ |
| + char src; |
| + char pat; |
| + while (1) |
| + { |
| + /* If at end of pattern, accept if also at end of string. */ |
| + if (!*pattern) |
| + return !*s; |
| + |
| + /* Process '*'. */ |
| + if (*pattern == '*') |
| + { |
| + /* Skip the asterisk. */ |
| + pattern++; |
| + |
| + /* If at end of pattern, accept immediately. */ |
| + if (!*pattern) |
| + return 1; |
| + |
| + /* If next character in pattern is known, optimize. */ |
| + if (*pattern != '?' && *pattern != '*') |
| + { |
| + /* Look instances of the next character in pattern, and try |
| + to match starting from those. */ |
| + pat = *pattern; |
| + for (; *s; s++) { |
| + src = *s; |
| + if (toupper(src) == toupper(pat) && |
| + match_pattern_ylo(s + 1, pattern + 1)) |
| + return 1; |
| + } |
| + /* Failed. */ |
| + return 0; |
| + } |
| + |
| + /* Move ahead one character at a time and try to match at each |
| + position. */ |
| + for (; *s; s++) |
| + if (match_pattern_ylo(s, pattern)) |
| + return 1; |
| + /* Failed. */ |
| + return 0; |
| + } |
| + |
| + /* There must be at least one more character in the string. If we are |
| + at the end, fail. */ |
| + if (!*s) |
| + return 0; |
| + |
| + /* Check if the next character of the string is acceptable. */ |
| + pat = *pattern; |
| + src = *s; |
| + if (*pattern != '?' && toupper(pat) != toupper(src)) |
| + return 0; |
| + |
| + /* Move to the next character, both in string and in pattern. */ |
| + s++; |
| + pattern++; |
| + } |
| + /*NOTREACHED*/ |
| +} |
| +#endif /* DISABLE_WILDCARD_MATCHING */ |