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 ®istered_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 ®istered_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