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#define APR_WANT_STRFUNC
18#include "apr_want.h"
19#include "apr_lib.h"
20#include "apr_hash.h"
21#include "apr_strings.h"
22
23#include "httpd.h"
24#include "http_config.h"
25#include "http_core.h"
26#include "http_log.h"
27#include "util_filter.h"
28
29/* NOTE: Apache's current design doesn't allow a pool to be passed thru,
30   so we depend on a global to hold the correct pool
31*/
32#define FILTER_POOL     apr_hook_global_pool
33#include "ap_hooks.h"   /* for apr_hook_global_pool */
34
35/*
36** This macro returns true/false if a given filter should be inserted BEFORE
37** another filter. This will happen when one of: 1) there isn't another
38** filter; 2) that filter has a higher filter type (class); 3) that filter
39** corresponds to a different request.
40*/
41#define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
42                           || (before_this)->frec->ftype > (f)->frec->ftype \
43                           || (before_this)->r != (f)->r)
44
45/* Trie structure to hold the mapping from registered
46 * filter names to filters
47 */
48
49/* we know core's module_index is 0 */
50#undef APLOG_MODULE_INDEX
51#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
52
53typedef struct filter_trie_node filter_trie_node;
54
55typedef struct {
56    int c;
57    filter_trie_node *child;
58} filter_trie_child_ptr;
59
60/* Each trie node has an array of pointers to its children.
61 * The array is kept in sorted order so that add_any_filter()
62 * can do a binary search
63 */
64struct filter_trie_node {
65    ap_filter_rec_t *frec;
66    filter_trie_child_ptr *children;
67    int nchildren;
68    int size;
69};
70
71#define TRIE_INITIAL_SIZE 4
72
73/* Link a trie node to its parent
74 */
75static void trie_node_link(apr_pool_t *p, filter_trie_node *parent,
76                           filter_trie_node *child, int c)
77{
78    int i, j;
79
80    if (parent->nchildren == parent->size) {
81        filter_trie_child_ptr *new;
82        parent->size *= 2;
83        new = (filter_trie_child_ptr *)apr_palloc(p, parent->size *
84                                             sizeof(filter_trie_child_ptr));
85        memcpy(new, parent->children, parent->nchildren *
86               sizeof(filter_trie_child_ptr));
87        parent->children = new;
88    }
89
90    for (i = 0; i < parent->nchildren; i++) {
91        if (c == parent->children[i].c) {
92            return;
93        }
94        else if (c < parent->children[i].c) {
95            break;
96        }
97    }
98    for (j = parent->nchildren; j > i; j--) {
99        parent->children[j].c = parent->children[j - 1].c;
100        parent->children[j].child = parent->children[j - 1].child;
101    }
102    parent->children[i].c = c;
103    parent->children[i].child = child;
104
105    parent->nchildren++;
106}
107
108/* Allocate a new node for a trie.
109 * If parent is non-NULL, link the new node under the parent node with
110 * key 'c' (or, if an existing child node matches, return that one)
111 */
112static filter_trie_node *trie_node_alloc(apr_pool_t *p,
113                                         filter_trie_node *parent, char c)
114{
115    filter_trie_node *new_node;
116    if (parent) {
117        int i;
118        for (i = 0; i < parent->nchildren; i++) {
119            if (c == parent->children[i].c) {
120                return parent->children[i].child;
121            }
122            else if (c < parent->children[i].c) {
123                break;
124            }
125        }
126        new_node =
127            (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node));
128        trie_node_link(p, parent, new_node, c);
129    }
130    else { /* No parent node */
131        new_node = (filter_trie_node *)apr_palloc(p,
132                                                  sizeof(filter_trie_node));
133    }
134
135    new_node->frec = NULL;
136    new_node->nchildren = 0;
137    new_node->size = TRIE_INITIAL_SIZE;
138    new_node->children = (filter_trie_child_ptr *)apr_palloc(p,
139                             new_node->size * sizeof(filter_trie_child_ptr));
140    return new_node;
141}
142
143static filter_trie_node *registered_output_filters = NULL;
144static filter_trie_node *registered_input_filters = NULL;
145
146
147static apr_status_t filter_cleanup(void *ctx)
148{
149    registered_output_filters = NULL;
150    registered_input_filters = NULL;
151    return APR_SUCCESS;
152}
153
154static ap_filter_rec_t *get_filter_handle(const char *name,
155                                          const filter_trie_node *filter_set)
156{
157    if (filter_set) {
158        const char *n;
159        const filter_trie_node *node;
160
161        node = filter_set;
162        for (n = name; *n; n++) {
163            int start, end;
164            start = 0;
165            end = node->nchildren - 1;
166            while (end >= start) {
167                int middle = (end + start) / 2;
168                char ch = node->children[middle].c;
169                if (*n == ch) {
170                    node = node->children[middle].child;
171                    break;
172                }
173                else if (*n < ch) {
174                    end = middle - 1;
175                }
176                else {
177                    start = middle + 1;
178                }
179            }
180            if (end < start) {
181                node = NULL;
182                break;
183            }
184        }
185
186        if (node && node->frec) {
187            return node->frec;
188        }
189    }
190    return NULL;
191}
192
193AP_DECLARE(ap_filter_rec_t *)ap_get_output_filter_handle(const char *name)
194{
195    return get_filter_handle(name, registered_output_filters);
196}
197
198AP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name)
199{
200    return get_filter_handle(name, registered_input_filters);
201}
202
203static ap_filter_rec_t *register_filter(const char *name,
204                            ap_filter_func filter_func,
205                            ap_init_filter_func filter_init,
206                            ap_filter_type ftype,
207                            filter_trie_node **reg_filter_set)
208{
209    ap_filter_rec_t *frec;
210    char *normalized_name;
211    const char *n;
212    filter_trie_node *node;
213
214    if (!*reg_filter_set) {
215        *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0);
216    }
217
218    normalized_name = apr_pstrdup(FILTER_POOL, name);
219    ap_str_tolower(normalized_name);
220
221    node = *reg_filter_set;
222    for (n = normalized_name; *n; n++) {
223        filter_trie_node *child = trie_node_alloc(FILTER_POOL, node, *n);
224        if (apr_isalpha(*n)) {
225            trie_node_link(FILTER_POOL, node, child, apr_toupper(*n));
226        }
227        node = child;
228    }
229    if (node->frec) {
230        frec = node->frec;
231    }
232    else {
233        frec = apr_pcalloc(FILTER_POOL, sizeof(*frec));
234        node->frec = frec;
235        frec->name = normalized_name;
236    }
237    frec->filter_func = filter_func;
238    frec->filter_init_func = filter_init;
239    frec->ftype = ftype;
240
241    apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
242                              apr_pool_cleanup_null);
243    return frec;
244}
245
246AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
247                                          ap_in_filter_func filter_func,
248                                          ap_init_filter_func filter_init,
249                                          ap_filter_type ftype)
250{
251    ap_filter_func f;
252    f.in_func = filter_func;
253    return register_filter(name, f, filter_init, ftype,
254                           &registered_input_filters);
255}
256
257AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
258                                           ap_out_filter_func filter_func,
259                                           ap_init_filter_func filter_init,
260                                           ap_filter_type ftype)
261{
262    return ap_register_output_filter_protocol(name, filter_func,
263                                              filter_init, ftype, 0);
264}
265
266AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter_protocol(
267                                           const char *name,
268                                           ap_out_filter_func filter_func,
269                                           ap_init_filter_func filter_init,
270                                           ap_filter_type ftype,
271                                           unsigned int proto_flags)
272{
273    ap_filter_rec_t* ret ;
274    ap_filter_func f;
275    f.out_func = filter_func;
276    ret = register_filter(name, f, filter_init, ftype,
277                          &registered_output_filters);
278    ret->proto_flags = proto_flags ;
279    return ret ;
280}
281
282static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,
283                                          request_rec *r, conn_rec *c,
284                                          ap_filter_t **r_filters,
285                                          ap_filter_t **p_filters,
286                                          ap_filter_t **c_filters)
287{
288    apr_pool_t *p = frec->ftype < AP_FTYPE_CONNECTION && r ? r->pool : c->pool;
289    ap_filter_t *f = apr_palloc(p, sizeof(*f));
290    ap_filter_t **outf;
291
292    if (frec->ftype < AP_FTYPE_PROTOCOL) {
293        if (r) {
294            outf = r_filters;
295        }
296        else {
297            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00080)
298                          "a content filter was added without a request: %s", frec->name);
299            return NULL;
300        }
301    }
302    else if (frec->ftype < AP_FTYPE_CONNECTION) {
303        if (r) {
304            outf = p_filters;
305        }
306        else {
307            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00081)
308                          "a protocol filter was added without a request: %s", frec->name);
309            return NULL;
310        }
311    }
312    else {
313        outf = c_filters;
314    }
315
316    f->frec = frec;
317    f->ctx = ctx;
318    /* f->r must always be NULL for connection filters */
319    f->r = frec->ftype < AP_FTYPE_CONNECTION ? r : NULL;
320    f->c = c;
321    f->next = NULL;
322
323    if (INSERT_BEFORE(f, *outf)) {
324        f->next = *outf;
325
326        if (*outf) {
327            ap_filter_t *first = NULL;
328
329            if (r) {
330                /* If we are adding our first non-connection filter,
331                 * Then don't try to find the right location, it is
332                 * automatically first.
333                 */
334                if (*r_filters != *c_filters) {
335                    first = *r_filters;
336                    while (first && (first->next != (*outf))) {
337                        first = first->next;
338                    }
339                }
340            }
341            if (first && first != (*outf)) {
342                first->next = f;
343            }
344        }
345        *outf = f;
346    }
347    else {
348        ap_filter_t *fscan = *outf;
349        while (!INSERT_BEFORE(f, fscan->next))
350            fscan = fscan->next;
351
352        f->next = fscan->next;
353        fscan->next = f;
354    }
355
356    if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
357        *r_filters = *p_filters;
358    }
359    return f;
360}
361
362static ap_filter_t *add_any_filter(const char *name, void *ctx,
363                                   request_rec *r, conn_rec *c,
364                                   const filter_trie_node *reg_filter_set,
365                                   ap_filter_t **r_filters,
366                                   ap_filter_t **p_filters,
367                                   ap_filter_t **c_filters)
368{
369    if (reg_filter_set) {
370        const char *n;
371        const filter_trie_node *node;
372
373        node = reg_filter_set;
374        for (n = name; *n; n++) {
375            int start, end;
376            start = 0;
377            end = node->nchildren - 1;
378            while (end >= start) {
379                int middle = (end + start) / 2;
380                char ch = node->children[middle].c;
381                if (*n == ch) {
382                    node = node->children[middle].child;
383                    break;
384                }
385                else if (*n < ch) {
386                    end = middle - 1;
387                }
388                else {
389                    start = middle + 1;
390                }
391            }
392            if (end < start) {
393                node = NULL;
394                break;
395            }
396        }
397
398        if (node && node->frec) {
399            return add_any_filter_handle(node->frec, ctx, r, c, r_filters,
400                                         p_filters, c_filters);
401        }
402    }
403
404    ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, r ? r->connection : c, APLOGNO(00082)
405                  "an unknown filter was not added: %s", name);
406    return NULL;
407}
408
409AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
410                                              request_rec *r, conn_rec *c)
411{
412    return add_any_filter(name, ctx, r, c, registered_input_filters,
413                          r ? &r->input_filters : NULL,
414                          r ? &r->proto_input_filters : NULL, &c->input_filters);
415}
416
417AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f,
418                                                     void *ctx,
419                                                     request_rec *r,
420                                                     conn_rec *c)
421{
422    return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL,
423                                 r ? &r->proto_input_filters : NULL,
424                                 &c->input_filters);
425}
426
427AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
428                                               request_rec *r, conn_rec *c)
429{
430    return add_any_filter(name, ctx, r, c, registered_output_filters,
431                          r ? &r->output_filters : NULL,
432                          r ? &r->proto_output_filters : NULL, &c->output_filters);
433}
434
435AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f,
436                                                      void *ctx,
437                                                      request_rec *r,
438                                                      conn_rec *c)
439{
440    return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL,
441                                 r ? &r->proto_output_filters : NULL,
442                                 &c->output_filters);
443}
444
445static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
446                              ap_filter_t **c_filt)
447{
448    ap_filter_t **curr = r_filt ? r_filt : c_filt;
449    ap_filter_t *fscan = *curr;
450
451    if (p_filt && *p_filt == f)
452        *p_filt = (*p_filt)->next;
453
454    if (*curr == f) {
455        *curr = (*curr)->next;
456        return;
457    }
458
459    while (fscan->next != f) {
460        if (!(fscan = fscan->next)) {
461            return;
462        }
463    }
464
465    fscan->next = f->next;
466}
467
468AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
469{
470    remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
471                      f->r ? &f->r->proto_input_filters : NULL,
472                      &f->c->input_filters);
473}
474
475AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
476{
477    remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
478                      f->r ? &f->r->proto_output_filters : NULL,
479                      &f->c->output_filters);
480}
481
482AP_DECLARE(apr_status_t) ap_remove_input_filter_byhandle(ap_filter_t *next,
483                                                         const char *handle)
484{
485    ap_filter_t *found = NULL;
486    ap_filter_rec_t *filter;
487
488    if (!handle) {
489        return APR_EINVAL;
490    }
491    filter = ap_get_input_filter_handle(handle);
492    if (!filter) {
493        return APR_NOTFOUND;
494    }
495
496    while (next) {
497        if (next->frec == filter) {
498            found = next;
499            break;
500        }
501        next = next->next;
502    }
503    if (found) {
504        ap_remove_input_filter(found);
505        return APR_SUCCESS;
506    }
507    return APR_NOTFOUND;
508}
509
510AP_DECLARE(apr_status_t) ap_remove_output_filter_byhandle(ap_filter_t *next,
511                                                          const char *handle)
512{
513    ap_filter_t *found = NULL;
514    ap_filter_rec_t *filter;
515
516    if (!handle) {
517        return APR_EINVAL;
518    }
519    filter = ap_get_output_filter_handle(handle);
520    if (!filter) {
521        return APR_NOTFOUND;
522    }
523
524    while (next) {
525        if (next->frec == filter) {
526            found = next;
527            break;
528        }
529        next = next->next;
530    }
531    if (found) {
532        ap_remove_output_filter(found);
533        return APR_SUCCESS;
534    }
535    return APR_NOTFOUND;
536}
537
538
539/*
540 * Read data from the next filter in the filter stack.  Data should be
541 * modified in the bucket brigade that is passed in.  The core allocates the
542 * bucket brigade, modules that wish to replace large chunks of data or to
543 * save data off to the side should probably create their own temporary
544 * brigade especially for that use.
545 */
546AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
547                                        apr_bucket_brigade *bb,
548                                        ap_input_mode_t mode,
549                                        apr_read_type_e block,
550                                        apr_off_t readbytes)
551{
552    if (next) {
553        return next->frec->filter_func.in_func(next, bb, mode, block,
554                                               readbytes);
555    }
556    return AP_NOBODY_READ;
557}
558
559/* Pass the buckets to the next filter in the filter stack.  If the
560 * current filter is a handler, we should get NULL passed in instead of
561 * the current filter.  At that point, we can just call the first filter in
562 * the stack, or r->output_filters.
563 */
564AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
565                                         apr_bucket_brigade *bb)
566{
567    if (next) {
568        apr_bucket *e;
569        if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
570            /* This is only safe because HTTP_HEADER filter is always in
571             * the filter stack.   This ensures that there is ALWAYS a
572             * request-based filter that we can attach this to.  If the
573             * HTTP_FILTER is removed, and another filter is not put in its
574             * place, then handlers like mod_cgi, which attach their own
575             * EOS bucket to the brigade will be broken, because we will
576             * get two EOS buckets on the same request.
577             */
578            next->r->eos_sent = 1;
579
580            /* remember the eos for internal redirects, too */
581            if (next->r->prev) {
582                request_rec *prev = next->r->prev;
583
584                while (prev) {
585                    prev->eos_sent = 1;
586                    prev = prev->prev;
587                }
588            }
589        }
590        return next->frec->filter_func.out_func(next, bb);
591    }
592    return AP_NOBODY_WROTE;
593}
594
595/* Pass the buckets to the next filter in the filter stack
596 * checking return status for filter errors.
597 * returns: OK if ap_pass_brigade returns APR_SUCCESS
598 *          AP_FILTER_ERROR if filter error exists
599 *          HTTP_INTERNAL_SERVER_ERROR for all other cases
600 *          logged with optional errmsg
601 */
602AP_DECLARE(apr_status_t) ap_pass_brigade_fchk(request_rec *r,
603                                              apr_bucket_brigade *bb,
604                                              const char *fmt,
605                                              ...)
606{
607    apr_status_t rv;
608
609    rv = ap_pass_brigade(r->output_filters, bb);
610    if (rv != APR_SUCCESS) {
611        if (rv != AP_FILTER_ERROR) {
612            if (!fmt)
613                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(00083)
614                              "ap_pass_brigade returned %d", rv);
615            else {
616                va_list ap;
617                const char *res;
618                va_start(ap, fmt);
619                res = apr_pvsprintf(r->pool, fmt, ap);
620                va_end(ap);
621                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, "%s", res);
622            }
623            return HTTP_INTERNAL_SERVER_ERROR;
624        }
625        return AP_FILTER_ERROR;
626    }
627    return OK;
628}
629
630AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
631                                         apr_bucket_brigade **saveto,
632                                         apr_bucket_brigade **b, apr_pool_t *p)
633{
634    apr_bucket *e;
635    apr_status_t rv, srv = APR_SUCCESS;
636
637    /* If have never stored any data in the filter, then we had better
638     * create an empty bucket brigade so that we can concat.
639     */
640    if (!(*saveto)) {
641        *saveto = apr_brigade_create(p, f->c->bucket_alloc);
642    }
643
644    for (e = APR_BRIGADE_FIRST(*b);
645         e != APR_BRIGADE_SENTINEL(*b);
646         e = APR_BUCKET_NEXT(e))
647    {
648        rv = apr_bucket_setaside(e, p);
649
650        /* If the bucket type does not implement setaside, then
651         * (hopefully) morph it into a bucket type which does, and set
652         * *that* aside... */
653        if (rv == APR_ENOTIMPL) {
654            const char *s;
655            apr_size_t n;
656
657            rv = apr_bucket_read(e, &s, &n, APR_BLOCK_READ);
658            if (rv == APR_SUCCESS) {
659                rv = apr_bucket_setaside(e, p);
660            }
661        }
662
663        if (rv != APR_SUCCESS) {
664            srv = rv;
665            /* Return an error but still save the brigade if
666             * ->setaside() is really not implemented. */
667            if (rv != APR_ENOTIMPL) {
668                return rv;
669            }
670        }
671    }
672    APR_BRIGADE_CONCAT(*saveto, *b);
673    return srv;
674}
675
676AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
677                                                void *ctx)
678{
679    ap_filter_t *f = ctx;
680    apr_status_t rv;
681
682    rv = ap_pass_brigade(f, bb);
683
684    /* Before invocation of the flush callback, apr_brigade_write et
685     * al may place transient buckets in the brigade, which will fall
686     * out of scope after returning.  Empty the brigade here, to avoid
687     * issues with leaving such buckets in the brigade if some filter
688     * fails and leaves a non-empty brigade. */
689    apr_brigade_cleanup(bb);
690
691    return rv;
692}
693
694AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
695{
696    apr_bucket *b;
697
698    b = apr_bucket_flush_create(f->c->bucket_alloc);
699    APR_BRIGADE_INSERT_TAIL(bb, b);
700    return ap_pass_brigade(f, bb);
701}
702
703AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
704                                            apr_bucket_brigade *bb, ...)
705{
706    va_list args;
707    apr_status_t rv;
708
709    va_start(args, bb);
710    rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
711    va_end(args);
712    return rv;
713}
714
715AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
716                                           apr_bucket_brigade *bb,
717                                           const char *fmt,
718                                           ...)
719{
720    va_list args;
721    apr_status_t rv;
722
723    va_start(args, fmt);
724    rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
725    va_end(args);
726    return rv;
727}
728AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
729{
730    f->frec->proto_flags = flags ;
731}
732