]> andersk Git - openssh.git/blob - match.c
- (djm) Fix rsh path in RPMs. Report from Jason L Tibbitts III
[openssh.git] / match.c
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"
17 RCSID("$Id$");
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
26 int
27 match_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 -1 if negation matches, 1 if there is
88  * a positive match, 0 if there is no match at all.
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 -1;              /* Negative */
131                         else
132                                 got_positive = 1;       /* Positive */
133                 }
134         }
135
136         /*
137          * Return success if got a positive match.  If there was a negative
138          * match, we have already returned -1 and never get here.
139          */
140         return got_positive;
141 }
This page took 0.088945 seconds and 5 git commands to generate.