Annotation of src/usr.bin/ssh/match.c, Revision 1.5
1.1 deraadt 1: /*
1.3 deraadt 2: *
3: * match.c
4: *
5: * Author: Tatu Ylonen <ylo@cs.hut.fi>
6: *
7: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: * All rights reserved
9: *
10: * Created: Thu Jun 22 01:17:50 1995 ylo
11: *
12: * Simple pattern matching, with '*' and '?' as wildcards.
13: *
14: */
1.1 deraadt 15:
16: #include "includes.h"
1.5 ! markus 17: RCSID("$Id: match.c,v 1.2 2000/02/07 19:12:54 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:
26: int
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
! 87: * indicate negation). Returns true if there is a positive match; zero
! 88: * otherwise.
! 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)
! 130: return 0; /* Fail */
! 131: else
! 132: got_positive = 1;
! 133: }
! 134: }
! 135:
! 136: /*
! 137: * Return success if got a positive match. If there was a negative
! 138: * match, we have already returned zero and never get here.
! 139: */
! 140: return got_positive;
1.1 deraadt 141: }