~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/ssl/ssl_expr_eval.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/*                      _             _
 
18
 *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
 
19
 * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
 
20
 * | | | | | | (_) | (_| |   \__ \__ \ |
 
21
 * |_| |_| |_|\___/ \__,_|___|___/___/_|
 
22
 *                      |_____|
 
23
 *  ssl_expr_eval.c
 
24
 *  Expression Evaluation
 
25
 */
 
26
                             /* ``Make love,
 
27
                                  not software!''
 
28
                                        -- Unknown */
 
29
#include "ssl_private.h"
 
30
 
 
31
/*  _________________________________________________________________
 
32
**
 
33
**  Expression Evaluation
 
34
**  _________________________________________________________________
 
35
*/
 
36
 
 
37
static BOOL  ssl_expr_eval_comp(request_rec *, ssl_expr *);
 
38
static char *ssl_expr_eval_word(request_rec *, ssl_expr *);
 
39
static BOOL  ssl_expr_eval_oid(request_rec *r, const char *word, const char *oidstr);
 
40
static char *ssl_expr_eval_func_file(request_rec *, char *);
 
41
static int   ssl_expr_eval_strcmplex(char *, char *);
 
42
 
 
43
BOOL ssl_expr_eval(request_rec *r, ssl_expr *node)
 
44
{
 
45
    switch (node->node_op) {
 
46
        case op_True: {
 
47
            return TRUE;
 
48
        }
 
49
        case op_False: {
 
50
            return FALSE;
 
51
        }
 
52
        case op_Not: {
 
53
            ssl_expr *e = (ssl_expr *)node->node_arg1;
 
54
            return (!ssl_expr_eval(r, e));
 
55
        }
 
56
        case op_Or: {
 
57
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
58
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
59
            return (ssl_expr_eval(r, e1) || ssl_expr_eval(r, e2));
 
60
        }
 
61
        case op_And: {
 
62
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
63
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
64
            return (ssl_expr_eval(r, e1) && ssl_expr_eval(r, e2));
 
65
        }
 
66
        case op_Comp: {
 
67
            ssl_expr *e = (ssl_expr *)node->node_arg1;
 
68
            return ssl_expr_eval_comp(r, e);
 
69
        }
 
70
        default: {
 
71
            ssl_expr_error = "Internal evaluation error: Unknown expression node";
 
72
            return FALSE;
 
73
        }
 
74
    }
 
75
}
 
76
 
 
77
static BOOL ssl_expr_eval_comp(request_rec *r, ssl_expr *node)
 
78
{
 
79
    switch (node->node_op) {
 
80
        case op_EQ: {
 
81
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
82
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
83
            return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) == 0);
 
84
        }
 
85
        case op_NE: {
 
86
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
87
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
88
            return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) != 0);
 
89
        }
 
90
        case op_LT: {
 
91
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
92
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
93
            return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) <  0);
 
94
        }
 
95
        case op_LE: {
 
96
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
97
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
98
            return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) <= 0);
 
99
        }
 
100
        case op_GT: {
 
101
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
102
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
103
            return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) >  0);
 
104
        }
 
105
        case op_GE: {
 
106
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
107
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
108
            return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) >= 0);
 
109
        }
 
110
        case op_IN: {
 
111
            ssl_expr *e1 = (ssl_expr *)node->node_arg1;
 
112
            ssl_expr *e2 = (ssl_expr *)node->node_arg2;
 
113
            ssl_expr *e3;
 
114
            char *w1 = ssl_expr_eval_word(r, e1);
 
115
            BOOL found = FALSE;
 
116
            do {
 
117
                ssl_expr_node_op op = e2->node_op;
 
118
                e3 = (ssl_expr *)e2->node_arg1;
 
119
                e2 = (ssl_expr *)e2->node_arg2;
 
120
 
 
121
                if (op == op_OidListElement) {
 
122
                    char *w3 = ssl_expr_eval_word(r, e3);
 
123
 
 
124
                    found = ssl_expr_eval_oid(r, w1, w3);
 
125
 
 
126
                    /* There will be no more nodes on the list, so the result is authoritative */
 
127
                    break;
 
128
                }
 
129
 
 
130
                if (strcmp(w1, ssl_expr_eval_word(r, e3)) == 0) {
 
131
                    found = TRUE;
 
132
                    break;
 
133
                }
 
134
            } while (e2 != NULL);
 
135
            return found;
 
136
        }
 
137
        case op_REG: {
 
138
            ssl_expr *e1;
 
139
            ssl_expr *e2;
 
140
            char *word;
 
141
            ap_regex_t *regex;
 
142
 
 
143
            e1 = (ssl_expr *)node->node_arg1;
 
144
            e2 = (ssl_expr *)node->node_arg2;
 
145
            word = ssl_expr_eval_word(r, e1);
 
146
            regex = (ap_regex_t *)(e2->node_arg1);
 
147
            return (ap_regexec(regex, word, 0, NULL, 0) == 0);
 
148
        }
 
149
        case op_NRE: {
 
150
            ssl_expr *e1;
 
151
            ssl_expr *e2;
 
152
            char *word;
 
153
            ap_regex_t *regex;
 
154
 
 
155
            e1 = (ssl_expr *)node->node_arg1;
 
156
            e2 = (ssl_expr *)node->node_arg2;
 
157
            word = ssl_expr_eval_word(r, e1);
 
158
            regex = (ap_regex_t *)(e2->node_arg1);
 
159
            return !(ap_regexec(regex, word, 0, NULL, 0) == 0);
 
160
        }
 
161
        default: {
 
162
            ssl_expr_error = "Internal evaluation error: Unknown expression node";
 
163
            return FALSE;
 
164
        }
 
165
    }
 
166
}
 
167
 
 
168
static char *ssl_expr_eval_word(request_rec *r, ssl_expr *node)
 
169
{
 
170
    switch (node->node_op) {
 
171
        case op_Digit: {
 
172
            char *string = (char *)node->node_arg1;
 
173
            return string;
 
174
        }
 
175
        case op_String: {
 
176
            char *string = (char *)node->node_arg1;
 
177
            return string;
 
178
        }
 
179
        case op_Var: {
 
180
            char *var = (char *)node->node_arg1;
 
181
            char *val = ssl_var_lookup(r->pool, r->server, r->connection, r, var);
 
182
            return (val == NULL ? "" : val);
 
183
        }
 
184
        case op_Func: {
 
185
            char *name = (char *)node->node_arg1;
 
186
            ssl_expr *args = (ssl_expr *)node->node_arg2;
 
187
            if (strEQ(name, "file"))
 
188
                return ssl_expr_eval_func_file(r, (char *)(args->node_arg1));
 
189
            else {
 
190
                ssl_expr_error = "Internal evaluation error: Unknown function name";
 
191
                return "";
 
192
            }
 
193
        }
 
194
        default: {
 
195
            ssl_expr_error = "Internal evaluation error: Unknown expression node";
 
196
            return FALSE;
 
197
        }
 
198
    }
 
199
}
 
200
 
 
201
#define NUM_OID_ELTS 8 /* start with 8 oid slots, resize when needed */
 
202
 
 
203
apr_array_header_t *ssl_extlist_by_oid(request_rec *r, const char *oidstr)
 
204
{
 
205
    int count = 0, j;
 
206
    X509 *xs = NULL;
 
207
    ASN1_OBJECT *oid;
 
208
    apr_array_header_t *val_array;
 
209
    SSLConnRec *sslconn = myConnConfig(r->connection);
 
210
 
 
211
    /* trivia */
 
212
    if (oidstr == NULL || sslconn == NULL || sslconn->ssl == NULL)
 
213
        return NULL;
 
214
 
 
215
    /* Determine the oid we are looking for */
 
216
    if ((oid = OBJ_txt2obj(oidstr, 1)) == NULL) {
 
217
        ERR_clear_error();
 
218
        return NULL;
 
219
    }
 
220
 
 
221
    /* are there any extensions in the cert? */
 
222
    if ((xs = SSL_get_peer_certificate(sslconn->ssl)) == NULL ||
 
223
        (count = X509_get_ext_count(xs)) == 0) {
 
224
        return NULL;
 
225
    }
 
226
 
 
227
    val_array = apr_array_make(r->pool, NUM_OID_ELTS, sizeof(char *));
 
228
 
 
229
    /* Loop over all extensions, extract the desired oids */
 
230
    for (j = 0; j < count; j++) {
 
231
        X509_EXTENSION *ext = X509_get_ext(xs, j);
 
232
 
 
233
        if (OBJ_cmp(ext->object, oid) == 0) {
 
234
            BIO *bio = BIO_new(BIO_s_mem());
 
235
 
 
236
            if (X509V3_EXT_print(bio, ext, 0, 0) == 1) {
 
237
                BUF_MEM *buf;
 
238
                char **new = apr_array_push(val_array);
 
239
 
 
240
                BIO_get_mem_ptr(bio, &buf);
 
241
 
 
242
                *new = apr_pstrdup(r->pool, buf->data);
 
243
            }
 
244
 
 
245
            BIO_vfree(bio);
 
246
        }
 
247
    }
 
248
 
 
249
    X509_free(xs);
 
250
    ERR_clear_error();
 
251
 
 
252
    if (val_array->nelts == 0)
 
253
        return NULL;
 
254
    else
 
255
        return val_array;
 
256
}
 
257
 
 
258
static BOOL ssl_expr_eval_oid(request_rec *r, const char *word, const char *oidstr)
 
259
{
 
260
    int j;
 
261
    BOOL result = FALSE;
 
262
    apr_array_header_t *oid_array;
 
263
    char **oid_value;
 
264
 
 
265
    if (NULL == (oid_array = ssl_extlist_by_oid(r, oidstr))) {
 
266
        return FALSE;
 
267
    }
 
268
 
 
269
    oid_value = (char **) oid_array->elts;
 
270
    for (j = 0; j < oid_array->nelts; j++) {
 
271
        if (strcmp(word, oid_value[j]) == 0) {
 
272
            result = TRUE;
 
273
            break;
 
274
        }
 
275
    }
 
276
    return result;
 
277
}
 
278
 
 
279
 
 
280
static char *ssl_expr_eval_func_file(request_rec *r, char *filename)
 
281
{
 
282
    apr_file_t *fp;
 
283
    char *buf;
 
284
    apr_off_t offset;
 
285
    apr_size_t len;
 
286
    apr_finfo_t finfo;
 
287
 
 
288
    if (apr_file_open(&fp, filename, APR_READ|APR_BUFFERED,
 
289
                      APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
 
290
        ssl_expr_error = "Cannot open file";
 
291
        return "";
 
292
    }
 
293
    apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
 
294
    if ((finfo.size + 1) != ((apr_size_t)finfo.size + 1)) {
 
295
        ssl_expr_error = "Huge file cannot be read";
 
296
        apr_file_close(fp);
 
297
        return "";
 
298
    }
 
299
    len = (apr_size_t)finfo.size;
 
300
    if (len == 0) {
 
301
        buf = (char *)apr_palloc(r->pool, sizeof(char) * 1);
 
302
        *buf = NUL;
 
303
    }
 
304
    else {
 
305
        if ((buf = (char *)apr_palloc(r->pool, sizeof(char)*(len+1))) == NULL) {
 
306
            ssl_expr_error = "Cannot allocate memory";
 
307
            apr_file_close(fp);
 
308
            return "";
 
309
        }
 
310
        offset = 0;
 
311
        apr_file_seek(fp, APR_SET, &offset);
 
312
        if (apr_file_read(fp, buf, &len) != APR_SUCCESS) {
 
313
            ssl_expr_error = "Cannot read from file";
 
314
            apr_file_close(fp);
 
315
            return "";
 
316
        }
 
317
        buf[len] = NUL;
 
318
    }
 
319
    apr_file_close(fp);
 
320
    return buf;
 
321
}
 
322
 
 
323
/* a variant of strcmp(3) which works correctly also for number strings */
 
324
static int ssl_expr_eval_strcmplex(char *cpNum1, char *cpNum2)
 
325
{
 
326
    int i, n1, n2;
 
327
 
 
328
    if (cpNum1 == NULL)
 
329
        return -1;
 
330
    if (cpNum2 == NULL)
 
331
        return +1;
 
332
    n1 = strlen(cpNum1);
 
333
    n2 = strlen(cpNum2);
 
334
    if (n1 > n2)
 
335
        return 1;
 
336
    if (n1 < n2)
 
337
        return -1;
 
338
    for (i = 0; i < n1; i++) {
 
339
        if (cpNum1[i] > cpNum2[i])
 
340
            return 1;
 
341
        if (cpNum1[i] < cpNum2[i])
 
342
            return -1;
 
343
    }
 
344
    return 0;
 
345
}