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/* HTTP routines for Apache proxy */ 18 19#include "mod_proxy.h" 20#include "ap_regex.h" 21 22module AP_MODULE_DECLARE_DATA proxy_http_module; 23 24static int (*ap_proxy_clear_connection_fn)(request_rec *r, apr_table_t *headers) = 25 NULL; 26 27static apr_status_t ap_proxy_http_cleanup(const char *scheme, 28 request_rec *r, 29 proxy_conn_rec *backend); 30 31/* 32 * Canonicalise http-like URLs. 33 * scheme is the scheme for the URL 34 * url is the URL starting with the first '/' 35 * def_port is the default port for this scheme. 36 */ 37static int proxy_http_canon(request_rec *r, char *url) 38{ 39 char *host, *path, sport[7]; 40 char *search = NULL; 41 const char *err; 42 const char *scheme; 43 apr_port_t port, def_port; 44 45 /* ap_port_of_scheme() */ 46 if (strncasecmp(url, "http:", 5) == 0) { 47 url += 5; 48 scheme = "http"; 49 } 50 else if (strncasecmp(url, "https:", 6) == 0) { 51 url += 6; 52 scheme = "https"; 53 } 54 else { 55 return DECLINED; 56 } 57 port = def_port = ap_proxy_port_of_scheme(scheme); 58 59 ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, 60 "HTTP: canonicalising URL %s", url); 61 62 /* do syntatic check. 63 * We break the URL into host, port, path, search 64 */ 65 err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); 66 if (err) { 67 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01083) 68 "error parsing URL %s: %s", url, err); 69 return HTTP_BAD_REQUEST; 70 } 71 72 /* 73 * now parse path/search args, according to rfc1738: 74 * process the path. 75 * 76 * In a reverse proxy, our URL has been processed, so canonicalise 77 * unless proxy-nocanon is set to say it's raw 78 * In a forward proxy, we have and MUST NOT MANGLE the original. 79 */ 80 switch (r->proxyreq) { 81 default: /* wtf are we doing here? */ 82 case PROXYREQ_REVERSE: 83 if (apr_table_get(r->notes, "proxy-nocanon")) { 84 path = url; /* this is the raw path */ 85 } 86 else { 87 path = ap_proxy_canonenc(r->pool, url, strlen(url), 88 enc_path, 0, r->proxyreq); 89 search = r->args; 90 } 91 break; 92 case PROXYREQ_PROXY: 93 path = url; 94 break; 95 } 96 97 if (path == NULL) 98 return HTTP_BAD_REQUEST; 99 100 if (port != def_port) 101 apr_snprintf(sport, sizeof(sport), ":%d", port); 102 else 103 sport[0] = '\0'; 104 105 if (ap_strchr_c(host, ':')) { /* if literal IPv6 address */ 106 host = apr_pstrcat(r->pool, "[", host, "]", NULL); 107 } 108 r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, 109 "/", path, (search) ? "?" : "", (search) ? search : "", NULL); 110 return OK; 111} 112 113/* Clear all connection-based headers from the incoming headers table */ 114typedef struct header_dptr { 115 apr_pool_t *pool; 116 apr_table_t *table; 117 apr_time_t time; 118} header_dptr; 119static ap_regex_t *warn_rx; 120static int clean_warning_headers(void *data, const char *key, const char *val) 121{ 122 apr_table_t *headers = ((header_dptr*)data)->table; 123 apr_pool_t *pool = ((header_dptr*)data)->pool; 124 char *warning; 125 char *date; 126 apr_time_t warn_time; 127 const int nmatch = 3; 128 ap_regmatch_t pmatch[3]; 129 130 if (headers == NULL) { 131 ((header_dptr*)data)->table = headers = apr_table_make(pool, 2); 132 } 133/* 134 * Parse this, suckers! 135 * 136 * Warning = "Warning" ":" 1#warning-value 137 * 138 * warning-value = warn-code SP warn-agent SP warn-text 139 * [SP warn-date] 140 * 141 * warn-code = 3DIGIT 142 * warn-agent = ( host [ ":" port ] ) | pseudonym 143 * ; the name or pseudonym of the server adding 144 * ; the Warning header, for use in debugging 145 * warn-text = quoted-string 146 * warn-date = <"> HTTP-date <"> 147 * 148 * Buggrit, use a bloomin' regexp! 149 * (\d{3}\s+\S+\s+\".*?\"(\s+\"(.*?)\")?) --> whole in $1, date in $3 150 */ 151 while (!ap_regexec(warn_rx, val, nmatch, pmatch, 0)) { 152 warning = apr_pstrndup(pool, val+pmatch[0].rm_so, 153 pmatch[0].rm_eo - pmatch[0].rm_so); 154 warn_time = 0; 155 if (pmatch[2].rm_eo > pmatch[2].rm_so) { 156 /* OK, we have a date here */ 157 date = apr_pstrndup(pool, val+pmatch[2].rm_so, 158 pmatch[2].rm_eo - pmatch[2].rm_so); 159 warn_time = apr_date_parse_http(date); 160 } 161 if (!warn_time || (warn_time == ((header_dptr*)data)->time)) { 162 apr_table_addn(headers, key, warning); 163 } 164 val += pmatch[0].rm_eo; 165 } 166 return 1; 167} 168static apr_table_t *ap_proxy_clean_warnings(apr_pool_t *p, apr_table_t *headers) 169{ 170 header_dptr x; 171 x.pool = p; 172 x.table = NULL; 173 x.time = apr_date_parse_http(apr_table_get(headers, "Date")); 174 apr_table_do(clean_warning_headers, &x, headers, "Warning", NULL); 175 if (x.table != NULL) { 176 apr_table_unset(headers, "Warning"); 177 return apr_table_overlay(p, headers, x.table); 178 } 179 else { 180 return headers; 181 } 182} 183 184static void add_te_chunked(apr_pool_t *p, 185 apr_bucket_alloc_t *bucket_alloc, 186 apr_bucket_brigade *header_brigade) 187{ 188 apr_bucket *e; 189 char *buf; 190 const char te_hdr[] = "Transfer-Encoding: chunked" CRLF; 191 192 buf = apr_pmemdup(p, te_hdr, sizeof(te_hdr)-1); 193 ap_xlate_proto_to_ascii(buf, sizeof(te_hdr)-1); 194 195 e = apr_bucket_pool_create(buf, sizeof(te_hdr)-1, p, bucket_alloc); 196 APR_BRIGADE_INSERT_TAIL(header_brigade, e); 197} 198 199static void add_cl(apr_pool_t *p, 200 apr_bucket_alloc_t *bucket_alloc, 201 apr_bucket_brigade *header_brigade, 202 const char *cl_val) 203{ 204 apr_bucket *e; 205 char *buf; 206 207 buf = apr_pstrcat(p, "Content-Length: ", 208 cl_val, 209 CRLF, 210 NULL); 211 ap_xlate_proto_to_ascii(buf, strlen(buf)); 212 e = apr_bucket_pool_create(buf, strlen(buf), p, bucket_alloc); 213 APR_BRIGADE_INSERT_TAIL(header_brigade, e); 214} 215 216#define ASCII_CRLF "\015\012" 217#define ASCII_ZERO "\060" 218 219static void terminate_headers(apr_bucket_alloc_t *bucket_alloc, 220 apr_bucket_brigade *header_brigade) 221{ 222 apr_bucket *e; 223 224 /* add empty line at the end of the headers */ 225 e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); 226 APR_BRIGADE_INSERT_TAIL(header_brigade, e); 227} 228 229 230#define MAX_MEM_SPOOL 16384 231 232static int stream_reqbody_chunked(apr_pool_t *p, 233 request_rec *r, 234 proxy_conn_rec *p_conn, 235 conn_rec *origin, 236 apr_bucket_brigade *header_brigade, 237 apr_bucket_brigade *input_brigade) 238{ 239 int seen_eos = 0, rv = OK; 240 apr_size_t hdr_len; 241 apr_off_t bytes; 242 apr_status_t status; 243 apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc; 244 apr_bucket_brigade *bb; 245 apr_bucket *e; 246 247 add_te_chunked(p, bucket_alloc, header_brigade); 248 terminate_headers(bucket_alloc, header_brigade); 249 250 while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) 251 { 252 char chunk_hdr[20]; /* must be here due to transient bucket. */ 253 254 /* If this brigade contains EOS, either stop or remove it. */ 255 if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { 256 seen_eos = 1; 257 258 /* We can't pass this EOS to the output_filters. */ 259 e = APR_BRIGADE_LAST(input_brigade); 260 apr_bucket_delete(e); 261 } 262 263 apr_brigade_length(input_brigade, 1, &bytes); 264 265 hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr), 266 "%" APR_UINT64_T_HEX_FMT CRLF, 267 (apr_uint64_t)bytes); 268 269 ap_xlate_proto_to_ascii(chunk_hdr, hdr_len); 270 e = apr_bucket_transient_create(chunk_hdr, hdr_len, 271 bucket_alloc); 272 APR_BRIGADE_INSERT_HEAD(input_brigade, e); 273 274 /* 275 * Append the end-of-chunk CRLF 276 */ 277 e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); 278 APR_BRIGADE_INSERT_TAIL(input_brigade, e); 279 280 if (header_brigade) { 281 /* we never sent the header brigade, so go ahead and 282 * take care of that now 283 */ 284 bb = header_brigade; 285 286 /* 287 * Save input_brigade in bb brigade. (At least) in the SSL case 288 * input_brigade contains transient buckets whose data would get 289 * overwritten during the next call of ap_get_brigade in the loop. 290 * ap_save_brigade ensures these buckets to be set aside. 291 * Calling ap_save_brigade with NULL as filter is OK, because 292 * bb brigade already has been created and does not need to get 293 * created by ap_save_brigade. 294 */ 295 status = ap_save_brigade(NULL, &bb, &input_brigade, p); 296 if (status != APR_SUCCESS) { 297 return HTTP_INTERNAL_SERVER_ERROR; 298 } 299 300 header_brigade = NULL; 301 } 302 else { 303 bb = input_brigade; 304 } 305 306 /* The request is flushed below this loop with chunk EOS header */ 307 rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, 0); 308 if (rv != OK) { 309 return rv; 310 } 311 312 if (seen_eos) { 313 break; 314 } 315 316 status = ap_get_brigade(r->input_filters, input_brigade, 317 AP_MODE_READBYTES, APR_BLOCK_READ, 318 HUGE_STRING_LEN); 319 320 if (status != APR_SUCCESS) { 321 conn_rec *c = r->connection; 322 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02608) 323 "read request body failed to %pI (%s)" 324 " from %s (%s)", p_conn->addr, 325 p_conn->hostname ? p_conn->hostname: "", 326 c->client_ip, c->remote_host ? c->remote_host: ""); 327 return HTTP_BAD_REQUEST; 328 } 329 } 330 331 if (header_brigade) { 332 /* we never sent the header brigade because there was no request body; 333 * send it now 334 */ 335 bb = header_brigade; 336 } 337 else { 338 if (!APR_BRIGADE_EMPTY(input_brigade)) { 339 /* input brigade still has an EOS which we can't pass to the output_filters. */ 340 e = APR_BRIGADE_LAST(input_brigade); 341 AP_DEBUG_ASSERT(APR_BUCKET_IS_EOS(e)); 342 apr_bucket_delete(e); 343 } 344 bb = input_brigade; 345 } 346 347 e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF 348 /* <trailers> */ 349 ASCII_CRLF, 350 5, bucket_alloc); 351 APR_BRIGADE_INSERT_TAIL(bb, e); 352 353 if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) { 354 e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); 355 APR_BRIGADE_INSERT_TAIL(bb, e); 356 } 357 358 /* Now we have headers-only, or the chunk EOS mark; flush it */ 359 rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1); 360 return rv; 361} 362 363static int stream_reqbody_cl(apr_pool_t *p, 364 request_rec *r, 365 proxy_conn_rec *p_conn, 366 conn_rec *origin, 367 apr_bucket_brigade *header_brigade, 368 apr_bucket_brigade *input_brigade, 369 char *old_cl_val) 370{ 371 int seen_eos = 0, rv = 0; 372 apr_status_t status = APR_SUCCESS; 373 apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc; 374 apr_bucket_brigade *bb; 375 apr_bucket *e; 376 apr_off_t cl_val = 0; 377 apr_off_t bytes; 378 apr_off_t bytes_streamed = 0; 379 380 if (old_cl_val) { 381 char *endstr; 382 383 add_cl(p, bucket_alloc, header_brigade, old_cl_val); 384 status = apr_strtoff(&cl_val, old_cl_val, &endstr, 10); 385 386 if (status || *endstr || endstr == old_cl_val || cl_val < 0) { 387 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01085) 388 "could not parse request Content-Length (%s)", 389 old_cl_val); 390 return HTTP_BAD_REQUEST; 391 } 392 } 393 terminate_headers(bucket_alloc, header_brigade); 394 395 while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) 396 { 397 apr_brigade_length(input_brigade, 1, &bytes); 398 bytes_streamed += bytes; 399 400 /* If this brigade contains EOS, either stop or remove it. */ 401 if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { 402 seen_eos = 1; 403 404 /* We can't pass this EOS to the output_filters. */ 405 e = APR_BRIGADE_LAST(input_brigade); 406 apr_bucket_delete(e); 407 408 if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) { 409 e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); 410 APR_BRIGADE_INSERT_TAIL(input_brigade, e); 411 } 412 } 413 414 /* C-L < bytes streamed?!? 415 * We will error out after the body is completely 416 * consumed, but we can't stream more bytes at the 417 * back end since they would in part be interpreted 418 * as another request! If nothing is sent, then 419 * just send nothing. 420 * 421 * Prevents HTTP Response Splitting. 422 */ 423 if (bytes_streamed > cl_val) { 424 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01086) 425 "read more bytes of request body than expected " 426 "(got %" APR_OFF_T_FMT ", expected %" APR_OFF_T_FMT ")", 427 bytes_streamed, cl_val); 428 return HTTP_INTERNAL_SERVER_ERROR; 429 } 430 431 if (header_brigade) { 432 /* we never sent the header brigade, so go ahead and 433 * take care of that now 434 */ 435 bb = header_brigade; 436 437 /* 438 * Save input_brigade in bb brigade. (At least) in the SSL case 439 * input_brigade contains transient buckets whose data would get 440 * overwritten during the next call of ap_get_brigade in the loop. 441 * ap_save_brigade ensures these buckets to be set aside. 442 * Calling ap_save_brigade with NULL as filter is OK, because 443 * bb brigade already has been created and does not need to get 444 * created by ap_save_brigade. 445 */ 446 status = ap_save_brigade(NULL, &bb, &input_brigade, p); 447 if (status != APR_SUCCESS) { 448 return HTTP_INTERNAL_SERVER_ERROR; 449 } 450 451 header_brigade = NULL; 452 } 453 else { 454 bb = input_brigade; 455 } 456 457 /* Once we hit EOS, we are ready to flush. */ 458 rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, seen_eos); 459 if (rv != OK) { 460 return rv ; 461 } 462 463 if (seen_eos) { 464 break; 465 } 466 467 status = ap_get_brigade(r->input_filters, input_brigade, 468 AP_MODE_READBYTES, APR_BLOCK_READ, 469 HUGE_STRING_LEN); 470 471 if (status != APR_SUCCESS) { 472 conn_rec *c = r->connection; 473 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02609) 474 "read request body failed to %pI (%s)" 475 " from %s (%s)", p_conn->addr, 476 p_conn->hostname ? p_conn->hostname: "", 477 c->client_ip, c->remote_host ? c->remote_host: ""); 478 return HTTP_BAD_REQUEST; 479 } 480 } 481 482 if (bytes_streamed != cl_val) { 483 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01087) 484 "client %s given Content-Length did not match" 485 " number of body bytes read", r->connection->client_ip); 486 return HTTP_BAD_REQUEST; 487 } 488 489 if (header_brigade) { 490 /* we never sent the header brigade since there was no request 491 * body; send it now with the flush flag 492 */ 493 bb = header_brigade; 494 return(ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1)); 495 } 496 497 return OK; 498} 499 500static int spool_reqbody_cl(apr_pool_t *p, 501 request_rec *r, 502 proxy_conn_rec *p_conn, 503 conn_rec *origin, 504 apr_bucket_brigade *header_brigade, 505 apr_bucket_brigade *input_brigade, 506 int force_cl) 507{ 508 int seen_eos = 0; 509 apr_status_t status; 510 apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc; 511 apr_bucket_brigade *body_brigade; 512 apr_bucket *e; 513 apr_off_t bytes, bytes_spooled = 0, fsize = 0; 514 apr_file_t *tmpfile = NULL; 515 apr_off_t limit; 516 517 body_brigade = apr_brigade_create(p, bucket_alloc); 518 519 limit = ap_get_limit_req_body(r); 520 521 while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) 522 { 523 /* If this brigade contains EOS, either stop or remove it. */ 524 if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { 525 seen_eos = 1; 526 527 /* We can't pass this EOS to the output_filters. */ 528 e = APR_BRIGADE_LAST(input_brigade); 529 apr_bucket_delete(e); 530 } 531 532 apr_brigade_length(input_brigade, 1, &bytes); 533 534 if (bytes_spooled + bytes > MAX_MEM_SPOOL) { 535 /* 536 * LimitRequestBody does not affect Proxy requests (Should it?). 537 * Let it take effect if we decide to store the body in a 538 * temporary file on disk. 539 */ 540 if (limit && (bytes_spooled + bytes > limit)) { 541 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01088) 542 "Request body is larger than the configured " 543 "limit of %" APR_OFF_T_FMT, limit); 544 return HTTP_REQUEST_ENTITY_TOO_LARGE; 545 } 546 /* can't spool any more in memory; write latest brigade to disk */ 547 if (tmpfile == NULL) { 548 const char *temp_dir; 549 char *template; 550 551 status = apr_temp_dir_get(&temp_dir, p); 552 if (status != APR_SUCCESS) { 553 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01089) 554 "search for temporary directory failed"); 555 return HTTP_INTERNAL_SERVER_ERROR; 556 } 557 apr_filepath_merge(&template, temp_dir, 558 "modproxy.tmp.XXXXXX", 559 APR_FILEPATH_NATIVE, p); 560 status = apr_file_mktemp(&tmpfile, template, 0, p); 561 if (status != APR_SUCCESS) { 562 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01090) 563 "creation of temporary file in directory " 564 "%s failed", temp_dir); 565 return HTTP_INTERNAL_SERVER_ERROR; 566 } 567 } 568 for (e = APR_BRIGADE_FIRST(input_brigade); 569 e != APR_BRIGADE_SENTINEL(input_brigade); 570 e = APR_BUCKET_NEXT(e)) { 571 const char *data; 572 apr_size_t bytes_read, bytes_written; 573 574 apr_bucket_read(e, &data, &bytes_read, APR_BLOCK_READ); 575 status = apr_file_write_full(tmpfile, data, bytes_read, &bytes_written); 576 if (status != APR_SUCCESS) { 577 const char *tmpfile_name; 578 579 if (apr_file_name_get(&tmpfile_name, tmpfile) != APR_SUCCESS) { 580 tmpfile_name = "(unknown)"; 581 } 582 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01091) 583 "write to temporary file %s failed", 584 tmpfile_name); 585 return HTTP_INTERNAL_SERVER_ERROR; 586 } 587 AP_DEBUG_ASSERT(bytes_read == bytes_written); 588 fsize += bytes_written; 589 } 590 apr_brigade_cleanup(input_brigade); 591 } 592 else { 593 594 /* 595 * Save input_brigade in body_brigade. (At least) in the SSL case 596 * input_brigade contains transient buckets whose data would get 597 * overwritten during the next call of ap_get_brigade in the loop. 598 * ap_save_brigade ensures these buckets to be set aside. 599 * Calling ap_save_brigade with NULL as filter is OK, because 600 * body_brigade already has been created and does not need to get 601 * created by ap_save_brigade. 602 */ 603 status = ap_save_brigade(NULL, &body_brigade, &input_brigade, p); 604 if (status != APR_SUCCESS) { 605 return HTTP_INTERNAL_SERVER_ERROR; 606 } 607 608 } 609 610 bytes_spooled += bytes; 611 612 if (seen_eos) { 613 break; 614 } 615 616 status = ap_get_brigade(r->input_filters, input_brigade, 617 AP_MODE_READBYTES, APR_BLOCK_READ, 618 HUGE_STRING_LEN); 619 620 if (status != APR_SUCCESS) { 621 conn_rec *c = r->connection; 622 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02610) 623 "read request body failed to %pI (%s)" 624 " from %s (%s)", p_conn->addr, 625 p_conn->hostname ? p_conn->hostname: "", 626 c->client_ip, c->remote_host ? c->remote_host: ""); 627 return HTTP_BAD_REQUEST; 628 } 629 } 630 631 if (bytes_spooled || force_cl) { 632 add_cl(p, bucket_alloc, header_brigade, apr_off_t_toa(p, bytes_spooled)); 633 } 634 terminate_headers(bucket_alloc, header_brigade); 635 APR_BRIGADE_CONCAT(header_brigade, body_brigade); 636 if (tmpfile) { 637 apr_brigade_insert_file(header_brigade, tmpfile, 0, fsize, p); 638 } 639 if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) { 640 e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); 641 APR_BRIGADE_INSERT_TAIL(header_brigade, e); 642 } 643 /* This is all a single brigade, pass with flush flagged */ 644 return(ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, header_brigade, 1)); 645} 646 647/* 648 * Transform buckets from one bucket allocator to another one by creating a 649 * transient bucket for each data bucket and let it use the data read from 650 * the old bucket. Metabuckets are transformed by just recreating them. 651 * Attention: Currently only the following bucket types are handled: 652 * 653 * All data buckets 654 * FLUSH 655 * EOS 656 * 657 * If an other bucket type is found its type is logged as a debug message 658 * and APR_EGENERAL is returned. 659 */ 660static apr_status_t proxy_buckets_lifetime_transform(request_rec *r, 661 apr_bucket_brigade *from, apr_bucket_brigade *to) 662{ 663 apr_bucket *e; 664 apr_bucket *new; 665 const char *data; 666 apr_size_t bytes; 667 apr_status_t rv = APR_SUCCESS; 668 669 apr_brigade_cleanup(to); 670 for (e = APR_BRIGADE_FIRST(from); 671 e != APR_BRIGADE_SENTINEL(from); 672 e = APR_BUCKET_NEXT(e)) { 673 if (!APR_BUCKET_IS_METADATA(e)) { 674 apr_bucket_read(e, &data, &bytes, APR_BLOCK_READ); 675 new = apr_bucket_transient_create(data, bytes, r->connection->bucket_alloc); 676 APR_BRIGADE_INSERT_TAIL(to, new); 677 } 678 else if (APR_BUCKET_IS_FLUSH(e)) { 679 new = apr_bucket_flush_create(r->connection->bucket_alloc); 680 APR_BRIGADE_INSERT_TAIL(to, new); 681 } 682 else if (APR_BUCKET_IS_EOS(e)) { 683 new = apr_bucket_eos_create(r->connection->bucket_alloc); 684 APR_BRIGADE_INSERT_TAIL(to, new); 685 } 686 else { 687 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00964) 688 "Unhandled bucket type of type %s in" 689 " proxy_buckets_lifetime_transform", e->type->name); 690 apr_bucket_delete(e); 691 rv = APR_EGENERAL; 692 } 693 } 694 return rv; 695} 696 697static 698int ap_proxy_http_request(apr_pool_t *p, request_rec *r, 699 proxy_conn_rec *p_conn, proxy_worker *worker, 700 proxy_server_conf *conf, 701 apr_uri_t *uri, 702 char *url, char *server_portstr) 703{ 704 conn_rec *c = r->connection; 705 apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc; 706 apr_bucket_brigade *header_brigade; 707 apr_bucket_brigade *input_brigade; 708 apr_bucket_brigade *temp_brigade; 709 apr_bucket *e; 710 char *buf; 711 apr_status_t status; 712 enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED, RB_SPOOL_CL}; 713 enum rb_methods rb_method = RB_INIT; 714 char *old_cl_val = NULL; 715 char *old_te_val = NULL; 716 apr_off_t bytes_read = 0; 717 apr_off_t bytes; 718 int force10, rv; 719 conn_rec *origin = p_conn->connection; 720 721 if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) { 722 if (r->expecting_100) { 723 return HTTP_EXPECTATION_FAILED; 724 } 725 force10 = 1; 726 } else { 727 force10 = 0; 728 } 729 730 header_brigade = apr_brigade_create(p, bucket_alloc); 731 rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn, 732 worker, conf, uri, url, server_portstr, 733 &old_cl_val, &old_te_val); 734 if (rv != OK) { 735 return rv; 736 } 737 738 /* We have headers, let's figure out our request body... */ 739 input_brigade = apr_brigade_create(p, bucket_alloc); 740 741 /* sub-requests never use keepalives, and mustn't pass request bodies. 742 * Because the new logic looks at input_brigade, we will self-terminate 743 * input_brigade and jump past all of the request body logic... 744 * Reading anything with ap_get_brigade is likely to consume the 745 * main request's body or read beyond EOS - which would be unplesant. 746 * 747 * An exception: when a kept_body is present, then subrequest CAN use 748 * pass request bodies, and we DONT skip the body. 749 */ 750 if (!r->kept_body && r->main) { 751 /* XXX: Why DON'T sub-requests use keepalives? */ 752 p_conn->close = 1; 753 if (old_cl_val) { 754 old_cl_val = NULL; 755 apr_table_unset(r->headers_in, "Content-Length"); 756 } 757 if (old_te_val) { 758 old_te_val = NULL; 759 apr_table_unset(r->headers_in, "Transfer-Encoding"); 760 } 761 rb_method = RB_STREAM_CL; 762 e = apr_bucket_eos_create(input_brigade->bucket_alloc); 763 APR_BRIGADE_INSERT_TAIL(input_brigade, e); 764 goto skip_body; 765 } 766 767 /* WE only understand chunked. Other modules might inject 768 * (and therefore, decode) other flavors but we don't know 769 * that the can and have done so unless they they remove 770 * their decoding from the headers_in T-E list. 771 * XXX: Make this extensible, but in doing so, presume the 772 * encoding has been done by the extensions' handler, and 773 * do not modify add_te_chunked's logic 774 */ 775 if (old_te_val && strcasecmp(old_te_val, "chunked") != 0) { 776 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093) 777 "%s Transfer-Encoding is not supported", old_te_val); 778 return HTTP_INTERNAL_SERVER_ERROR; 779 } 780 781 if (old_cl_val && old_te_val) { 782 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01094) 783 "client %s (%s) requested Transfer-Encoding " 784 "chunked body with Content-Length (C-L ignored)", 785 c->client_ip, c->remote_host ? c->remote_host: ""); 786 apr_table_unset(r->headers_in, "Content-Length"); 787 old_cl_val = NULL; 788 origin->keepalive = AP_CONN_CLOSE; 789 p_conn->close = 1; 790 } 791 792 /* Prefetch MAX_MEM_SPOOL bytes 793 * 794 * This helps us avoid any election of C-L v.s. T-E 795 * request bodies, since we are willing to keep in 796 * memory this much data, in any case. This gives 797 * us an instant C-L election if the body is of some 798 * reasonable size. 799 */ 800 temp_brigade = apr_brigade_create(p, bucket_alloc); 801 do { 802 status = ap_get_brigade(r->input_filters, temp_brigade, 803 AP_MODE_READBYTES, APR_BLOCK_READ, 804 MAX_MEM_SPOOL - bytes_read); 805 if (status != APR_SUCCESS) { 806 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01095) 807 "prefetch request body failed to %pI (%s)" 808 " from %s (%s)", 809 p_conn->addr, p_conn->hostname ? p_conn->hostname: "", 810 c->client_ip, c->remote_host ? c->remote_host: ""); 811 return HTTP_BAD_REQUEST; 812 } 813 814 apr_brigade_length(temp_brigade, 1, &bytes); 815 bytes_read += bytes; 816 817 /* 818 * Save temp_brigade in input_brigade. (At least) in the SSL case 819 * temp_brigade contains transient buckets whose data would get 820 * overwritten during the next call of ap_get_brigade in the loop. 821 * ap_save_brigade ensures these buckets to be set aside. 822 * Calling ap_save_brigade with NULL as filter is OK, because 823 * input_brigade already has been created and does not need to get 824 * created by ap_save_brigade. 825 */ 826 status = ap_save_brigade(NULL, &input_brigade, &temp_brigade, p); 827 if (status != APR_SUCCESS) { 828 ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01096) 829 "processing prefetched request body failed" 830 " to %pI (%s) from %s (%s)", 831 p_conn->addr, p_conn->hostname ? p_conn->hostname: "", 832 c->client_ip, c->remote_host ? c->remote_host: ""); 833 return HTTP_INTERNAL_SERVER_ERROR; 834 } 835 836 /* Ensure we don't hit a wall where we have a buffer too small 837 * for ap_get_brigade's filters to fetch us another bucket, 838 * surrender once we hit 80 bytes less than MAX_MEM_SPOOL 839 * (an arbitrary value.) 840 */ 841 } while ((bytes_read < MAX_MEM_SPOOL - 80) 842 && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))); 843 844 /* Use chunked request body encoding or send a content-length body? 845 * 846 * Prefer C-L when: 847 * 848 * We have no request body (handled by RB_STREAM_CL) 849 * 850 * We have a request body length <= MAX_MEM_SPOOL 851 * 852 * The administrator has setenv force-proxy-request-1.0 853 * 854 * The client sent a C-L body, and the administrator has 855 * not setenv proxy-sendchunked or has set setenv proxy-sendcl 856 * 857 * The client sent a T-E body, and the administrator has 858 * setenv proxy-sendcl, and not setenv proxy-sendchunked 859 * 860 * If both proxy-sendcl and proxy-sendchunked are set, the 861 * behavior is the same as if neither were set, large bodies 862 * that can't be read will be forwarded in their original 863 * form of C-L, or T-E. 864 * 865 * To ensure maximum compatibility, setenv proxy-sendcl 866 * To reduce server resource use, setenv proxy-sendchunked 867 * 868 * Then address specific servers with conditional setenv 869 * options to restore the default behavior where desireable. 870 * 871 * We have to compute content length by reading the entire request 872 * body; if request body is not small, we'll spool the remaining 873 * input to a temporary file. Chunked is always preferable. 874 * 875 * We can only trust the client-provided C-L if the T-E header 876 * is absent, and the filters are unchanged (the body won't 877 * be resized by another content filter). 878 */ 879 if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { 880 /* The whole thing fit, so our decision is trivial, use 881 * the filtered bytes read from the client for the request 882 * body Content-Length. 883 * 884 * If we expected no body, and read no body, do not set 885 * the Content-Length. 886 */ 887 if (old_cl_val || old_te_val || bytes_read) { 888 old_cl_val = apr_off_t_toa(r->pool, bytes_read); 889 } 890 rb_method = RB_STREAM_CL; 891 } 892 else if (old_te_val) { 893 if (force10 894 || (apr_table_get(r->subprocess_env, "proxy-sendcl") 895 && !apr_table_get(r->subprocess_env, "proxy-sendchunks") 896 && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) { 897 rb_method = RB_SPOOL_CL; 898 } 899 else { 900 rb_method = RB_STREAM_CHUNKED; 901 } 902 } 903 else if (old_cl_val) { 904 if (r->input_filters == r->proto_input_filters) { 905 rb_method = RB_STREAM_CL; 906 } 907 else if (!force10 908 && (apr_table_get(r->subprocess_env, "proxy-sendchunks") 909 || apr_table_get(r->subprocess_env, "proxy-sendchunked")) 910 && !apr_table_get(r->subprocess_env, "proxy-sendcl")) { 911 rb_method = RB_STREAM_CHUNKED; 912 } 913 else { 914 rb_method = RB_SPOOL_CL; 915 } 916 } 917 else { 918 /* This is an appropriate default; very efficient for no-body 919 * requests, and has the behavior that it will not add any C-L 920 * when the old_cl_val is NULL. 921 */ 922 rb_method = RB_SPOOL_CL; 923 } 924 925/* Yes I hate gotos. This is the subrequest shortcut */ 926skip_body: 927 /* 928 * Handle Connection: header if we do HTTP/1.1 request: 929 * If we plan to close the backend connection sent Connection: close 930 * otherwise sent Connection: Keep-Alive. 931 */ 932 if (!force10) { 933 if (p_conn->close) { 934 buf = apr_pstrdup(p, "Connection: close" CRLF); 935 } 936 else { 937 buf = apr_pstrdup(p, "Connection: Keep-Alive" CRLF); 938 } 939 ap_xlate_proto_to_ascii(buf, strlen(buf)); 940 e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc); 941 APR_BRIGADE_INSERT_TAIL(header_brigade, e); 942 } 943 944 /* send the request body, if any. */ 945 switch(rb_method) { 946 case RB_STREAM_CHUNKED: 947 rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade, 948 input_brigade); 949 break; 950 case RB_STREAM_CL: 951 rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade, 952 input_brigade, old_cl_val); 953 break; 954 case RB_SPOOL_CL: 955 rv = spool_reqbody_cl(p, r, p_conn, origin, header_brigade, 956 input_brigade, (old_cl_val != NULL) 957 || (old_te_val != NULL) 958 || (bytes_read > 0)); 959 break; 960 default: 961 /* shouldn't be possible */ 962 rv = HTTP_INTERNAL_SERVER_ERROR ; 963 break; 964 } 965 966 if (rv != OK) { 967 /* apr_status_t value has been logged in lower level method */ 968 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01097) 969 "pass request body failed to %pI (%s) from %s (%s)", 970 p_conn->addr, p_conn->hostname ? p_conn->hostname: "", 971 c->client_ip, c->remote_host ? c->remote_host: ""); 972 return rv; 973 } 974 975 return OK; 976} 977 978/* 979 * If the date is a valid RFC 850 date or asctime() date, then it 980 * is converted to the RFC 1123 format. 981 */ 982static const char *date_canon(apr_pool_t *p, const char *date) 983{ 984 apr_status_t rv; 985 char* ndate; 986 987 apr_time_t time = apr_date_parse_http(date); 988 if (!time) { 989 return date; 990 } 991 992 ndate = apr_palloc(p, APR_RFC822_DATE_LEN); 993 rv = apr_rfc822_date(ndate, time); 994 if (rv != APR_SUCCESS) { 995 return date; 996 } 997 998 return ndate; 999} 1000 1001static request_rec *make_fake_req(conn_rec *c, request_rec *r) 1002{ 1003 apr_pool_t *pool; 1004 request_rec *rp; 1005 1006 apr_pool_create(&pool, c->pool); 1007 1008 rp = apr_pcalloc(pool, sizeof(*r)); 1009 1010 rp->pool = pool; 1011 rp->status = HTTP_OK; 1012 1013 rp->headers_in = apr_table_make(pool, 50); 1014 rp->subprocess_env = apr_table_make(pool, 50); 1015 rp->headers_out = apr_table_make(pool, 12); 1016 rp->err_headers_out = apr_table_make(pool, 5); 1017 rp->notes = apr_table_make(pool, 5); 1018 1019 rp->server = r->server; 1020 rp->log = r->log; 1021 rp->proxyreq = r->proxyreq; 1022 rp->request_time = r->request_time; 1023 rp->connection = c; 1024 rp->output_filters = c->output_filters; 1025 rp->input_filters = c->input_filters; 1026 rp->proto_output_filters = c->output_filters; 1027 rp->proto_input_filters = c->input_filters; 1028 rp->useragent_ip = c->client_ip; 1029 rp->useragent_addr = c->client_addr; 1030 1031 rp->request_config = ap_create_request_config(pool); 1032 proxy_run_create_req(r, rp); 1033 1034 return rp; 1035} 1036 1037static void process_proxy_header(request_rec *r, proxy_dir_conf *c, 1038 const char *key, const char *value) 1039{ 1040 static const char *date_hdrs[] 1041 = { "Date", "Expires", "Last-Modified", NULL }; 1042 static const struct { 1043 const char *name; 1044 ap_proxy_header_reverse_map_fn func; 1045 } transform_hdrs[] = { 1046 { "Location", ap_proxy_location_reverse_map }, 1047 { "Content-Location", ap_proxy_location_reverse_map }, 1048 { "URI", ap_proxy_location_reverse_map }, 1049 { "Destination", ap_proxy_location_reverse_map }, 1050 { "Set-Cookie", ap_proxy_cookie_reverse_map }, 1051 { NULL, NULL } 1052 }; 1053 int i; 1054 for (i = 0; date_hdrs[i]; ++i) { 1055 if (!strcasecmp(date_hdrs[i], key)) { 1056 apr_table_add(r->headers_out, key, 1057 date_canon(r->pool, value)); 1058 return; 1059 } 1060 } 1061 for (i = 0; transform_hdrs[i].name; ++i) { 1062 if (!strcasecmp(transform_hdrs[i].name, key)) { 1063 apr_table_add(r->headers_out, key, 1064 (*transform_hdrs[i].func)(r, c, value)); 1065 return; 1066 } 1067 } 1068 apr_table_add(r->headers_out, key, value); 1069 return; 1070} 1071 1072/* 1073 * Note: pread_len is the length of the response that we've mistakenly 1074 * read (assuming that we don't consider that an error via 1075 * ProxyBadHeader StartBody). This depends on buffer actually being 1076 * local storage to the calling code in order for pread_len to make 1077 * any sense at all, since we depend on buffer still containing 1078 * what was read by ap_getline() upon return. 1079 */ 1080static void ap_proxy_read_headers(request_rec *r, request_rec *rr, 1081 char *buffer, int size, 1082 conn_rec *c, int *pread_len) 1083{ 1084 int len; 1085 char *value, *end; 1086 char field[MAX_STRING_LEN]; 1087 int saw_headers = 0; 1088 void *sconf = r->server->module_config; 1089 proxy_server_conf *psc; 1090 proxy_dir_conf *dconf; 1091 1092 dconf = ap_get_module_config(r->per_dir_config, &proxy_module); 1093 psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); 1094 1095 r->headers_out = apr_table_make(r->pool, 20); 1096 *pread_len = 0; 1097 1098 /* 1099 * Read header lines until we get the empty separator line, a read error, 1100 * the connection closes (EOF), or we timeout. 1101 */ 1102 ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, 1103 "Headers received from backend:"); 1104 while ((len = ap_getline(buffer, size, rr, 1)) > 0) { 1105 ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "%s", buffer); 1106 1107 if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */ 1108 1109 /* We may encounter invalid headers, usually from buggy 1110 * MS IIS servers, so we need to determine just how to handle 1111 * them. We can either ignore them, assume that they mark the 1112 * start-of-body (eg: a missing CRLF) or (the default) mark 1113 * the headers as totally bogus and return a 500. The sole 1114 * exception is an extra "HTTP/1.0 200, OK" line sprinkled 1115 * in between the usual MIME headers, which is a favorite 1116 * IIS bug. 1117 */ 1118 /* XXX: The mask check is buggy if we ever see an HTTP/1.10 */ 1119 1120 if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) { 1121 if (psc->badopt == bad_error) { 1122 /* Nope, it wasn't even an extra HTTP header. Give up. */ 1123 r->headers_out = NULL; 1124 return ; 1125 } 1126 else if (psc->badopt == bad_body) { 1127 /* if we've already started loading headers_out, then 1128 * return what we've accumulated so far, in the hopes 1129 * that they are useful; also note that we likely pre-read 1130 * the first line of the response. 1131 */ 1132 if (saw_headers) { 1133 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01098) 1134 "Starting body due to bogus non-header " 1135 "in headers returned by %s (%s)", 1136 r->uri, r->method); 1137 *pread_len = len; 1138 return ; 1139 } else { 1140 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01099) 1141 "No HTTP headers returned by %s (%s)", 1142 r->uri, r->method); 1143 return ; 1144 } 1145 } 1146 } 1147 /* this is the psc->badopt == bad_ignore case */ 1148 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01100) 1149 "Ignoring bogus HTTP header returned by %s (%s)", 1150 r->uri, r->method); 1151 continue; 1152 } 1153 1154 *value = '\0'; 1155 ++value; 1156 /* XXX: RFC2068 defines only SP and HT as whitespace, this test is 1157 * wrong... and so are many others probably. 1158 */ 1159 while (apr_isspace(*value)) 1160 ++value; /* Skip to start of value */ 1161 1162 /* should strip trailing whitespace as well */ 1163 for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); -- 1164end) 1165 *end = '\0'; 1166 1167 /* make sure we add so as not to destroy duplicated headers 1168 * Modify headers requiring canonicalisation and/or affected 1169 * by ProxyPassReverse and family with process_proxy_header 1170 */ 1171 process_proxy_header(r, dconf, buffer, value) ; 1172 saw_headers = 1; 1173 1174 /* the header was too long; at the least we should skip extra data */ 1175 if (len >= size - 1) { 1176 while ((len = ap_getline(field, MAX_STRING_LEN, rr, 1)) 1177 >= MAX_STRING_LEN - 1) { 1178 /* soak up the extra data */ 1179 } 1180 if (len == 0) /* time to exit the larger loop as well */ 1181 break; 1182 } 1183 } 1184} 1185 1186 1187 1188static int addit_dammit(void *v, const char *key, const char *val) 1189{ 1190 apr_table_addn(v, key, val); 1191 return 1; 1192} 1193 1194static 1195apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec *r, 1196 int fold, int *writen) 1197{ 1198 char *tmp_s = s; 1199 apr_status_t rv; 1200 apr_size_t len; 1201 1202 rv = ap_rgetline(&tmp_s, n, &len, r, fold, bb); 1203 apr_brigade_cleanup(bb); 1204 1205 if (rv == APR_SUCCESS) { 1206 *writen = (int) len; 1207 } else if (APR_STATUS_IS_ENOSPC(rv)) { 1208 *writen = n; 1209 } else { 1210 *writen = -1; 1211 } 1212 1213 return rv; 1214} 1215 1216/* 1217 * Limit the number of interim responses we sent back to the client. Otherwise 1218 * we suffer from a memory build up. Besides there is NO sense in sending back 1219 * an unlimited number of interim responses to the client. Thus if we cross 1220 * this limit send back a 502 (Bad Gateway). 1221 */ 1222#ifndef AP_MAX_INTERIM_RESPONSES 1223#define AP_MAX_INTERIM_RESPONSES 10 1224#endif 1225 1226static 1227apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, 1228 proxy_conn_rec **backend_ptr, 1229 proxy_worker *worker, 1230 proxy_server_conf *conf, 1231 char *server_portstr) { 1232 conn_rec *c = r->connection; 1233 char buffer[HUGE_STRING_LEN]; 1234 const char *buf; 1235 char keepchar; 1236 apr_bucket *e; 1237 apr_bucket_brigade *bb, *tmp_bb; 1238 apr_bucket_brigade *pass_bb; 1239 int len, backasswards; 1240 int interim_response = 0; /* non-zero whilst interim 1xx responses 1241 * are being read. */ 1242 int pread_len = 0; 1243 apr_table_t *save_table; 1244 int backend_broke = 0; 1245 static const char *hop_by_hop_hdrs[] = 1246 {"Keep-Alive", "Proxy-Authenticate", "TE", "Trailer", "Upgrade", NULL}; 1247 int i; 1248 const char *te = NULL; 1249 int original_status = r->status; 1250 int proxy_status = OK; 1251 const char *original_status_line = r->status_line; 1252 const char *proxy_status_line = NULL; 1253 proxy_conn_rec *backend = *backend_ptr; 1254 conn_rec *origin = backend->connection; 1255 apr_interval_time_t old_timeout = 0; 1256 proxy_dir_conf *dconf; 1257 int do_100_continue; 1258 1259 dconf = ap_get_module_config(r->per_dir_config, &proxy_module); 1260 1261 do_100_continue = (worker->s->ping_timeout_set 1262 && ap_request_has_body(r) 1263 && (PROXYREQ_REVERSE == r->proxyreq) 1264 && !(apr_table_get(r->subprocess_env, "force-proxy-request-1.0"))); 1265 1266 bb = apr_brigade_create(p, c->bucket_alloc); 1267 pass_bb = apr_brigade_create(p, c->bucket_alloc); 1268 1269 /* Setup for 100-Continue timeout if appropriate */ 1270 if (do_100_continue) { 1271 apr_socket_timeout_get(backend->sock, &old_timeout); 1272 if (worker->s->ping_timeout != old_timeout) { 1273 apr_status_t rc; 1274 rc = apr_socket_timeout_set(backend->sock, worker->s->ping_timeout); 1275 if (rc != APR_SUCCESS) { 1276 ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, APLOGNO(01101) 1277 "could not set 100-Continue timeout"); 1278 } 1279 } 1280 } 1281 1282 /* Get response from the remote server, and pass it up the 1283 * filter chain 1284 */ 1285 1286 backend->r = make_fake_req(origin, r); 1287 /* In case anyone needs to know, this is a fake request that is really a 1288 * response. 1289 */ 1290 backend->r->proxyreq = PROXYREQ_RESPONSE; 1291 apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu", 1292 origin->local_addr->port)); 1293 tmp_bb = apr_brigade_create(p, c->bucket_alloc); 1294 do { 1295 apr_status_t rc; 1296 1297 apr_brigade_cleanup(bb); 1298 1299 rc = ap_proxygetline(tmp_bb, buffer, sizeof(buffer), backend->r, 0, &len); 1300 if (len == 0) { 1301 /* handle one potential stray CRLF */ 1302 rc = ap_proxygetline(tmp_bb, buffer, sizeof(buffer), backend->r, 0, &len); 1303 } 1304 if (len <= 0) { 1305 ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, APLOGNO(01102) 1306 "error reading status line from remote " 1307 "server %s:%d", backend->hostname, backend->port); 1308 if (APR_STATUS_IS_TIMEUP(rc)) { 1309 apr_table_set(r->notes, "proxy_timedout", "1"); 1310 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01103) "read timeout"); 1311 if (do_100_continue) { 1312 return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, "Timeout on 100-Continue"); 1313 } 1314 } 1315 /* 1316 * If we are a reverse proxy request shutdown the connection 1317 * WITHOUT ANY response to trigger a retry by the client 1318 * if allowed (as for idempotent requests). 1319 * BUT currently we should not do this if the request is the 1320 * first request on a keepalive connection as browsers like 1321 * seamonkey only display an empty page in this case and do 1322 * not do a retry. We should also not do this on a 1323 * connection which times out; instead handle as 1324 * we normally would handle timeouts 1325 */ 1326 if (r->proxyreq == PROXYREQ_REVERSE && c->keepalives && 1327 !APR_STATUS_IS_TIMEUP(rc)) { 1328 apr_bucket *eos; 1329 1330 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01104) 1331 "Closing connection to client because" 1332 " reading from backend server %s:%d failed." 1333 " Number of keepalives %i", backend->hostname, 1334 backend->port, c->keepalives); 1335 ap_proxy_backend_broke(r, bb); 1336 /* 1337 * Add an EOC bucket to signal the ap_http_header_filter 1338 * that it should get out of our way, BUT ensure that the 1339 * EOC bucket is inserted BEFORE an EOS bucket in bb as 1340 * some resource filters like mod_deflate pass everything 1341 * up to the EOS down the chain immediately and sent the 1342 * remainder of the brigade later (or even never). But in 1343 * this case the ap_http_header_filter does not get out of 1344 * our way soon enough. 1345 */ 1346 e = ap_bucket_eoc_create(c->bucket_alloc); 1347 eos = APR_BRIGADE_LAST(bb); 1348 while ((APR_BRIGADE_SENTINEL(bb) != eos) 1349 && !APR_BUCKET_IS_EOS(eos)) { 1350 eos = APR_BUCKET_PREV(eos); 1351 } 1352 if (eos == APR_BRIGADE_SENTINEL(bb)) { 1353 APR_BRIGADE_INSERT_TAIL(bb, e); 1354 } 1355 else { 1356 APR_BUCKET_INSERT_BEFORE(eos, e); 1357 } 1358 ap_pass_brigade(r->output_filters, bb); 1359 /* Mark the backend connection for closing */ 1360 backend->close = 1; 1361 /* Need to return OK to avoid sending an error message */ 1362 return OK; 1363 } 1364 else if (!c->keepalives) { 1365 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01105) 1366 "NOT Closing connection to client" 1367 " although reading from backend server %s:%d" 1368 " failed.", 1369 backend->hostname, backend->port); 1370 } 1371 return ap_proxyerror(r, HTTP_BAD_GATEWAY, 1372 "Error reading from remote server"); 1373 } 1374 /* XXX: Is this a real headers length send from remote? */ 1375 backend->worker->s->read += len; 1376 1377 /* Is it an HTTP/1 response? 1378 * This is buggy if we ever see an HTTP/1.10 1379 */ 1380 if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) { 1381 int major, minor; 1382 1383 major = buffer[5] - '0'; 1384 minor = buffer[7] - '0'; 1385 1386 /* If not an HTTP/1 message or 1387 * if the status line was > 8192 bytes 1388 */ 1389 if ((major != 1) || (len >= sizeof(buffer)-1)) { 1390 return ap_proxyerror(r, HTTP_BAD_GATEWAY, 1391 apr_pstrcat(p, "Corrupt status line returned by remote " 1392 "server: ", buffer, NULL)); 1393 } 1394 backasswards = 0; 1395 1396 keepchar = buffer[12]; 1397 buffer[12] = '\0'; 1398 proxy_status = atoi(&buffer[9]); 1399 apr_table_setn(r->notes, "proxy-status", 1400 apr_pstrdup(r->pool, &buffer[9])); 1401 1402 if (keepchar != '\0') { 1403 buffer[12] = keepchar; 1404 } else { 1405 /* 2616 requires the space in Status-Line; the origin 1406 * server may have sent one but ap_rgetline_core will 1407 * have stripped it. */ 1408 buffer[12] = ' '; 1409 buffer[13] = '\0'; 1410 } 1411 proxy_status_line = apr_pstrdup(p, &buffer[9]); 1412 1413 /* The status out of the front is the same as the status coming in 1414 * from the back, until further notice. 1415 */ 1416 r->status = proxy_status; 1417 r->status_line = proxy_status_line; 1418 1419 ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, 1420 "Status from backend: %d", proxy_status); 1421 1422 /* read the headers. */ 1423 /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers*/ 1424 /* Also, take care with headers with multiple occurences. */ 1425 1426 /* First, tuck away all already existing cookies */ 1427 save_table = apr_table_make(r->pool, 2); 1428 apr_table_do(addit_dammit, save_table, r->headers_out, 1429 "Set-Cookie", NULL); 1430 1431 /* shove the headers direct into r->headers_out */ 1432 ap_proxy_read_headers(r, backend->r, buffer, sizeof(buffer), origin, 1433 &pread_len); 1434 1435 if (r->headers_out == NULL) { 1436 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01106) 1437 "bad HTTP/%d.%d header returned by %s (%s)", 1438 major, minor, r->uri, r->method); 1439 backend->close = 1; 1440 /* 1441 * ap_send_error relies on a headers_out to be present. we 1442 * are in a bad position here.. so force everything we send out 1443 * to have nothing to do with the incoming packet 1444 */ 1445 r->headers_out = apr_table_make(r->pool,1); 1446 r->status = HTTP_BAD_GATEWAY; 1447 r->status_line = "bad gateway"; 1448 return r->status; 1449 } 1450 1451 /* Now, add in the just read cookies */ 1452 apr_table_do(addit_dammit, save_table, r->headers_out, 1453 "Set-Cookie", NULL); 1454 1455 /* and now load 'em all in */ 1456 if (!apr_is_empty_table(save_table)) { 1457 apr_table_unset(r->headers_out, "Set-Cookie"); 1458 r->headers_out = apr_table_overlay(r->pool, 1459 r->headers_out, 1460 save_table); 1461 } 1462 1463 /* can't have both Content-Length and Transfer-Encoding */ 1464 if (apr_table_get(r->headers_out, "Transfer-Encoding") 1465 && apr_table_get(r->headers_out, "Content-Length")) { 1466 /* 1467 * 2616 section 4.4, point 3: "if both Transfer-Encoding 1468 * and Content-Length are received, the latter MUST be 1469 * ignored"; 1470 * 1471 * To help mitigate HTTP Splitting, unset Content-Length 1472 * and shut down the backend server connection 1473 * XXX: We aught to treat such a response as uncachable 1474 */ 1475 apr_table_unset(r->headers_out, "Content-Length"); 1476 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01107) 1477 "server %s:%d returned Transfer-Encoding" 1478 " and Content-Length", 1479 backend->hostname, backend->port); 1480 backend->close = 1; 1481 } 1482 1483 /* 1484 * Save a possible Transfer-Encoding header as we need it later for 1485 * ap_http_filter to know where to end. 1486 */ 1487 te = apr_table_get(r->headers_out, "Transfer-Encoding"); 1488 1489 /* strip connection listed hop-by-hop headers from response */ 1490 backend->close = ap_proxy_clear_connection_fn(r, r->headers_out); 1491 1492 if ((buf = apr_table_get(r->headers_out, "Content-Type"))) { 1493 ap_set_content_type(r, apr_pstrdup(p, buf)); 1494 } 1495 if (!ap_is_HTTP_INFO(proxy_status)) { 1496 ap_proxy_pre_http_request(origin, backend->r); 1497 } 1498 1499 /* Clear hop-by-hop headers */ 1500 for (i=0; hop_by_hop_hdrs[i]; ++i) { 1501 apr_table_unset(r->headers_out, hop_by_hop_hdrs[i]); 1502 } 1503 1504 /* Delete warnings with wrong date */ 1505 r->headers_out = ap_proxy_clean_warnings(p, r->headers_out); 1506 1507 /* handle Via header in response */ 1508 if (conf->viaopt != via_off && conf->viaopt != via_block) { 1509 const char *server_name = ap_get_server_name(r); 1510 /* If USE_CANONICAL_NAME_OFF was configured for the proxy virtual host, 1511 * then the server name returned by ap_get_server_name() is the 1512 * origin server name (which does make too much sense with Via: headers) 1513 * so we use the proxy vhost's name instead. 1514 */ 1515 if (server_name == r->hostname) 1516 server_name = r->server->server_hostname; 1517 /* create a "Via:" response header entry and merge it */ 1518 apr_table_addn(r->headers_out, "Via", 1519 (conf->viaopt == via_full) 1520 ? apr_psprintf(p, "%d.%d %s%s (%s)", 1521 HTTP_VERSION_MAJOR(r->proto_num), 1522 HTTP_VERSION_MINOR(r->proto_num), 1523 server_name, 1524 server_portstr, 1525 AP_SERVER_BASEVERSION) 1526 : apr_psprintf(p, "%d.%d %s%s", 1527 HTTP_VERSION_MAJOR(r->proto_num), 1528 HTTP_VERSION_MINOR(r->proto_num), 1529 server_name, 1530 server_portstr) 1531 ); 1532 } 1533 1534 /* cancel keepalive if HTTP/1.0 or less */ 1535 if ((major < 1) || (minor < 1)) { 1536 backend->close = 1; 1537 origin->keepalive = AP_CONN_CLOSE; 1538 } 1539 } else { 1540 /* an http/0.9 response */ 1541 backasswards = 1; 1542 r->status = 200; 1543 r->status_line = "200 OK"; 1544 backend->close = 1; 1545 } 1546 1547 if (ap_is_HTTP_INFO(proxy_status)) { 1548 interim_response++; 1549 /* Reset to old timeout iff we've adjusted it */ 1550 if (do_100_continue 1551 && (r->status == HTTP_CONTINUE) 1552 && (worker->s->ping_timeout != old_timeout)) { 1553 apr_socket_timeout_set(backend->sock, old_timeout); 1554 } 1555 } 1556 else { 1557 interim_response = 0; 1558 } 1559 if (interim_response) { 1560 /* RFC2616 tells us to forward this. 1561 * 1562 * OTOH, an interim response here may mean the backend 1563 * is playing sillybuggers. The Client didn't ask for 1564 * it within the defined HTTP/1.1 mechanisms, and if 1565 * it's an extension, it may also be unsupported by us. 1566 * 1567 * There's also the possibility that changing existing 1568 * behaviour here might break something. 1569 * 1570 * So let's make it configurable. 1571 * 1572 * We need to set "r->expecting_100 = 1" otherwise origin 1573 * server behaviour will apply. 1574 */ 1575 const char *policy = apr_table_get(r->subprocess_env, 1576 "proxy-interim-response"); 1577 ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, 1578 "HTTP: received interim %d response", r->status); 1579 if (!policy 1580 || (!strcasecmp(policy, "RFC") && ((r->expecting_100 = 1)))) { 1581 ap_send_interim_response(r, 1); 1582 } 1583 /* FIXME: refine this to be able to specify per-response-status 1584 * policies and maybe also add option to bail out with 502 1585 */ 1586 else if (strcasecmp(policy, "Suppress")) { 1587 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01108) 1588 "undefined proxy interim response policy"); 1589 } 1590 } 1591 /* Moved the fixups of Date headers and those affected by 1592 * ProxyPassReverse/etc from here to ap_proxy_read_headers 1593 */ 1594 1595 if ((proxy_status == 401) && (dconf->error_override)) { 1596 const char *buf; 1597 const char *wa = "WWW-Authenticate"; 1598 if ((buf = apr_table_get(r->headers_out, wa))) { 1599 apr_table_set(r->err_headers_out, wa, buf); 1600 } else { 1601 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01109) 1602 "origin server sent 401 without " 1603 "WWW-Authenticate header"); 1604 } 1605 } 1606 1607 r->sent_bodyct = 1; 1608 /* 1609 * Is it an HTTP/0.9 response or did we maybe preread the 1st line of 1610 * the response? If so, load the extra data. These are 2 mutually 1611 * exclusive possibilities, that just happen to require very 1612 * similar behavior. 1613 */ 1614 if (backasswards || pread_len) { 1615 apr_ssize_t cntr = (apr_ssize_t)pread_len; 1616 if (backasswards) { 1617 /*@@@FIXME: 1618 * At this point in response processing of a 0.9 response, 1619 * we don't know yet whether data is binary or not. 1620 * mod_charset_lite will get control later on, so it cannot 1621 * decide on the conversion of this buffer full of data. 1622 * However, chances are that we are not really talking to an 1623 * HTTP/0.9 server, but to some different protocol, therefore 1624 * the best guess IMHO is to always treat the buffer as "text/x": 1625 */ 1626 ap_xlate_proto_to_ascii(buffer, len); 1627 cntr = (apr_ssize_t)len; 1628 } 1629 e = apr_bucket_heap_create(buffer, cntr, NULL, c->bucket_alloc); 1630 APR_BRIGADE_INSERT_TAIL(bb, e); 1631 } 1632 /* PR 41646: get HEAD right with ProxyErrorOverride */ 1633 if (ap_is_HTTP_ERROR(r->status) && dconf->error_override) { 1634 /* clear r->status for override error, otherwise ErrorDocument 1635 * thinks that this is a recursive error, and doesn't find the 1636 * custom error page 1637 */ 1638 r->status = HTTP_OK; 1639 /* Discard body, if one is expected */ 1640 if (!r->header_only && /* not HEAD request */ 1641 (proxy_status != HTTP_NO_CONTENT) && /* not 204 */ 1642 (proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */ 1643 ap_discard_request_body(backend->r); 1644 } 1645 return proxy_status; 1646 } 1647 1648 /* send body - but only if a body is expected */ 1649 if ((!r->header_only) && /* not HEAD request */ 1650 !interim_response && /* not any 1xx response */ 1651 (proxy_status != HTTP_NO_CONTENT) && /* not 204 */ 1652 (proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */ 1653 1654 /* We need to copy the output headers and treat them as input 1655 * headers as well. BUT, we need to do this before we remove 1656 * TE, so that they are preserved accordingly for 1657 * ap_http_filter to know where to end. 1658 */ 1659 backend->r->headers_in = apr_table_clone(backend->r->pool, r->headers_out); 1660 /* 1661 * Restore Transfer-Encoding header from response if we saved 1662 * one before and there is none left. We need it for the 1663 * ap_http_filter. See above. 1664 */ 1665 if (te && !apr_table_get(backend->r->headers_in, "Transfer-Encoding")) { 1666 apr_table_add(backend->r->headers_in, "Transfer-Encoding", te); 1667 } 1668 1669 apr_table_unset(r->headers_out,"Transfer-Encoding"); 1670 1671 ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, "start body send"); 1672 1673 /* 1674 * if we are overriding the errors, we can't put the content 1675 * of the page into the brigade 1676 */ 1677 if (!dconf->error_override || !ap_is_HTTP_ERROR(proxy_status)) { 1678 /* read the body, pass it to the output filters */ 1679 apr_read_type_e mode = APR_NONBLOCK_READ; 1680 int finish = FALSE; 1681 1682 /* Handle the case where the error document is itself reverse 1683 * proxied and was successful. We must maintain any previous 1684 * error status so that an underlying error (eg HTTP_NOT_FOUND) 1685 * doesn't become an HTTP_OK. 1686 */ 1687 if (dconf->error_override && !ap_is_HTTP_ERROR(proxy_status) 1688 && ap_is_HTTP_ERROR(original_status)) { 1689 r->status = original_status; 1690 r->status_line = original_status_line; 1691 } 1692 1693 do { 1694 apr_off_t readbytes; 1695 apr_status_t rv; 1696 1697 rv = ap_get_brigade(backend->r->input_filters, bb, 1698 AP_MODE_READBYTES, mode, 1699 conf->io_buffer_size); 1700 1701 /* ap_get_brigade will return success with an empty brigade 1702 * for a non-blocking read which would block: */ 1703 if (mode == APR_NONBLOCK_READ 1704 && (APR_STATUS_IS_EAGAIN(rv) 1705 || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) { 1706 /* flush to the client and switch to blocking mode */ 1707 e = apr_bucket_flush_create(c->bucket_alloc); 1708 APR_BRIGADE_INSERT_TAIL(bb, e); 1709 if (ap_pass_brigade(r->output_filters, bb) 1710 || c->aborted) { 1711 backend->close = 1; 1712 break; 1713 } 1714 apr_brigade_cleanup(bb); 1715 mode = APR_BLOCK_READ; 1716 continue; 1717 } 1718 else if (rv == APR_EOF) { 1719 backend->close = 1; 1720 break; 1721 } 1722 else if (rv != APR_SUCCESS) { 1723 /* In this case, we are in real trouble because 1724 * our backend bailed on us. Pass along a 502 error 1725 * error bucket 1726 */ 1727 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01110) 1728 "error reading response"); 1729 ap_proxy_backend_broke(r, bb); 1730 ap_pass_brigade(r->output_filters, bb); 1731 backend_broke = 1; 1732 backend->close = 1; 1733 break; 1734 } 1735 /* next time try a non-blocking read */ 1736 mode = APR_NONBLOCK_READ; 1737 1738 apr_brigade_length(bb, 0, &readbytes); 1739 backend->worker->s->read += readbytes; 1740#if DEBUGGING 1741 { 1742 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01111) 1743 "readbytes: %#x", readbytes); 1744 } 1745#endif 1746 /* sanity check */ 1747 if (APR_BRIGADE_EMPTY(bb)) { 1748 apr_brigade_cleanup(bb); 1749 break; 1750 } 1751 1752 /* Switch the allocator lifetime of the buckets */ 1753 proxy_buckets_lifetime_transform(r, bb, pass_bb); 1754 1755 /* found the last brigade? */ 1756 if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pass_bb))) { 1757 1758 /* signal that we must leave */ 1759 finish = TRUE; 1760 1761 /* the brigade may contain transient buckets that contain 1762 * data that lives only as long as the backend connection. 1763 * Force a setaside so these transient buckets become heap 1764 * buckets that live as long as the request. 1765 */ 1766 for (e = APR_BRIGADE_FIRST(pass_bb); e 1767 != APR_BRIGADE_SENTINEL(pass_bb); e 1768 = APR_BUCKET_NEXT(e)) { 1769 apr_bucket_setaside(e, r->pool); 1770 } 1771 1772 /* finally it is safe to clean up the brigade from the 1773 * connection pool, as we have forced a setaside on all 1774 * buckets. 1775 */ 1776 apr_brigade_cleanup(bb); 1777 1778 /* make sure we release the backend connection as soon 1779 * as we know we are done, so that the backend isn't 1780 * left waiting for a slow client to eventually 1781 * acknowledge the data. 1782 */ 1783 ap_proxy_release_connection(backend->worker->s->scheme, 1784 backend, r->server); 1785 /* Ensure that the backend is not reused */ 1786 *backend_ptr = NULL; 1787 1788 } 1789 1790 /* try send what we read */ 1791 if (ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS 1792 || c->aborted) { 1793 /* Ack! Phbtt! Die! User aborted! */ 1794 /* Only close backend if we haven't got all from the 1795 * backend. Furthermore if *backend_ptr is NULL it is no 1796 * longer safe to fiddle around with backend as it might 1797 * be already in use by another thread. 1798 */ 1799 if (*backend_ptr) { 1800 backend->close = 1; /* this causes socket close below */ 1801 } 1802 finish = TRUE; 1803 } 1804 1805 /* make sure we always clean up after ourselves */ 1806 apr_brigade_cleanup(pass_bb); 1807 apr_brigade_cleanup(bb); 1808 1809 } while (!finish); 1810 } 1811 ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "end body send"); 1812 } 1813 else if (!interim_response) { 1814 ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "header only"); 1815 1816 /* make sure we release the backend connection as soon 1817 * as we know we are done, so that the backend isn't 1818 * left waiting for a slow client to eventually 1819 * acknowledge the data. 1820 */ 1821 ap_proxy_release_connection(backend->worker->s->scheme, 1822 backend, r->server); 1823 *backend_ptr = NULL; 1824 1825 /* Pass EOS bucket down the filter chain. */ 1826 e = apr_bucket_eos_create(c->bucket_alloc); 1827 APR_BRIGADE_INSERT_TAIL(bb, e); 1828 ap_pass_brigade(r->output_filters, bb); 1829 1830 apr_brigade_cleanup(bb); 1831 } 1832 } while (interim_response && (interim_response < AP_MAX_INTERIM_RESPONSES)); 1833 1834 /* We have to cleanup bb brigade, because buckets inserted to it could be 1835 * created from scpool and this pool can be freed before this brigade. */ 1836 apr_brigade_cleanup(bb); 1837 1838 /* See define of AP_MAX_INTERIM_RESPONSES for why */ 1839 if (interim_response >= AP_MAX_INTERIM_RESPONSES) { 1840 return ap_proxyerror(r, HTTP_BAD_GATEWAY, 1841 apr_psprintf(p, 1842 "Too many (%d) interim responses from origin server", 1843 interim_response)); 1844 } 1845 1846 /* If our connection with the client is to be aborted, return DONE. */ 1847 if (c->aborted || backend_broke) { 1848 return DONE; 1849 } 1850 1851 return OK; 1852} 1853 1854static 1855apr_status_t ap_proxy_http_cleanup(const char *scheme, request_rec *r, 1856 proxy_conn_rec *backend) 1857{ 1858 ap_proxy_release_connection(scheme, backend, r->server); 1859 return OK; 1860} 1861 1862/* 1863 * This handles http:// URLs, and other URLs using a remote proxy over http 1864 * If proxyhost is NULL, then contact the server directly, otherwise 1865 * go via the proxy. 1866 * Note that if a proxy is used, then URLs other than http: can be accessed, 1867 * also, if we have trouble which is clearly specific to the proxy, then 1868 * we return DECLINED so that we can try another proxy. (Or the direct 1869 * route.) 1870 */ 1871static int proxy_http_handler(request_rec *r, proxy_worker *worker, 1872 proxy_server_conf *conf, 1873 char *url, const char *proxyname, 1874 apr_port_t proxyport) 1875{ 1876 int status; 1877 char server_portstr[32]; 1878 char *scheme; 1879 const char *proxy_function; 1880 const char *u; 1881 proxy_conn_rec *backend = NULL; 1882 int is_ssl = 0; 1883 conn_rec *c = r->connection; 1884 int retry = 0; 1885 /* 1886 * Use a shorter-lived pool to reduce memory usage 1887 * and avoid a memory leak 1888 */ 1889 apr_pool_t *p = r->pool; 1890 apr_uri_t *uri = apr_palloc(p, sizeof(*uri)); 1891 1892 /* find the scheme */ 1893 u = strchr(url, ':'); 1894 if (u == NULL || u[1] != '/' || u[2] != '/' || u[3] == '\0') 1895 return DECLINED; 1896 if ((u - url) > 14) 1897 return HTTP_BAD_REQUEST; 1898 scheme = apr_pstrmemdup(p, url, u - url); 1899 /* scheme is lowercase */ 1900 ap_str_tolower(scheme); 1901 /* is it for us? */ 1902 if (strcmp(scheme, "https") == 0) { 1903 if (!ap_proxy_ssl_enable(NULL)) { 1904 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01112) 1905 "HTTPS: declining URL %s (mod_ssl not configured?)", 1906 url); 1907 return DECLINED; 1908 } 1909 is_ssl = 1; 1910 proxy_function = "HTTPS"; 1911 } 1912 else if (!(strcmp(scheme, "http") == 0 || (strcmp(scheme, "ftp") == 0 && proxyname))) { 1913 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01113) "HTTP: declining URL %s", 1914 url); 1915 return DECLINED; /* only interested in HTTP, or FTP via proxy */ 1916 } 1917 else { 1918 if (*scheme == 'h') 1919 proxy_function = "HTTP"; 1920 else 1921 proxy_function = "FTP"; 1922 } 1923 ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "HTTP: serving URL %s", url); 1924 1925 1926 /* create space for state information */ 1927 if ((status = ap_proxy_acquire_connection(proxy_function, &backend, 1928 worker, r->server)) != OK) 1929 goto cleanup; 1930 1931 1932 backend->is_ssl = is_ssl; 1933 1934 if (is_ssl) { 1935 ap_proxy_ssl_connection_cleanup(backend, r); 1936 } 1937 1938 /* 1939 * In the case that we are handling a reverse proxy connection and this 1940 * is not a request that is coming over an already kept alive connection 1941 * with the client, do NOT reuse the connection to the backend, because 1942 * we cannot forward a failure to the client in this case as the client 1943 * does NOT expect this in this situation. 1944 * Yes, this creates a performance penalty. 1945 */ 1946 if ((r->proxyreq == PROXYREQ_REVERSE) && (!c->keepalives) 1947 && (apr_table_get(r->subprocess_env, "proxy-initial-not-pooled"))) { 1948 backend->close = 1; 1949 } 1950 1951 while (retry < 2) { 1952 char *locurl = url; 1953 1954 /* Step One: Determine Who To Connect To */ 1955 if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend, 1956 uri, &locurl, proxyname, 1957 proxyport, server_portstr, 1958 sizeof(server_portstr))) != OK) 1959 break; 1960 1961 /* Step Two: Make the Connection */ 1962 if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server)) { 1963 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01114) 1964 "HTTP: failed to make connection to backend: %s", 1965 backend->hostname); 1966 status = HTTP_SERVICE_UNAVAILABLE; 1967 break; 1968 } 1969 1970 /* Step Three: Create conn_rec */ 1971 if (!backend->connection) { 1972 if ((status = ap_proxy_connection_create(proxy_function, backend, 1973 c, r->server)) != OK) 1974 break; 1975 /* 1976 * On SSL connections set a note on the connection what CN is 1977 * requested, such that mod_ssl can check if it is requested to do 1978 * so. 1979 */ 1980 if (is_ssl) { 1981 proxy_dir_conf *dconf; 1982 const char *ssl_hostname; 1983 1984 /* 1985 * In the case of ProxyPreserveHost on use the hostname of 1986 * the request if present otherwise use the one from the 1987 * backend request URI. 1988 */ 1989 dconf = ap_get_module_config(r->per_dir_config, &proxy_module); 1990 if ((dconf->preserve_host != 0) && (r->hostname != NULL)) { 1991 ssl_hostname = r->hostname; 1992 } 1993 else { 1994 ssl_hostname = uri->hostname; 1995 } 1996 1997 apr_table_set(backend->connection->notes, "proxy-request-hostname", 1998 ssl_hostname); 1999 } 2000 } 2001 2002 /* Step Four: Send the Request 2003 * On the off-chance that we forced a 100-Continue as a 2004 * kinda HTTP ping test, allow for retries 2005 */ 2006 if ((status = ap_proxy_http_request(p, r, backend, worker, 2007 conf, uri, locurl, server_portstr)) != OK) { 2008 if ((status == HTTP_SERVICE_UNAVAILABLE) && worker->s->ping_timeout_set) { 2009 backend->close = 1; 2010 ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r, APLOGNO(01115) 2011 "HTTP: 100-Continue failed to %pI (%s)", 2012 worker->cp->addr, worker->s->hostname); 2013 retry++; 2014 continue; 2015 } else { 2016 break; 2017 } 2018 2019 } 2020 2021 /* Step Five: Receive the Response... Fall thru to cleanup */ 2022 status = ap_proxy_http_process_response(p, r, &backend, worker, 2023 conf, server_portstr); 2024 2025 break; 2026 } 2027 2028 /* Step Six: Clean Up */ 2029cleanup: 2030 if (backend) { 2031 if (status != OK) 2032 backend->close = 1; 2033 ap_proxy_http_cleanup(proxy_function, r, backend); 2034 } 2035 return status; 2036} 2037 2038/* post_config hook: */ 2039static int proxy_http_post_config(apr_pool_t *pconf, apr_pool_t *plog, 2040 apr_pool_t *ptemp, server_rec *s) 2041{ 2042 2043 /* proxy_http_post_config() will be called twice during startup. So, don't 2044 * set up the static data the 1st time through. */ 2045 if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) { 2046 return OK; 2047 } 2048 2049 if (!ap_proxy_clear_connection_fn) { 2050 ap_proxy_clear_connection_fn = 2051 APR_RETRIEVE_OPTIONAL_FN(ap_proxy_clear_connection); 2052 if (!ap_proxy_clear_connection_fn) { 2053 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02477) 2054 "mod_proxy must be loaded for mod_proxy_http"); 2055 return !OK; 2056 } 2057 } 2058 2059 return OK; 2060} 2061 2062static void ap_proxy_http_register_hook(apr_pool_t *p) 2063{ 2064 ap_hook_post_config(proxy_http_post_config, NULL, NULL, APR_HOOK_MIDDLE); 2065 proxy_hook_scheme_handler(proxy_http_handler, NULL, NULL, APR_HOOK_FIRST); 2066 proxy_hook_canon_handler(proxy_http_canon, NULL, NULL, APR_HOOK_FIRST); 2067 warn_rx = ap_pregcomp(p, "[0-9]{3}[ \t]+[^ \t]+[ \t]+\"[^\"]*\"([ \t]+\"([^\"]+)\")?", 0); 2068} 2069 2070AP_DECLARE_MODULE(proxy_http) = { 2071 STANDARD20_MODULE_STUFF, 2072 NULL, /* create per-directory config structure */ 2073 NULL, /* merge per-directory config structures */ 2074 NULL, /* create per-server config structure */ 2075 NULL, /* merge per-server config structures */ 2076 NULL, /* command apr_table_t */ 2077 ap_proxy_http_register_hook/* register hooks */ 2078}; 2079 2080