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