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