~ubuntu-branches/ubuntu/raring/nss/raring-security

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/util/portreg.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-03-25 13:46:06 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20100325134606-bl6liuok2w9l7snv
Tags: 3.12.6-0ubuntu1
* New upstream release 3.12.6 RTM (NSS_3_12_6_RTM)
  - fixes CVE-2009-3555 aka US-CERT VU#120541
* Adjust patches to changed upstream code base
  - update debian/patches/38_kbsd.patch
  - update debian/patches/38_mips64_build.patch
  - update debian/patches/85_security_load.patch
* Remove patches that are merged upstream
  - delete debian/patches/91_nonexec_stack.patch
  - update debian/patches/series
* Bump nspr dependency to 4.8
  - update debian/control
* Add new symbols for 3.12.6
  - update debian/libnss3-1d.symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 * the Initial Developer. All Rights Reserved.
20
20
 *
21
21
 * Contributor(s):
 
22
 *      Rob McCool  (original author)
22
23
 *      Ken Key <key+mozilla@ksquared.net>
 
24
 *      Nelson Bolyard <nelson@bolyard.me>
23
25
 *
24
26
 * Alternatively, the contents of this file may be used under the terms of
25
27
 * either the GNU General Public License Version 2 or later (the "GPL"), or
38
40
/* 
39
41
 * shexp.c: shell-like wildcard match routines
40
42
 *
41
 
 *
42
43
 * See shexp.h for public documentation.
43
 
 *
44
44
 */
45
45
 
46
46
#include "seccomon.h"
50
50
 
51
51
 
52
52
static int 
53
 
_valid_subexp(const char *exp, char stop) 
 
53
_valid_subexp(const char *exp, char stop1, char stop2) 
54
54
{
55
 
    register int x,y,t;
56
 
    int nsc,np,tld;
57
 
 
58
 
    x=0;nsc=0;tld=0;
59
 
 
60
 
    while(exp[x] && (exp[x] != stop)) {
 
55
    register int x;
 
56
    int nsc = 0;     /* Number of special characters */
 
57
    int np;          /* Number of pipe characters in union */
 
58
    int tld = 0;     /* Number of tilde characters */
 
59
 
 
60
    for (x = 0; exp[x] && (exp[x] != stop1) && (exp[x] != stop2); ++x) {
61
61
        switch(exp[x]) {
62
 
          case '~':
63
 
            if(tld) return INVALID_SXP;
64
 
            else ++tld;
65
 
          case '*':
66
 
          case '?':
67
 
          case '^':
68
 
          case '$':
 
62
        case '~':
 
63
            if(tld)                 /* at most one exclusion */
 
64
                return INVALID_SXP;
 
65
            if (stop1)              /* no exclusions within unions */
 
66
                return INVALID_SXP;
 
67
            if (!exp[x+1])          /* exclusion cannot be last character */
 
68
                return INVALID_SXP;
 
69
            if (!x)                 /* exclusion cannot be first character */
 
70
                return INVALID_SXP;
 
71
            ++tld;
 
72
            /* fall through */
 
73
        case '*':
 
74
        case '?':
 
75
        case '$':
69
76
            ++nsc;
70
77
            break;
71
 
          case '[':
 
78
        case '[':
72
79
            ++nsc;
73
80
            if((!exp[++x]) || (exp[x] == ']'))
74
81
                return INVALID_SXP;
75
 
            for(++x;exp[x] && (exp[x] != ']');++x)
76
 
                if(exp[x] == '\\')
77
 
                    if(!exp[++x])
78
 
                        return INVALID_SXP;
 
82
            for(; exp[x] && (exp[x] != ']'); ++x) {
 
83
                if(exp[x] == '\\' && !exp[++x])
 
84
                    return INVALID_SXP;
 
85
            }
79
86
            if(!exp[x])
80
87
                return INVALID_SXP;
81
88
            break;
82
 
          case '(':
83
 
            ++nsc;np = 0;
84
 
            while(1) {
85
 
                if(exp[++x] == ')')
86
 
                    return INVALID_SXP;
87
 
                for(y=x;(exp[y]) && (exp[y] != '|') && (exp[y] != ')');++y)
88
 
                    if(exp[y] == '\\')
89
 
                        if(!exp[++y])
90
 
                            return INVALID_SXP;
91
 
                if(!exp[y])
92
 
                    return INVALID_SXP;
93
 
                if(exp[y] == '|')
94
 
                    ++np;
95
 
                t = _valid_subexp(&exp[x],exp[y]);
96
 
                if(t == INVALID_SXP)
 
89
        case '(':
 
90
            ++nsc;
 
91
            if (stop1)                  /* no nested unions */
 
92
                return INVALID_SXP;
 
93
            np = -1;
 
94
            do {
 
95
                int t = _valid_subexp(&exp[++x], ')', '|');
 
96
                if(t == 0 || t == INVALID_SXP)
97
97
                    return INVALID_SXP;
98
98
                x+=t;
99
 
                if(exp[x] == ')') {
100
 
                    if(!np)
101
 
                        return INVALID_SXP;
102
 
                    break;
103
 
                }
104
 
            }
 
99
                if(!exp[x])
 
100
                    return INVALID_SXP;
 
101
                ++np;
 
102
            } while (exp[x] == '|' );
 
103
            if(np < 1)  /* must be at least one pipe */
 
104
                return INVALID_SXP;
105
105
            break;
106
 
          case ')':
107
 
          case ']':
 
106
        case ')':
 
107
        case '|':
 
108
        case ']':
108
109
            return INVALID_SXP;
109
 
          case '\\':
 
110
        case '\\':
 
111
            ++nsc;
110
112
            if(!exp[++x])
111
113
                return INVALID_SXP;
112
 
          default:
 
114
            break;
 
115
        default:
113
116
            break;
114
117
        }
115
 
        ++x;
116
118
    }
117
 
    if((!stop) && (!nsc))
 
119
    if((!stop1) && (!nsc)) /* must be at least one special character */
118
120
        return NON_SXP;
119
 
    return ((exp[x] == stop) ? x : INVALID_SXP);
 
121
    return ((exp[x] == stop1 || exp[x] == stop2) ? x : INVALID_SXP);
120
122
}
121
123
 
122
124
int 
124
126
{
125
127
    int x;
126
128
 
127
 
    x = _valid_subexp(exp, '\0');
 
129
    x = _valid_subexp(exp, '\0', '\0');
128
130
    return (x < 0 ? x : VALID_SXP);
129
131
}
130
132
 
136
138
#define NOMATCH 1
137
139
#define ABORTED -1
138
140
 
139
 
static int _shexp_match(const char *str, const char *exp, PRBool case_insensitive);
140
 
 
141
 
static int 
142
 
_handle_union(const char *str, const char *exp, PRBool case_insensitive) 
143
 
{
144
 
    char *e2 = (char *) PORT_Alloc(sizeof(char)*strlen(exp));
145
 
    register int t,p2,p1 = 1;
146
 
    int cp;
147
 
 
148
 
    while(1) {
149
 
        for(cp=1;exp[cp] != ')';cp++)
150
 
            if(exp[cp] == '\\')
151
 
                ++cp;
152
 
        for(p2 = 0;(exp[p1] != '|') && (p1 != cp);p1++,p2++) {
153
 
            if(exp[p1] == '\\')
154
 
                e2[p2++] = exp[p1++];
155
 
            e2[p2] = exp[p1];
156
 
        }
157
 
        for (t=cp+1; ((e2[p2] = exp[t]) != 0); ++t,++p2) {}
158
 
        if(_shexp_match(str,e2, case_insensitive) == MATCH) {
159
 
            PORT_Free(e2);
160
 
            return MATCH;
161
 
        }
162
 
        if(p1 == cp) {
163
 
            PORT_Free(e2);
 
141
static int 
 
142
_shexp_match(const char *str, const char *exp, PRBool case_insensitive,
 
143
             unsigned int level);
 
144
 
 
145
/* Count characters until we reach a NUL character or either of the 
 
146
 * two delimiter characters, stop1 or stop2.  If we encounter a bracketed 
 
147
 * expression, look only for NUL or ']' inside it.  Do not look for stop1 
 
148
 * or stop2 inside it. Return ABORTED if bracketed expression is unterminated.
 
149
 * Handle all escaping.
 
150
 * Return index in input string of first stop found, or ABORTED if not found.
 
151
 * If "dest" is non-NULL, copy counted characters to it and NUL terminate.
 
152
 */
 
153
static int 
 
154
_scan_and_copy(const char *exp, char stop1, char stop2, char *dest)
 
155
{
 
156
    register int sx;     /* source index */
 
157
    register char cc;
 
158
 
 
159
    for (sx = 0; (cc = exp[sx]) && cc != stop1 && cc != stop2; sx++) {
 
160
        if (cc == '\\') {
 
161
            if (!exp[++sx])
 
162
                return ABORTED; /* should be impossible */
 
163
        } else if (cc == '[') {
 
164
            while ((cc = exp[++sx]) && cc != ']') {
 
165
                if(cc == '\\' && !exp[++sx])
 
166
                    return ABORTED;
 
167
            }
 
168
            if (!cc) 
 
169
                return ABORTED; /* should be impossible */
 
170
        }
 
171
    }
 
172
    if (dest && sx) {
 
173
        /* Copy all but the closing delimiter. */
 
174
        memcpy(dest, exp, sx);
 
175
        dest[sx] = 0;
 
176
    }
 
177
    return cc ? sx : ABORTED; /* index of closing delimiter */
 
178
}
 
179
 
 
180
/* On input, exp[0] is the opening parenthesis of a union.
 
181
 * See if any of the alternatives in the union matches as a pattern.
 
182
 * The strategy is to take each of the alternatives, in turn, and append
 
183
 * the rest of the expression (after the closing ')' that marks the end of 
 
184
 * this union) to that alternative, and then see if the resultant expression
 
185
 * matches the input string.  Repeat this until some alternative matches, 
 
186
 * or we have an abort. 
 
187
 */
 
188
static int 
 
189
_handle_union(const char *str, const char *exp, PRBool case_insensitive,
 
190
              unsigned int level) 
 
191
{
 
192
    register int sx;     /* source index */
 
193
    int cp;              /* source index of closing parenthesis */
 
194
    int count;
 
195
    int ret   = NOMATCH;
 
196
    char *e2;
 
197
 
 
198
    /* Find the closing parenthesis that ends this union in the expression */
 
199
    cp = _scan_and_copy(exp, ')', '\0', NULL);
 
200
    if (cp == ABORTED || cp < 4) /* must be at least "(a|b" before ')' */
 
201
        return ABORTED;
 
202
    ++cp;                /* now index of char after closing parenthesis */
 
203
    e2 = (char *) PORT_Alloc(1 + strlen(exp));
 
204
    if (!e2)
 
205
        return ABORTED;
 
206
    for (sx = 1; ; ++sx) {
 
207
        /* Here, exp[sx] is one character past the preceeding '(' or '|'. */
 
208
        /* Copy everything up to the next delimiter to e2 */
 
209
        count = _scan_and_copy(exp + sx, ')', '|', e2);
 
210
        if (count == ABORTED || !count) {
 
211
            ret = ABORTED;
 
212
            break;
 
213
        }
 
214
        sx += count;
 
215
        /* Append everything after closing parenthesis to e2. This is safe. */
 
216
        strcpy(e2+count, exp+cp);
 
217
        ret = _shexp_match(str, e2, case_insensitive, level + 1);
 
218
        if (ret != NOMATCH || !exp[sx] || exp[sx] == ')')
 
219
            break;
 
220
    }
 
221
    PORT_Free(e2);
 
222
    if (sx < 2)
 
223
        ret = ABORTED;
 
224
    return ret;
 
225
}
 
226
 
 
227
/* returns 1 if val is in range from start..end, case insensitive. */
 
228
static int
 
229
_is_char_in_range(int start, int end, int val)
 
230
{
 
231
    char map[256];
 
232
    memset(map, 0, sizeof map);
 
233
    while (start <= end)
 
234
        map[tolower(start++)] = 1;
 
235
    return map[tolower(val)];
 
236
}
 
237
 
 
238
static int 
 
239
_shexp_match(const char *str, const char *exp, PRBool case_insensitive, 
 
240
             unsigned int level) 
 
241
{
 
242
    register int x;   /* input string index */
 
243
    register int y;   /* expression index */
 
244
    int ret,neg;
 
245
 
 
246
    if (level > 20)      /* Don't let the stack get too deep. */
 
247
        return ABORTED;
 
248
    for(x = 0, y = 0; exp[y]; ++y, ++x) {
 
249
        if((!str[x]) && (exp[y] != '$') && (exp[y] != '*')) {
164
250
            return NOMATCH;
165
 
        }
166
 
        else ++p1;
 
251
        }
 
252
        switch(exp[y]) {
 
253
        case '$':
 
254
            if(str[x])
 
255
                return NOMATCH;
 
256
            --x;                 /* we don't want loop to increment x */
 
257
            break;
 
258
        case '*':
 
259
            while(exp[++y] == '*'){}
 
260
            if(!exp[y])
 
261
                return MATCH;
 
262
            while(str[x]) {
 
263
                ret = _shexp_match(&str[x++], &exp[y], case_insensitive, 
 
264
                                   level + 1);
 
265
                switch(ret) {
 
266
                case NOMATCH:
 
267
                    continue;
 
268
                case ABORTED:
 
269
                    return ABORTED;
 
270
                default:
 
271
                    return MATCH;
 
272
                }
 
273
            }
 
274
            if((exp[y] == '$') && (exp[y+1] == '\0') && (!str[x]))
 
275
                return MATCH;
 
276
            else
 
277
                return NOMATCH;
 
278
        case '[': {
 
279
            int start, end = 0, i;
 
280
            neg = ((exp[++y] == '^') && (exp[y+1] != ']'));
 
281
            if (neg)
 
282
                ++y;
 
283
            i = y;
 
284
            start = (unsigned char)(exp[i++]);
 
285
            if (start == '\\')
 
286
                start = (unsigned char)(exp[i++]);
 
287
            if (isalnum(start) && exp[i++] == '-') {
 
288
                end = (unsigned char)(exp[i++]); 
 
289
                if (end == '\\')
 
290
                    end = (unsigned char)(exp[i++]);
 
291
            }
 
292
            if (isalnum(end) && exp[i] == ']') {
 
293
                /* This is a range form: a-b */
 
294
                int val   = (unsigned char)(str[x]);
 
295
                if (end < start) { /* swap them */
 
296
                    start ^= end;
 
297
                    end ^= start;
 
298
                    start ^= end;
 
299
                }
 
300
                if (case_insensitive && isalpha(val)) {
 
301
                    val = _is_char_in_range(start, end, val);
 
302
                    if (neg == val)
 
303
                        return NOMATCH;
 
304
                } else if (neg != ((val < start) || (val > end))) {
 
305
                    return NOMATCH;
 
306
                }
 
307
                y = i;
 
308
            } else {
 
309
                /* Not range form */
 
310
                int matched = 0;
 
311
                for (; exp[y] != ']'; y++) {
 
312
                    if (exp[y] == '\\')
 
313
                        ++y;
 
314
                    if(case_insensitive) {
 
315
                        matched |= (toupper(str[x]) == toupper(exp[y]));
 
316
                    } else {
 
317
                        matched |= (str[x] == exp[y]);
 
318
                    }
 
319
                }
 
320
                if (neg == matched)
 
321
                    return NOMATCH;
 
322
            }
 
323
        }
 
324
        break;
 
325
        case '(':
 
326
            if (!exp[y+1])
 
327
                return ABORTED;
 
328
            return _handle_union(&str[x], &exp[y], case_insensitive, level);
 
329
        case '?':
 
330
            break;
 
331
        case '|':
 
332
        case ']':
 
333
        case ')':
 
334
            return ABORTED;
 
335
        case '\\':
 
336
            ++y;
 
337
            /* fall through */
 
338
        default:
 
339
            if(case_insensitive) {
 
340
                if(toupper(str[x]) != toupper(exp[y]))
 
341
                    return NOMATCH;
 
342
            } else {
 
343
                if(str[x] != exp[y])
 
344
                    return NOMATCH;
 
345
            }
 
346
            break;
 
347
        }
167
348
    }
 
349
    return (str[x] ? NOMATCH : MATCH);
168
350
}
169
351
 
170
 
 
171
352
static int 
172
 
_shexp_match(const char *str, const char *exp, PRBool case_insensitive) 
 
353
port_RegExpMatch(const char *str, const char *xp, PRBool case_insensitive) 
173
354
{
174
 
    register int x,y;
175
 
    int ret,neg;
176
 
 
177
 
    ret = 0;
178
 
    for(x=0,y=0;exp[y];++y,++x) {
179
 
        if((!str[x]) && (exp[y] != '(') && (exp[y] != '$') && (exp[y] != '*'))
180
 
            ret = ABORTED;
181
 
        else {
182
 
            switch(exp[y]) {
183
 
              case '$':
184
 
                if( (str[x]) )
185
 
                    ret = NOMATCH;
186
 
                else
187
 
                    --x;             /* we don't want loop to increment x */
188
 
                break;
189
 
              case '*':
190
 
                while(exp[++y] == '*'){}
191
 
                if(!exp[y])
192
 
                    return MATCH;
193
 
                while(str[x]) {
194
 
                    switch(_shexp_match(&str[x++],&exp[y], case_insensitive)) {
195
 
                    case NOMATCH:
196
 
                        continue;
197
 
                    case ABORTED:
198
 
                        ret = ABORTED;
199
 
                        break;
200
 
                    default:
201
 
                        return MATCH;
202
 
                    }
203
 
                    break;
204
 
                }
205
 
                if((exp[y] == '$') && (exp[y+1] == '\0') && (!str[x]))
206
 
                    return MATCH;
207
 
                else
208
 
                    ret = ABORTED;
209
 
                break;
210
 
              case '[':
211
 
                neg = ((exp[++y] == '^') && (exp[y+1] != ']'));
212
 
                if (neg)
213
 
                    ++y;
214
 
                
215
 
                if ((isalnum(exp[y])) && (exp[y+1] == '-') && 
216
 
                   (isalnum(exp[y+2])) && (exp[y+3] == ']'))
217
 
                    {
218
 
                        int start = exp[y], end = exp[y+2];
219
 
                        
220
 
                        /* no safeguards here */
221
 
                        if(neg ^ ((str[x] < start) || (str[x] > end))) {
222
 
                            ret = NOMATCH;
223
 
                            break;
224
 
                        }
225
 
                        y+=3;
226
 
                    }
227
 
                else {
228
 
                    int matched;
229
 
                    
230
 
                    for (matched=0;exp[y] != ']';y++)
231
 
                        matched |= (str[x] == exp[y]);
232
 
                    if (neg ^ (!matched))
233
 
                        ret = NOMATCH;
234
 
                }
235
 
                break;
236
 
              case '(':
237
 
                return _handle_union(&str[x],&exp[y], case_insensitive);
238
 
                break;
239
 
              case '?':
240
 
                break;
241
 
              case '\\':
242
 
                ++y;
243
 
              default:
244
 
                if(case_insensitive)
245
 
                  {
246
 
                    if(toupper(str[x]) != toupper(exp[y]))
247
 
                        ret = NOMATCH;
248
 
                  }
249
 
                else
250
 
                  {
251
 
                    if(str[x] != exp[y])
252
 
                        ret = NOMATCH;
253
 
                  }
254
 
                break;
255
 
            }
256
 
        }
257
 
        if(ret)
258
 
            break;
259
 
    }
260
 
    return (ret ? ret : (str[x] ? NOMATCH : MATCH));
261
 
}
262
 
 
263
 
static int 
264
 
port_RegExpMatch(const char *str, const char *xp, PRBool case_insensitive) {
265
 
    register int x;
266
355
    char *exp = 0;
 
356
    int x, ret = MATCH;
 
357
 
 
358
    if (!strchr(xp, '~'))
 
359
        return _shexp_match(str, xp, case_insensitive, 0);
267
360
 
268
361
    exp = PORT_Strdup(xp);
269
 
 
270
362
    if(!exp)
271
 
        return 1;
 
363
        return NOMATCH;
272
364
 
273
 
    for(x=strlen(exp)-1;x;--x) {
274
 
        if((exp[x] == '~') && (exp[x-1] != '\\')) {
275
 
            exp[x] = '\0';
276
 
            if(_shexp_match(str,&exp[++x], case_insensitive) == MATCH)
277
 
                goto punt;
278
 
            break;
 
365
    x = _scan_and_copy(exp, '~', '\0', NULL);
 
366
    if (x != ABORTED && exp[x] == '~') {
 
367
        exp[x++] = '\0';
 
368
        ret = _shexp_match(str, &exp[x], case_insensitive, 0);
 
369
        switch (ret) {
 
370
        case NOMATCH: ret = MATCH;   break;
 
371
        case MATCH:   ret = NOMATCH; break;
 
372
        default:                     break;
279
373
        }
280
374
    }
281
 
    if(_shexp_match(str,exp, case_insensitive) == MATCH) {
282
 
        PORT_Free(exp);
283
 
        return 0;
284
 
    }
 
375
    if (ret == MATCH)
 
376
        ret = _shexp_match(str, exp, case_insensitive, 0);
285
377
 
286
 
  punt:
287
378
    PORT_Free(exp);
288
 
    return 1;
 
379
    return ret;
289
380
}
290
381
 
291
382