Annotation of src/usr.bin/ssh/match.c, Revision 1.8
1.1 deraadt 1: /*
1.6 markus 2: *
1.3 deraadt 3: * match.c
1.6 markus 4: *
1.3 deraadt 5: * Author: Tatu Ylonen <ylo@cs.hut.fi>
1.6 markus 6: *
1.3 deraadt 7: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: * All rights reserved
1.6 markus 9: *
1.3 deraadt 10: * Created: Thu Jun 22 01:17:50 1995 ylo
1.6 markus 11: *
1.3 deraadt 12: * Simple pattern matching, with '*' and '?' as wildcards.
1.6 markus 13: *
1.3 deraadt 14: */
1.1 deraadt 15:
16: #include "includes.h"
1.8 ! markus 17: RCSID("$OpenBSD: match.c,v 1.7 2000/06/06 19:32:14 markus Exp $");
1.1 deraadt 18:
19: #include "ssh.h"
20:
1.4 markus 21: /*
22: * Returns true if the given string matches the pattern (which may contain ?
23: * and * as wildcards), and zero if it does not match.
24: */
1.2 markus 25:
1.6 markus 26: int
1.2 markus 27: match_pattern(const char *s, const char *pattern)
1.1 deraadt 28: {
1.2 markus 29: for (;;) {
30: /* If at end of pattern, accept if also at end of string. */
31: if (!*pattern)
32: return !*s;
33:
34: if (*pattern == '*') {
35: /* Skip the asterisk. */
36: pattern++;
37:
38: /* If at end of pattern, accept immediately. */
39: if (!*pattern)
40: return 1;
41:
42: /* If next character in pattern is known, optimize. */
43: if (*pattern != '?' && *pattern != '*') {
1.4 markus 44: /*
45: * Look instances of the next character in
46: * pattern, and try to match starting from
47: * those.
48: */
1.2 markus 49: for (; *s; s++)
50: if (*s == *pattern &&
51: match_pattern(s + 1, pattern + 1))
52: return 1;
53: /* Failed. */
54: return 0;
55: }
1.4 markus 56: /*
57: * Move ahead one character at a time and try to
58: * match at each position.
59: */
1.2 markus 60: for (; *s; s++)
61: if (match_pattern(s, pattern))
62: return 1;
63: /* Failed. */
64: return 0;
65: }
1.4 markus 66: /*
67: * There must be at least one more character in the string.
68: * If we are at the end, fail.
69: */
1.2 markus 70: if (!*s)
71: return 0;
72:
1.4 markus 73: /* Check if the next character of the string is acceptable. */
1.2 markus 74: if (*pattern != '?' && *pattern != *s)
75: return 0;
76:
1.4 markus 77: /* Move to the next character, both in string and in pattern. */
1.2 markus 78: s++;
79: pattern++;
80: }
81: /* NOTREACHED */
1.5 markus 82: }
83:
84: /*
85: * Tries to match the host name (which must be in all lowercase) against the
86: * comma-separated sequence of subpatterns (each possibly preceded by ! to
1.7 markus 87: * indicate negation). Returns -1 if negation matches, 1 if there is
88: * a positive match, 0 if there is no match at all.
1.5 markus 89: */
90:
91: int
92: match_hostname(const char *host, const char *pattern, unsigned int len)
93: {
94: char sub[1024];
95: int negated;
96: int got_positive;
97: unsigned int i, subi;
98:
99: got_positive = 0;
100: for (i = 0; i < len;) {
101: /* Check if the subpattern is negated. */
102: if (pattern[i] == '!') {
103: negated = 1;
104: i++;
105: } else
106: negated = 0;
107:
108: /*
109: * Extract the subpattern up to a comma or end. Convert the
110: * subpattern to lowercase.
111: */
112: for (subi = 0;
113: i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
114: subi++, i++)
115: sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
116: /* If subpattern too long, return failure (no match). */
117: if (subi >= sizeof(sub) - 1)
118: return 0;
119:
120: /* If the subpattern was terminated by a comma, skip the comma. */
121: if (i < len && pattern[i] == ',')
122: i++;
123:
124: /* Null-terminate the subpattern. */
125: sub[subi] = '\0';
126:
127: /* Try to match the subpattern against the host name. */
128: if (match_pattern(host, sub)) {
129: if (negated)
1.7 markus 130: return -1; /* Negative */
1.5 markus 131: else
1.7 markus 132: got_positive = 1; /* Positive */
1.5 markus 133: }
134: }
135:
136: /*
137: * Return success if got a positive match. If there was a negative
1.7 markus 138: * match, we have already returned -1 and never get here.
1.5 markus 139: */
140: return got_positive;
1.1 deraadt 141: }