~ubuntu-branches/ubuntu/precise/libssh/precise

« back to all changes in this revision

Viewing changes to libssh/match.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-06-15 15:48:07 UTC
  • mfrom: (1.1.10 upstream) (4.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20110615154807-3muklcqfftr1vtch
Tags: 0.5.0-2
* debian/patches/0002-Check-for-NULL-pointers-in-string-c.patch:
  Consolidate patch (Should fix previous REJECT)
* Support multiarch spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3
 
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4
 
 *                    All rights reserved
5
 
 * Simple pattern matching, with '*' and '?' as wildcards.
6
 
 *
7
 
 * As far as I am concerned, the code I have written for this software
8
 
 * can be used freely for any purpose.  Any derived versions of this
9
 
 * software must be clearly marked as such, and if the derived work is
10
 
 * incompatible with the protocol description in the RFC file, it must be
11
 
 * called by a name other than "ssh" or "Secure Shell".
12
 
 */
13
 
 
14
 
/*
15
 
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
16
 
 *
17
 
 * Redistribution and use in source and binary forms, with or without
18
 
 * modification, are permitted provided that the following conditions
19
 
 * are met:
20
 
 * 1. Redistributions of source code must retain the above copyright
21
 
 *    notice, this list of conditions and the following disclaimer.
22
 
 * 2. Redistributions in binary form must reproduce the above copyright
23
 
 *    notice, this list of conditions and the following disclaimer in the
24
 
 *    documentation and/or other materials provided with the distribution.
25
 
 *
26
 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27
 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28
 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29
 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30
 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31
 
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35
 
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
 
 */
37
 
 
38
 
#include <ctype.h>
39
 
#include <string.h>
40
 
#include <sys/types.h>
41
 
 
42
 
#include "libssh/priv.h"
43
 
 
44
 
/*
45
 
 * Returns true if the given string matches the pattern (which may contain ?
46
 
 * and * as wildcards), and zero if it does not match.
47
 
 */
48
 
static int match_pattern(const char *s, const char *pattern) {
49
 
  for (;;) {
50
 
    /* If at end of pattern, accept if also at end of string. */
51
 
    if (!*pattern) {
52
 
      return !*s;
53
 
    }
54
 
 
55
 
    if (*pattern == '*') {
56
 
      /* Skip the asterisk. */
57
 
      pattern++;
58
 
 
59
 
      /* If at end of pattern, accept immediately. */
60
 
      if (!*pattern)
61
 
        return 1;
62
 
 
63
 
      /* If next character in pattern is known, optimize. */
64
 
      if (*pattern != '?' && *pattern != '*') {
65
 
        /*
66
 
         * Look instances of the next character in
67
 
         * pattern, and try to match starting from
68
 
         * those.
69
 
         */
70
 
        for (; *s; s++)
71
 
          if (*s == *pattern && match_pattern(s + 1, pattern + 1)) {
72
 
            return 1;
73
 
          }
74
 
        /* Failed. */
75
 
        return 0;
76
 
      }
77
 
      /*
78
 
       * Move ahead one character at a time and try to
79
 
       * match at each position.
80
 
       */
81
 
      for (; *s; s++) {
82
 
        if (match_pattern(s, pattern)) {
83
 
          return 1;
84
 
        }
85
 
      }
86
 
      /* Failed. */
87
 
      return 0;
88
 
    }
89
 
    /*
90
 
     * There must be at least one more character in the string.
91
 
     * If we are at the end, fail.
92
 
     */
93
 
    if (!*s) {
94
 
      return 0;
95
 
    }
96
 
 
97
 
    /* Check if the next character of the string is acceptable. */
98
 
    if (*pattern != '?' && *pattern != *s) {
99
 
      return 0;
100
 
    }
101
 
 
102
 
    /* Move to the next character, both in string and in pattern. */
103
 
    s++;
104
 
    pattern++;
105
 
  }
106
 
 
107
 
  /* NOTREACHED */
108
 
}
109
 
 
110
 
/*
111
 
 * Tries to match the string against the comma-separated sequence of subpatterns
112
 
 * (each possibly preceded by ! to indicate negation).
113
 
 * Returns -1 if negation matches, 1 if there is a positive match, 0 if there is
114
 
 * no match at all.
115
 
 */
116
 
static int match_pattern_list(const char *string, const char *pattern,
117
 
    unsigned int len, int dolower) {
118
 
  char sub[1024];
119
 
  int negated;
120
 
  int got_positive;
121
 
  unsigned int i, subi;
122
 
 
123
 
  got_positive = 0;
124
 
  for (i = 0; i < len;) {
125
 
    /* Check if the subpattern is negated. */
126
 
    if (pattern[i] == '!') {
127
 
      negated = 1;
128
 
      i++;
129
 
    } else {
130
 
      negated = 0;
131
 
    }
132
 
 
133
 
    /*
134
 
     * Extract the subpattern up to a comma or end.  Convert the
135
 
     * subpattern to lowercase.
136
 
     */
137
 
    for (subi = 0;
138
 
        i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
139
 
        subi++, i++) {
140
 
      sub[subi] = dolower && isupper(pattern[i]) ?
141
 
        (char)tolower(pattern[i]) : pattern[i];
142
 
    }
143
 
 
144
 
    /* If subpattern too long, return failure (no match). */
145
 
    if (subi >= sizeof(sub) - 1) {
146
 
      return 0;
147
 
    }
148
 
 
149
 
    /* If the subpattern was terminated by a comma, skip the comma. */
150
 
    if (i < len && pattern[i] == ',') {
151
 
      i++;
152
 
    }
153
 
 
154
 
    /* Null-terminate the subpattern. */
155
 
    sub[subi] = '\0';
156
 
 
157
 
    /* Try to match the subpattern against the string. */
158
 
    if (match_pattern(string, sub)) {
159
 
      if (negated) {
160
 
        return -1;        /* Negative */
161
 
      } else {
162
 
        got_positive = 1; /* Positive */
163
 
      }
164
 
    }
165
 
  }
166
 
 
167
 
  /*
168
 
   * Return success if got a positive match.  If there was a negative
169
 
   * match, we have already returned -1 and never get here.
170
 
   */
171
 
  return got_positive;
172
 
}
173
 
 
174
 
/*
175
 
 * Tries to match the host name (which must be in all lowercase) against the
176
 
 * comma-separated sequence of subpatterns (each possibly preceded by ! to
177
 
 * indicate negation).
178
 
 * Returns -1 if negation matches, 1 if there is a positive match, 0 if there
179
 
 * is no match at all.
180
 
 */
181
 
int match_hostname(const char *host, const char *pattern, unsigned int len) {
182
 
  return match_pattern_list(host, pattern, len, 1);
183
 
}
184
 
 
185
 
/* vim: set ts=2 sw=2 et cindent: */