match.c revision 1.6
1/* 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 */ 15 16#include "includes.h" 17RCSID("$Id: match.c,v 1.6 2000/04/14 10:30:31 markus Exp $"); 18 19#include "ssh.h" 20 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 */ 25 26int 27match_pattern(const char *s, const char *pattern) 28{ 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 != '*') { 44 /* 45 * Look instances of the next character in 46 * pattern, and try to match starting from 47 * those. 48 */ 49 for (; *s; s++) 50 if (*s == *pattern && 51 match_pattern(s + 1, pattern + 1)) 52 return 1; 53 /* Failed. */ 54 return 0; 55 } 56 /* 57 * Move ahead one character at a time and try to 58 * match at each position. 59 */ 60 for (; *s; s++) 61 if (match_pattern(s, pattern)) 62 return 1; 63 /* Failed. */ 64 return 0; 65 } 66 /* 67 * There must be at least one more character in the string. 68 * If we are at the end, fail. 69 */ 70 if (!*s) 71 return 0; 72 73 /* Check if the next character of the string is acceptable. */ 74 if (*pattern != '?' && *pattern != *s) 75 return 0; 76 77 /* Move to the next character, both in string and in pattern. */ 78 s++; 79 pattern++; 80 } 81 /* NOTREACHED */ 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 91int 92match_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; 141} 142