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 /*
18  * protocol.c --- routines which directly communicate with the client.
19  *
20  * Code originally by Rob McCool; much redone by Robert S. Thau
21  * and the Apache Software Foundation.
22  */
23 
24 #include "apr.h"
25 #include "apr_strings.h"
26 #include "apr_buckets.h"
27 #include "apr_lib.h"
28 #include "apr_signal.h"
29 #include "apr_strmatch.h"
30 
31 #define APR_WANT_STDIO          /* for sscanf */
32 #define APR_WANT_STRFUNC
33 #define APR_WANT_MEMFUNC
34 #include "apr_want.h"
35 
36 #include "util_filter.h"
37 #include "ap_config.h"
38 #include "httpd.h"
39 #include "http_config.h"
40 #include "http_core.h"
41 #include "http_protocol.h"
42 #include "http_main.h"
43 #include "http_request.h"
44 #include "http_vhost.h"
45 #include "http_log.h"           /* For errors detected in basic auth common
46                                  * support code... */
47 #include "mod_core.h"
48 #include "util_charset.h"
49 #include "util_ebcdic.h"
50 #include "scoreboard.h"
51 
52 #if APR_HAVE_STDARG_H
53 #include <stdarg.h>
54 #endif
55 #if APR_HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif
58 
59 /* we know core's module_index is 0 */
60 #undef APLOG_MODULE_INDEX
61 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
62 
63 APR_HOOK_STRUCT(
64     APR_HOOK_LINK(pre_read_request)
65     APR_HOOK_LINK(post_read_request)
66     APR_HOOK_LINK(log_transaction)
67     APR_HOOK_LINK(http_scheme)
68     APR_HOOK_LINK(default_port)
69     APR_HOOK_LINK(note_auth_failure)
70     APR_HOOK_LINK(protocol_propose)
71     APR_HOOK_LINK(protocol_switch)
72     APR_HOOK_LINK(protocol_get)
73 )
74 
75 AP_DECLARE_DATA ap_filter_rec_t *ap_old_write_func = NULL;
76 
77 
78 /* Patterns to match in ap_make_content_type() */
79 static const char *needcset[] = {
80     "text/plain",
81     "text/html",
82     NULL
83 };
84 static const apr_strmatch_pattern **needcset_patterns;
85 static const apr_strmatch_pattern *charset_pattern;
86 
ap_setup_make_content_type(apr_pool_t * pool)87 AP_DECLARE(void) ap_setup_make_content_type(apr_pool_t *pool)
88 {
89     int i;
90     for (i = 0; needcset[i]; i++) {
91         continue;
92     }
93     needcset_patterns = (const apr_strmatch_pattern **)
94         apr_palloc(pool, (i + 1) * sizeof(apr_strmatch_pattern *));
95     for (i = 0; needcset[i]; i++) {
96         needcset_patterns[i] = apr_strmatch_precompile(pool, needcset[i], 0);
97     }
98     needcset_patterns[i] = NULL;
99     charset_pattern = apr_strmatch_precompile(pool, "charset=", 0);
100 }
101 
102 /*
103  * Builds the content-type that should be sent to the client from the
104  * content-type specified.  The following rules are followed:
105  *    - if type is NULL or "", return NULL (do not set content-type).
106  *    - if charset adding is disabled, stop processing and return type.
107  *    - then, if there are no parameters on type, add the default charset
108  *    - return type
109  */
ap_make_content_type(request_rec * r,const char * type)110 AP_DECLARE(const char *)ap_make_content_type(request_rec *r, const char *type)
111 {
112     const apr_strmatch_pattern **pcset;
113     core_dir_config *conf =
114         (core_dir_config *)ap_get_core_module_config(r->per_dir_config);
115     core_request_config *request_conf;
116     apr_size_t type_len;
117 
118     if (!type || *type == '\0') {
119         return NULL;
120     }
121 
122     if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) {
123         return type;
124     }
125 
126     request_conf = ap_get_core_module_config(r->request_config);
127     if (request_conf->suppress_charset) {
128         return type;
129     }
130 
131     type_len = strlen(type);
132 
133     if (apr_strmatch(charset_pattern, type, type_len) != NULL) {
134         /* already has parameter, do nothing */
135         /* XXX we don't check the validity */
136         ;
137     }
138     else {
139         /* see if it makes sense to add the charset. At present,
140          * we only add it if the Content-type is one of needcset[]
141          */
142         for (pcset = needcset_patterns; *pcset ; pcset++) {
143             if (apr_strmatch(*pcset, type, type_len) != NULL) {
144                 struct iovec concat[3];
145                 concat[0].iov_base = (void *)type;
146                 concat[0].iov_len = type_len;
147                 concat[1].iov_base = (void *)"; charset=";
148                 concat[1].iov_len = sizeof("; charset=") - 1;
149                 concat[2].iov_base = (void *)(conf->add_default_charset_name);
150                 concat[2].iov_len = strlen(conf->add_default_charset_name);
151                 type = apr_pstrcatv(r->pool, concat, 3, NULL);
152                 break;
153             }
154         }
155     }
156 
157     return type;
158 }
159 
ap_set_content_length(request_rec * r,apr_off_t clength)160 AP_DECLARE(void) ap_set_content_length(request_rec *r, apr_off_t clength)
161 {
162     r->clength = clength;
163     apr_table_setn(r->headers_out, "Content-Length",
164                    apr_off_t_toa(r->pool, clength));
165 }
166 
167 /*
168  * Return the latest rational time from a request/mtime (modification time)
169  * pair.  We return the mtime unless it's in the future, in which case we
170  * return the current time.  We use the request time as a reference in order
171  * to limit the number of calls to time().  We don't check for futurosity
172  * unless the mtime is at least as new as the reference.
173  */
ap_rationalize_mtime(request_rec * r,apr_time_t mtime)174 AP_DECLARE(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime)
175 {
176     apr_time_t now;
177 
178     /* For all static responses, it's almost certain that the file was
179      * last modified before the beginning of the request.  So there's
180      * no reason to call time(NULL) again.  But if the response has been
181      * created on demand, then it might be newer than the time the request
182      * started.  In this event we really have to call time(NULL) again
183      * so that we can give the clients the most accurate Last-Modified.  If we
184      * were given a time in the future, we return the current time - the
185      * Last-Modified can't be in the future.
186      */
187     now = (mtime < r->request_time) ? r->request_time : apr_time_now();
188     return (mtime > now) ? now : mtime;
189 }
190 
191 /* Get a line of protocol input, including any continuation lines
192  * caused by MIME folding (or broken clients) if fold != 0, and place it
193  * in the buffer s, of size n bytes, without the ending newline.
194  *
195  * Pulls from r->proto_input_filters instead of r->input_filters for
196  * stricter protocol adherence and better input filter behavior during
197  * chunked trailer processing (for http).
198  *
199  * If s is NULL, ap_rgetline_core will allocate necessary memory from r->pool.
200  *
201  * Returns APR_SUCCESS if there are no problems and sets *read to be
202  * the full length of s.
203  *
204  * APR_ENOSPC is returned if there is not enough buffer space.
205  * Other errors may be returned on other errors.
206  *
207  * The [CR]LF are *not* returned in the buffer.  Therefore, a *read of 0
208  * indicates that an empty line was read.
209  *
210  * Notes: Because the buffer uses 1 char for NUL, the most we can return is
211  *        (n - 1) actual characters.
212  *
213  *        If no LF is detected on the last line due to a dropped connection
214  *        or a full buffer, that's considered an error.
215  */
ap_rgetline_core(char ** s,apr_size_t n,apr_size_t * read,request_rec * r,int flags,apr_bucket_brigade * bb)216 AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n,
217                                           apr_size_t *read, request_rec *r,
218                                           int flags, apr_bucket_brigade *bb)
219 {
220     apr_status_t rv;
221     apr_bucket *e;
222     apr_size_t bytes_handled = 0, current_alloc = 0;
223     char *pos, *last_char = *s;
224     int do_alloc = (*s == NULL), saw_eos = 0;
225     int fold = flags & AP_GETLINE_FOLD;
226     int crlf = flags & AP_GETLINE_CRLF;
227     int nospc_eol = flags & AP_GETLINE_NOSPC_EOL;
228     int saw_eol = 0, saw_nospc = 0;
229 
230     if (!n) {
231         /* Needs room for NUL byte at least */
232         *read = 0;
233         return APR_BADARG;
234     }
235 
236     /*
237      * Initialize last_char as otherwise a random value will be compared
238      * against APR_ASCII_LF at the end of the loop if bb only contains
239      * zero-length buckets.
240      */
241     if (last_char)
242         *last_char = '\0';
243 
244     do {
245         apr_brigade_cleanup(bb);
246         rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE,
247                             APR_BLOCK_READ, 0);
248         if (rv != APR_SUCCESS) {
249             goto cleanup;
250         }
251 
252         /* Something horribly wrong happened.  Someone didn't block!
253          * (this also happens at the end of each keepalive connection)
254          */
255         if (APR_BRIGADE_EMPTY(bb)) {
256             rv = APR_EGENERAL;
257             goto cleanup;
258         }
259 
260         for (e = APR_BRIGADE_FIRST(bb);
261              e != APR_BRIGADE_SENTINEL(bb);
262              e = APR_BUCKET_NEXT(e))
263         {
264             const char *str;
265             apr_size_t len;
266 
267             /* If we see an EOS, don't bother doing anything more. */
268             if (APR_BUCKET_IS_EOS(e)) {
269                 saw_eos = 1;
270                 break;
271             }
272 
273             rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
274             if (rv != APR_SUCCESS) {
275                 goto cleanup;
276             }
277 
278             if (len == 0) {
279                 /* no use attempting a zero-byte alloc (hurts when
280                  * using --with-efence --enable-pool-debug) or
281                  * doing any of the other logic either
282                  */
283                 continue;
284             }
285 
286             /* Would this overrun our buffer?  If so, we'll die. */
287             if (n < bytes_handled + len) {
288                 /* Before we die, let's fill the buffer up to its limit (i.e.
289                  * fall through with the remaining length, if any), setting
290                  * saw_eol on LF to stop the outer loop appropriately; we may
291                  * come back here once the buffer is filled (no LF seen), and
292                  * either be done at that time or continue to wait for LF here
293                  * if nospc_eol is set.
294                  *
295                  * But there is also a corner cases which we want to address,
296                  * namely if the buffer is overrun by the final LF only (i.e.
297                  * the CR fits in); this is not really an overrun since we'll
298                  * strip the CR finally (and use it for NUL byte), but anyway
299                  * we have to handle the case so that it's not returned to the
300                  * caller as part of the truncated line (it's not!). This is
301                  * easier to consider that LF is out of counting and thus fall
302                  * through with no error (saw_eol is set to 2 so that we later
303                  * ignore LF handling already done here), while folding and
304                  * nospc_eol logics continue to work (or fail) appropriately.
305                  */
306                 saw_eol = (str[len - 1] == APR_ASCII_LF);
307                 if (/* First time around */
308                     saw_eol && !saw_nospc
309                     /*  Single LF completing the buffered CR, */
310                     && ((len == 1 && ((*s)[bytes_handled - 1] == APR_ASCII_CR))
311                     /*  or trailing CRLF overuns by LF only */
312                         || (len > 1 && str[len - 2] == APR_ASCII_CR
313                             && n - bytes_handled + 1 == len))) {
314                     /* In both cases *last_char is (to be) the CR stripped by
315                      * later 'bytes_handled = last_char - *s'.
316                      */
317                     saw_eol = 2;
318                 }
319                 else {
320                     /* In any other case we'd lose data. */
321                     rv = APR_ENOSPC;
322                     saw_nospc = 1;
323                 }
324                 len = n - bytes_handled;
325                 if (!len) {
326                     if (saw_eol) {
327                         break;
328                     }
329                     if (nospc_eol) {
330                         continue;
331                     }
332                     goto cleanup;
333                 }
334             }
335 
336             /* Do we have to handle the allocation ourselves? */
337             if (do_alloc) {
338                 /* We'll assume the common case where one bucket is enough. */
339                 if (!*s) {
340                     current_alloc = len;
341                     *s = apr_palloc(r->pool, current_alloc + 1);
342                 }
343                 else if (bytes_handled + len > current_alloc) {
344                     /* Increase the buffer size */
345                     apr_size_t new_size = current_alloc * 2;
346                     char *new_buffer;
347 
348                     if (bytes_handled + len > new_size) {
349                         new_size = (bytes_handled + len) * 2;
350                     }
351 
352                     new_buffer = apr_palloc(r->pool, new_size + 1);
353 
354                     /* Copy what we already had. */
355                     memcpy(new_buffer, *s, bytes_handled);
356                     current_alloc = new_size;
357                     *s = new_buffer;
358                 }
359             }
360 
361             /* Just copy the rest of the data to the end of the old buffer. */
362             pos = *s + bytes_handled;
363             memcpy(pos, str, len);
364             last_char = pos + len - 1;
365 
366             /* We've now processed that new data - update accordingly. */
367             bytes_handled += len;
368         }
369 
370         /* If we got a full line of input, stop reading */
371         if (last_char && (*last_char == APR_ASCII_LF)) {
372             saw_eol = 1;
373         }
374     } while (!saw_eol);
375 
376     if (rv != APR_SUCCESS) {
377         /* End of line after APR_ENOSPC above */
378         goto cleanup;
379     }
380 
381     /* Now terminate the string at the end of the line;
382      * if the last-but-one character is a CR, terminate there.
383      * LF is handled above (not accounted) when saw_eol == 2,
384      * the last char is CR to terminate at still.
385      */
386     if (saw_eol < 2) {
387         if (last_char > *s && last_char[-1] == APR_ASCII_CR) {
388             last_char--;
389         }
390         else if (crlf) {
391             rv = APR_EINVAL;
392             goto cleanup;
393         }
394     }
395     bytes_handled = last_char - *s;
396 
397     /* If we're folding, we have more work to do.
398      *
399      * Note that if an EOS was seen, we know we can't have another line.
400      */
401     if (fold && bytes_handled && !saw_eos) {
402         for (;;) {
403             const char *str;
404             apr_size_t len;
405             char c;
406 
407             /* Clear the temp brigade for this filter read. */
408             apr_brigade_cleanup(bb);
409 
410             /* We only care about the first byte. */
411             rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_SPECULATIVE,
412                                 APR_BLOCK_READ, 1);
413             if (rv != APR_SUCCESS) {
414                 goto cleanup;
415             }
416 
417             if (APR_BRIGADE_EMPTY(bb)) {
418                 break;
419             }
420 
421             e = APR_BRIGADE_FIRST(bb);
422 
423             /* If we see an EOS, don't bother doing anything more. */
424             if (APR_BUCKET_IS_EOS(e)) {
425                 break;
426             }
427 
428             rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
429             if (rv != APR_SUCCESS) {
430                 apr_brigade_cleanup(bb);
431                 goto cleanup;
432             }
433 
434             /* Found one, so call ourselves again to get the next line.
435              *
436              * FIXME: If the folding line is completely blank, should we
437              * stop folding?  Does that require also looking at the next
438              * char?
439              */
440             /* When we call destroy, the buckets are deleted, so save that
441              * one character we need.  This simplifies our execution paths
442              * at the cost of one character read.
443              */
444             c = *str;
445             if (c == APR_ASCII_BLANK || c == APR_ASCII_TAB) {
446                 /* Do we have enough space? We may be full now. */
447                 if (bytes_handled >= n) {
448                     rv = APR_ENOSPC;
449                     goto cleanup;
450                 }
451                 else {
452                     apr_size_t next_size, next_len;
453                     char *tmp;
454 
455                     /* If we're doing the allocations for them, we have to
456                      * give ourselves a NULL and copy it on return.
457                      */
458                     if (do_alloc) {
459                         tmp = NULL;
460                     }
461                     else {
462                         tmp = last_char;
463                     }
464 
465                     next_size = n - bytes_handled;
466 
467                     rv = ap_rgetline_core(&tmp, next_size, &next_len, r,
468                                           flags & ~AP_GETLINE_FOLD, bb);
469                     if (rv != APR_SUCCESS) {
470                         goto cleanup;
471                     }
472 
473                     if (do_alloc && next_len > 0) {
474                         char *new_buffer;
475                         apr_size_t new_size = bytes_handled + next_len + 1;
476 
477                         /* we need to alloc an extra byte for a null */
478                         new_buffer = apr_palloc(r->pool, new_size);
479 
480                         /* Copy what we already had. */
481                         memcpy(new_buffer, *s, bytes_handled);
482 
483                         /* copy the new line, including the trailing null */
484                         memcpy(new_buffer + bytes_handled, tmp, next_len);
485                         *s = new_buffer;
486                     }
487 
488                     last_char += next_len;
489                     bytes_handled += next_len;
490                 }
491             }
492             else { /* next character is not tab or space */
493                 break;
494             }
495         }
496     }
497 
498 cleanup:
499     if (bytes_handled >= n) {
500         bytes_handled = n - 1;
501     }
502 
503     *read = bytes_handled;
504     if (*s) {
505         /* ensure the string is NUL terminated */
506         (*s)[*read] = '\0';
507 
508         /* PR#43039: We shouldn't accept NULL bytes within the line */
509         bytes_handled = strlen(*s);
510         if (bytes_handled < *read) {
511             *read = bytes_handled;
512             if (rv == APR_SUCCESS) {
513                 rv = APR_EINVAL;
514             }
515         }
516     }
517     return rv;
518 }
519 
520 #if APR_CHARSET_EBCDIC
ap_rgetline(char ** s,apr_size_t n,apr_size_t * read,request_rec * r,int fold,apr_bucket_brigade * bb)521 AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n,
522                                      apr_size_t *read, request_rec *r,
523                                      int fold, apr_bucket_brigade *bb)
524 {
525     /* on ASCII boxes, ap_rgetline is a macro which simply invokes
526      * ap_rgetline_core with the same parms
527      *
528      * on EBCDIC boxes, each complete http protocol input line needs to be
529      * translated into the code page used by the compiler.  Since
530      * ap_rgetline_core uses recursion, we do the translation in a wrapper
531      * function to ensure that each input character gets translated only once.
532      */
533     apr_status_t rv;
534 
535     rv = ap_rgetline_core(s, n, read, r, fold, bb);
536     if (rv == APR_SUCCESS || APR_STATUS_IS_ENOSPC(rv)) {
537         ap_xlate_proto_from_ascii(*s, *read);
538     }
539     return rv;
540 }
541 #endif
542 
ap_getline(char * s,int n,request_rec * r,int flags)543 AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int flags)
544 {
545     char *tmp_s = s;
546     apr_status_t rv;
547     apr_size_t len;
548     apr_bucket_brigade *tmp_bb;
549 
550     if (n < 1) {
551         /* Can't work since we always NUL terminate */
552         return -1;
553     }
554 
555     tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
556     rv = ap_rgetline(&tmp_s, n, &len, r, flags, tmp_bb);
557     apr_brigade_destroy(tmp_bb);
558 
559     /* Map the out-of-space condition to the old API. */
560     if (rv == APR_ENOSPC) {
561         return n;
562     }
563 
564     /* Anything else is just bad. */
565     if (rv != APR_SUCCESS) {
566         return -1;
567     }
568 
569     return (int)len;
570 }
571 
572 /* parse_uri: break apart the uri
573  * Side Effects:
574  * - sets r->args to rest after '?' (or NULL if no '?')
575  * - sets r->uri to request uri (without r->args part)
576  * - sets r->hostname (if not set already) from request (scheme://host:port)
577  */
ap_parse_uri(request_rec * r,const char * uri)578 AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri)
579 {
580     int status = HTTP_OK;
581 
582     r->unparsed_uri = apr_pstrdup(r->pool, uri);
583 
584     /* http://issues.apache.org/bugzilla/show_bug.cgi?id=31875
585      * http://issues.apache.org/bugzilla/show_bug.cgi?id=28450
586      *
587      * This is not in fact a URI, it's a path.  That matters in the
588      * case of a leading double-slash.  We need to resolve the issue
589      * by normalizing that out before treating it as a URI.
590      */
591     while ((uri[0] == '/') && (uri[1] == '/')) {
592         ++uri ;
593     }
594     if (r->method_number == M_CONNECT) {
595         status = apr_uri_parse_hostinfo(r->pool, uri, &r->parsed_uri);
596     }
597     else {
598         status = apr_uri_parse(r->pool, uri, &r->parsed_uri);
599     }
600 
601     if (status == APR_SUCCESS) {
602         /* if it has a scheme we may need to do absoluteURI vhost stuff */
603         if (r->parsed_uri.scheme
604             && !ap_cstr_casecmp(r->parsed_uri.scheme, ap_http_scheme(r))) {
605             r->hostname = r->parsed_uri.hostname;
606         }
607         else if (r->method_number == M_CONNECT) {
608             r->hostname = r->parsed_uri.hostname;
609         }
610 
611         r->args = r->parsed_uri.query;
612         if (r->parsed_uri.path) {
613             r->uri = r->parsed_uri.path;
614         }
615         else if (r->method_number == M_OPTIONS) {
616             r->uri = apr_pstrdup(r->pool, "*");
617         }
618         else {
619             r->uri = apr_pstrdup(r->pool, "/");
620         }
621 
622 #if defined(OS2) || defined(WIN32)
623         /* Handle path translations for OS/2 and plug security hole.
624          * This will prevent "http://www.wherever.com/..\..\/" from
625          * returning a directory for the root drive.
626          */
627         {
628             char *x;
629 
630             for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
631                 *x = '/';
632         }
633 #endif /* OS2 || WIN32 */
634     }
635     else {
636         r->args = NULL;
637         r->hostname = NULL;
638         r->status = HTTP_BAD_REQUEST;             /* set error status */
639         r->uri = apr_pstrdup(r->pool, uri);
640     }
641 }
642 
643 /* get the length of the field name for logging, but no more than 80 bytes */
644 #define LOG_NAME_MAX_LEN 80
field_name_len(const char * field)645 static int field_name_len(const char *field)
646 {
647     const char *end = ap_strchr_c(field, ':');
648     if (end == NULL || end - field > LOG_NAME_MAX_LEN)
649         return LOG_NAME_MAX_LEN;
650     return end - field;
651 }
652 
read_request_line(request_rec * r,apr_bucket_brigade * bb)653 static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
654 {
655     apr_size_t len;
656     int num_blank_lines = DEFAULT_LIMIT_BLANK_LINES;
657     core_server_config *conf = ap_get_core_module_config(r->server->module_config);
658     int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
659 
660     /* Read past empty lines until we get a real request line,
661      * a read error, the connection closes (EOF), or we timeout.
662      *
663      * We skip empty lines because browsers have to tack a CRLF on to the end
664      * of POSTs to support old CERN webservers.  But note that we may not
665      * have flushed any previous response completely to the client yet.
666      * We delay the flush as long as possible so that we can improve
667      * performance for clients that are pipelining requests.  If a request
668      * is pipelined then we won't block during the (implicit) read() below.
669      * If the requests aren't pipelined, then the client is still waiting
670      * for the final buffer flush from us, and we will block in the implicit
671      * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
672      * have to block during a read.
673      */
674 
675     do {
676         apr_status_t rv;
677 
678         /* ensure ap_rgetline allocates memory each time thru the loop
679          * if there are empty lines
680          */
681         r->the_request = NULL;
682         rv = ap_rgetline(&(r->the_request), (apr_size_t)(r->server->limit_req_line + 2),
683                          &len, r, strict ? AP_GETLINE_CRLF : 0, bb);
684 
685         if (rv != APR_SUCCESS) {
686             r->request_time = apr_time_now();
687 
688             /* ap_rgetline returns APR_ENOSPC if it fills up the
689              * buffer before finding the end-of-line.  This is only going to
690              * happen if it exceeds the configured limit for a request-line.
691              */
692             if (APR_STATUS_IS_ENOSPC(rv)) {
693                 r->status = HTTP_REQUEST_URI_TOO_LARGE;
694             }
695             else if (APR_STATUS_IS_TIMEUP(rv)) {
696                 r->status = HTTP_REQUEST_TIME_OUT;
697             }
698             else if (APR_STATUS_IS_EINVAL(rv)) {
699                 r->status = HTTP_BAD_REQUEST;
700             }
701             r->proto_num = HTTP_VERSION(1,0);
702             r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
703             return 0;
704         }
705     } while ((len <= 0) && (--num_blank_lines >= 0));
706 
707     /* Set r->request_time before any logging, mod_unique_id needs it. */
708     r->request_time = apr_time_now();
709 
710     if (APLOGrtrace5(r)) {
711         ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r,
712                       "Request received from client: %s",
713                       ap_escape_logitem(r->pool, r->the_request));
714     }
715 
716     return 1;
717 }
718 
ap_parse_request_line(request_rec * r)719 AP_DECLARE(int) ap_parse_request_line(request_rec *r)
720 {
721     core_server_config *conf = ap_get_core_module_config(r->server->module_config);
722     int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
723     enum {
724         rrl_none, rrl_badmethod, rrl_badwhitespace, rrl_excesswhitespace,
725         rrl_missinguri, rrl_baduri, rrl_badprotocol, rrl_trailingtext,
726         rrl_badmethod09, rrl_reject09
727     } deferred_error = rrl_none;
728     apr_size_t len = 0;
729     char *uri, *ll;
730 
731     r->method = r->the_request;
732 
733     /* If there is whitespace before a method, skip it and mark in error */
734     if (apr_isspace(*r->method)) {
735         deferred_error = rrl_badwhitespace;
736         for ( ; apr_isspace(*r->method); ++r->method)
737             ;
738     }
739 
740     /* Scan the method up to the next whitespace, ensure it contains only
741      * valid http-token characters, otherwise mark in error
742      */
743     if (strict) {
744         ll = (char*) ap_scan_http_token(r->method);
745     }
746     else {
747         ll = (char*) ap_scan_vchar_obstext(r->method);
748     }
749 
750     if (((ll == r->method) || (*ll && !apr_isspace(*ll)))
751             && deferred_error == rrl_none) {
752         deferred_error = rrl_badmethod;
753         ll = strpbrk(ll, "\t\n\v\f\r ");
754     }
755 
756     /* Verify method terminated with a single SP, or mark as specific error */
757     if (!ll) {
758         if (deferred_error == rrl_none)
759             deferred_error = rrl_missinguri;
760         r->protocol = uri = "";
761         goto rrl_done;
762     }
763     else if (strict && ll[0] && apr_isspace(ll[1])
764              && deferred_error == rrl_none) {
765         deferred_error = rrl_excesswhitespace;
766     }
767 
768     /* Advance uri pointer over leading whitespace, NUL terminate the method
769      * If non-SP whitespace is encountered, mark as specific error
770      */
771     for (uri = ll; apr_isspace(*uri); ++uri)
772         if (*uri != ' ' && deferred_error == rrl_none)
773             deferred_error = rrl_badwhitespace;
774     *ll = '\0';
775 
776     if (!*uri && deferred_error == rrl_none)
777         deferred_error = rrl_missinguri;
778 
779     /* Scan the URI up to the next whitespace, ensure it contains no raw
780      * control characters, otherwise mark in error
781      */
782     ll = (char*) ap_scan_vchar_obstext(uri);
783     if (ll == uri || (*ll && !apr_isspace(*ll))) {
784         deferred_error = rrl_baduri;
785         ll = strpbrk(ll, "\t\n\v\f\r ");
786     }
787 
788     /* Verify URI terminated with a single SP, or mark as specific error */
789     if (!ll) {
790         r->protocol = "";
791         goto rrl_done;
792     }
793     else if (strict && ll[0] && apr_isspace(ll[1])
794              && deferred_error == rrl_none) {
795         deferred_error = rrl_excesswhitespace;
796     }
797 
798     /* Advance protocol pointer over leading whitespace, NUL terminate the uri
799      * If non-SP whitespace is encountered, mark as specific error
800      */
801     for (r->protocol = ll; apr_isspace(*r->protocol); ++r->protocol)
802         if (*r->protocol != ' ' && deferred_error == rrl_none)
803             deferred_error = rrl_badwhitespace;
804     *ll = '\0';
805 
806     /* Scan the protocol up to the next whitespace, validation comes later */
807     if (!(ll = (char*) ap_scan_vchar_obstext(r->protocol))) {
808         len = strlen(r->protocol);
809         goto rrl_done;
810     }
811     len = ll - r->protocol;
812 
813     /* Advance over trailing whitespace, if found mark in error,
814      * determine if trailing text is found, unconditionally mark in error,
815      * finally NUL terminate the protocol string
816      */
817     if (*ll && !apr_isspace(*ll)) {
818         deferred_error = rrl_badprotocol;
819     }
820     else if (strict && *ll) {
821         deferred_error = rrl_excesswhitespace;
822     }
823     else {
824         for ( ; apr_isspace(*ll); ++ll)
825             if (*ll != ' ' && deferred_error == rrl_none)
826                 deferred_error = rrl_badwhitespace;
827         if (*ll && deferred_error == rrl_none)
828             deferred_error = rrl_trailingtext;
829     }
830     *((char *)r->protocol + len) = '\0';
831 
832 rrl_done:
833     /* For internal integrity and palloc efficiency, reconstruct the_request
834      * in one palloc, using only single SP characters, per spec.
835      */
836     r->the_request = apr_pstrcat(r->pool, r->method, *uri ? " " : NULL, uri,
837                                  *r->protocol ? " " : NULL, r->protocol, NULL);
838 
839     if (len == 8
840             && r->protocol[0] == 'H' && r->protocol[1] == 'T'
841             && r->protocol[2] == 'T' && r->protocol[3] == 'P'
842             && r->protocol[4] == '/' && apr_isdigit(r->protocol[5])
843             && r->protocol[6] == '.' && apr_isdigit(r->protocol[7])
844             && r->protocol[5] != '0') {
845         r->assbackwards = 0;
846         r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
847     }
848     else if (len == 8
849                  && (r->protocol[0] == 'H' || r->protocol[0] == 'h')
850                  && (r->protocol[1] == 'T' || r->protocol[1] == 't')
851                  && (r->protocol[2] == 'T' || r->protocol[2] == 't')
852                  && (r->protocol[3] == 'P' || r->protocol[3] == 'p')
853                  && r->protocol[4] == '/' && apr_isdigit(r->protocol[5])
854                  && r->protocol[6] == '.' && apr_isdigit(r->protocol[7])
855                  && r->protocol[5] != '0') {
856         r->assbackwards = 0;
857         r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
858         if (strict && deferred_error == rrl_none)
859             deferred_error = rrl_badprotocol;
860         else
861             memcpy((char*)r->protocol, "HTTP", 4);
862     }
863     else if (r->protocol[0]) {
864         r->proto_num = HTTP_VERSION(0, 9);
865         /* Defer setting the r->protocol string till error msg is composed */
866         if (deferred_error == rrl_none)
867             deferred_error = rrl_badprotocol;
868     }
869     else {
870         r->assbackwards = 1;
871         r->protocol  = apr_pstrdup(r->pool, "HTTP/0.9");
872         r->proto_num = HTTP_VERSION(0, 9);
873     }
874 
875     /* Determine the method_number and parse the uri prior to invoking error
876      * handling, such that these fields are available for substitution
877      */
878     r->method_number = ap_method_number_of(r->method);
879     if (r->method_number == M_GET && r->method[0] == 'H')
880         r->header_only = 1;
881 
882     ap_parse_uri(r, uri);
883     if (r->status == HTTP_OK
884             && (r->parsed_uri.path != NULL)
885             && (r->parsed_uri.path[0] != '/')
886             && (r->method_number != M_OPTIONS
887                 || strcmp(r->parsed_uri.path, "*") != 0)) {
888         /* Invalid request-target per RFC 7230 section 5.3 */
889         r->status = HTTP_BAD_REQUEST;
890     }
891 
892     /* With the request understood, we can consider HTTP/0.9 specific errors */
893     if (r->proto_num == HTTP_VERSION(0, 9) && deferred_error == rrl_none) {
894         if (conf->http09_enable == AP_HTTP09_DISABLE)
895             deferred_error = rrl_reject09;
896         else if (strict && (r->method_number != M_GET || r->header_only))
897             deferred_error = rrl_badmethod09;
898     }
899 
900     /* Now that the method, uri and protocol are all processed,
901      * we can safely resume any deferred error reporting
902      */
903     if (deferred_error != rrl_none) {
904         if (deferred_error == rrl_badmethod)
905             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03445)
906                           "HTTP Request Line; Invalid method token: '%.*s'",
907                           field_name_len(r->method), r->method);
908         else if (deferred_error == rrl_badmethod09)
909             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03444)
910                           "HTTP Request Line; Invalid method token: '%.*s'"
911                           " (only GET is allowed for HTTP/0.9 requests)",
912                           field_name_len(r->method), r->method);
913         else if (deferred_error == rrl_missinguri)
914             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03446)
915                           "HTTP Request Line; Missing URI");
916         else if (deferred_error == rrl_baduri)
917             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03454)
918                           "HTTP Request Line; URI incorrectly encoded: '%.*s'",
919                           field_name_len(r->unparsed_uri), r->unparsed_uri);
920         else if (deferred_error == rrl_badwhitespace)
921             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03447)
922                           "HTTP Request Line; Invalid whitespace");
923         else if (deferred_error == rrl_excesswhitespace)
924             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03448)
925                           "HTTP Request Line; Excess whitespace "
926                           "(disallowed by HttpProtocolOptions Strict)");
927         else if (deferred_error == rrl_trailingtext)
928             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03449)
929                           "HTTP Request Line; Extraneous text found '%.*s' "
930                           "(perhaps whitespace was injected?)",
931                           field_name_len(ll), ll);
932         else if (deferred_error == rrl_reject09)
933             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02401)
934                           "HTTP Request Line; Rejected HTTP/0.9 request");
935         else if (deferred_error == rrl_badprotocol)
936             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02418)
937                           "HTTP Request Line; Unrecognized protocol '%.*s' "
938                           "(perhaps whitespace was injected?)",
939                           field_name_len(r->protocol), r->protocol);
940         r->status = HTTP_BAD_REQUEST;
941         goto rrl_failed;
942     }
943 
944     if (conf->http_methods == AP_HTTP_METHODS_REGISTERED
945             && r->method_number == M_INVALID) {
946         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02423)
947                       "HTTP Request Line; Unrecognized HTTP method: '%.*s' "
948                       "(disallowed by RegisteredMethods)",
949                       field_name_len(r->method), r->method);
950         r->status = HTTP_NOT_IMPLEMENTED;
951         /* This can't happen in an HTTP/0.9 request, we verified GET above */
952         return 0;
953     }
954 
955     if (r->status != HTTP_OK) {
956         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03450)
957                       "HTTP Request Line; Unable to parse URI: '%.*s'",
958                       field_name_len(r->uri), r->uri);
959         goto rrl_failed;
960     }
961 
962     if (strict) {
963         if (r->parsed_uri.fragment) {
964             /* RFC3986 3.5: no fragment */
965             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02421)
966                           "HTTP Request Line; URI must not contain a fragment");
967             r->status = HTTP_BAD_REQUEST;
968             goto rrl_failed;
969         }
970         if (r->parsed_uri.user || r->parsed_uri.password) {
971             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02422)
972                           "HTTP Request Line; URI must not contain a "
973                           "username/password");
974             r->status = HTTP_BAD_REQUEST;
975             goto rrl_failed;
976         }
977     }
978 
979     return 1;
980 
981 rrl_failed:
982     if (r->proto_num == HTTP_VERSION(0, 9)) {
983         /* Send all parsing and protocol error response with 1.x behavior,
984          * and reserve 505 errors for actual HTTP protocols presented.
985          * As called out in RFC7230 3.5, any errors parsing the protocol
986          * from the request line are nearly always misencoded HTTP/1.x
987          * requests. Only a valid 0.9 request with no parsing errors
988          * at all may be treated as a simple request, if allowed.
989          */
990         r->assbackwards = 0;
991         r->connection->keepalive = AP_CONN_CLOSE;
992         r->proto_num = HTTP_VERSION(1, 0);
993         r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
994     }
995     return 0;
996 }
997 
ap_check_request_header(request_rec * r)998 AP_DECLARE(int) ap_check_request_header(request_rec *r)
999 {
1000     core_server_config *conf;
1001     int strict_host_check;
1002     const char *expect;
1003     int access_status;
1004 
1005     conf = ap_get_core_module_config(r->server->module_config);
1006 
1007     /* update what we think the virtual host is based on the headers we've
1008      * now read. may update status.
1009      */
1010     strict_host_check = (conf->strict_host_check == AP_CORE_CONFIG_ON);
1011     access_status = ap_update_vhost_from_headers_ex(r, strict_host_check);
1012     if (strict_host_check && access_status != HTTP_OK) {
1013         if (r->server == ap_server_conf) {
1014             ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10156)
1015                           "Requested hostname '%s' did not match any ServerName/ServerAlias "
1016                           "in the global server configuration ", r->hostname);
1017         }
1018         else {
1019             ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10157)
1020                           "Requested hostname '%s' did not match any ServerName/ServerAlias "
1021                           "in the matching virtual host (default vhost for "
1022                           "current connection is %s:%u)",
1023                           r->hostname, r->server->defn_name, r->server->defn_line_number);
1024         }
1025         r->status = access_status;
1026     }
1027     if (r->status != HTTP_OK) {
1028         return 0;
1029     }
1030 
1031     if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1, 1)))
1032         || ((r->proto_num == HTTP_VERSION(1, 1))
1033             && !apr_table_get(r->headers_in, "Host"))) {
1034         /*
1035          * Client sent us an HTTP/1.1 or later request without telling us the
1036          * hostname, either with a full URL or a Host: header. We therefore
1037          * need to (as per the 1.1 spec) send an error.  As a special case,
1038          * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
1039          * a Host: header, and the server MUST respond with 400 if it doesn't.
1040          */
1041         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00569)
1042                       "client sent HTTP/1.1 request without hostname "
1043                       "(see RFC2616 section 14.23): %s", r->uri);
1044         r->status = HTTP_BAD_REQUEST;
1045         return 0;
1046     }
1047 
1048     if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL)
1049         && (expect[0] != '\0')) {
1050         /*
1051          * The Expect header field was added to HTTP/1.1 after RFC 2068
1052          * as a means to signal when a 100 response is desired and,
1053          * unfortunately, to signal a poor man's mandatory extension that
1054          * the server must understand or return 417 Expectation Failed.
1055          */
1056         if (ap_cstr_casecmp(expect, "100-continue") == 0) {
1057             r->expecting_100 = 1;
1058         }
1059         else {
1060             ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00570)
1061                           "client sent an unrecognized expectation value "
1062                           "of Expect: %s", expect);
1063             r->status = HTTP_EXPECTATION_FAILED;
1064             return 0;
1065         }
1066     }
1067 
1068     return 1;
1069 }
1070 
table_do_fn_check_lengths(void * r_,const char * key,const char * value)1071 static int table_do_fn_check_lengths(void *r_, const char *key,
1072                                      const char *value)
1073 {
1074     request_rec *r = r_;
1075     if (value == NULL || r->server->limit_req_fieldsize >= strlen(value) )
1076         return 1;
1077 
1078     r->status = HTTP_BAD_REQUEST;
1079     apr_table_setn(r->notes, "error-notes",
1080                    "Size of a request header field exceeds server limit.");
1081     ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00560) "Request "
1082                   "header exceeds LimitRequestFieldSize after merging: %.*s",
1083                   field_name_len(key), key);
1084     return 0;
1085 }
1086 
ap_get_mime_headers_core(request_rec * r,apr_bucket_brigade * bb)1087 AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb)
1088 {
1089     char *last_field = NULL;
1090     apr_size_t last_len = 0;
1091     apr_size_t alloc_len = 0;
1092     char *field;
1093     char *value;
1094     apr_size_t len;
1095     int fields_read = 0;
1096     char *tmp_field;
1097     core_server_config *conf = ap_get_core_module_config(r->server->module_config);
1098     int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
1099 
1100     /*
1101      * Read header lines until we get the empty separator line, a read error,
1102      * the connection closes (EOF), reach the server limit, or we timeout.
1103      */
1104     while(1) {
1105         apr_status_t rv;
1106 
1107         field = NULL;
1108         rv = ap_rgetline(&field, r->server->limit_req_fieldsize + 2,
1109                          &len, r, strict ? AP_GETLINE_CRLF : 0, bb);
1110 
1111         if (rv != APR_SUCCESS) {
1112             if (APR_STATUS_IS_TIMEUP(rv)) {
1113                 r->status = HTTP_REQUEST_TIME_OUT;
1114             }
1115             else {
1116                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
1117                               "Failed to read request header line %s", field);
1118                 r->status = HTTP_BAD_REQUEST;
1119             }
1120 
1121             /* ap_rgetline returns APR_ENOSPC if it fills up the buffer before
1122              * finding the end-of-line.  This is only going to happen if it
1123              * exceeds the configured limit for a field size.
1124              */
1125             if (rv == APR_ENOSPC) {
1126                 apr_table_setn(r->notes, "error-notes",
1127                                "Size of a request header field "
1128                                "exceeds server limit.");
1129                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00561)
1130                               "Request header exceeds LimitRequestFieldSize%s"
1131                               "%.*s",
1132                               (field && *field) ? ": " : "",
1133                               (field) ? field_name_len(field) : 0,
1134                               (field) ? field : "");
1135             }
1136             return;
1137         }
1138 
1139         /* For all header values, and all obs-fold lines, the presence of
1140          * additional whitespace is a no-op, so collapse trailing whitespace
1141          * to save buffer allocation and optimize copy operations.
1142          * Do not remove the last single whitespace under any condition.
1143          */
1144         while (len > 1 && (field[len-1] == '\t' || field[len-1] == ' ')) {
1145             field[--len] = '\0';
1146         }
1147 
1148         if (*field == '\t' || *field == ' ') {
1149 
1150             /* Append any newly-read obs-fold line onto the preceding
1151              * last_field line we are processing
1152              */
1153             apr_size_t fold_len;
1154 
1155             if (last_field == NULL) {
1156                 r->status = HTTP_BAD_REQUEST;
1157                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03442)
1158                               "Line folding encountered before first"
1159                               " header line");
1160                 return;
1161             }
1162 
1163             if (field[1] == '\0') {
1164                 r->status = HTTP_BAD_REQUEST;
1165                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03443)
1166                               "Empty folded line encountered");
1167                 return;
1168             }
1169 
1170             /* Leading whitespace on an obs-fold line can be
1171              * similarly discarded */
1172             while (field[1] == '\t' || field[1] == ' ') {
1173                 ++field; --len;
1174             }
1175 
1176             /* This line is a continuation of the preceding line(s),
1177              * so append it to the line that we've set aside.
1178              * Note: this uses a power-of-two allocator to avoid
1179              * doing O(n) allocs and using O(n^2) space for
1180              * continuations that span many many lines.
1181              */
1182             fold_len = last_len + len + 1; /* trailing null */
1183 
1184             if (fold_len >= (apr_size_t)(r->server->limit_req_fieldsize)) {
1185                 r->status = HTTP_BAD_REQUEST;
1186                 /* report what we have accumulated so far before the
1187                  * overflow (last_field) as the field with the problem
1188                  */
1189                 apr_table_setn(r->notes, "error-notes",
1190                                "Size of a request header field "
1191                                "exceeds server limit.");
1192                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00562)
1193                               "Request header exceeds LimitRequestFieldSize "
1194                               "after folding: %.*s",
1195                               field_name_len(last_field), last_field);
1196                 return;
1197             }
1198 
1199             if (fold_len > alloc_len) {
1200                 char *fold_buf;
1201                 alloc_len += alloc_len;
1202                 if (fold_len > alloc_len) {
1203                     alloc_len = fold_len;
1204                 }
1205                 fold_buf = (char *)apr_palloc(r->pool, alloc_len);
1206                 memcpy(fold_buf, last_field, last_len);
1207                 last_field = fold_buf;
1208             }
1209             memcpy(last_field + last_len, field, len +1); /* +1 for nul */
1210             /* Replace obs-fold w/ SP per RFC 7230 3.2.4 */
1211             last_field[last_len] = ' ';
1212             last_len += len;
1213 
1214             /* We've appended this obs-fold line to last_len, proceed to
1215              * read the next input line
1216              */
1217             continue;
1218         }
1219         else if (last_field != NULL) {
1220 
1221             /* Process the previous last_field header line with all obs-folded
1222              * segments already concatenated (this is not operating on the
1223              * most recently read input line).
1224              */
1225 
1226             if (r->server->limit_req_fields
1227                     && (++fields_read > r->server->limit_req_fields)) {
1228                 r->status = HTTP_BAD_REQUEST;
1229                 apr_table_setn(r->notes, "error-notes",
1230                                "The number of request header fields "
1231                                "exceeds this server's limit.");
1232                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00563)
1233                               "Number of request headers exceeds "
1234                               "LimitRequestFields");
1235                 return;
1236             }
1237 
1238             if (!strict)
1239             {
1240                 /* Not Strict ('Unsafe' mode), using the legacy parser */
1241 
1242                 if (!(value = strchr(last_field, ':'))) { /* Find ':' or */
1243                     r->status = HTTP_BAD_REQUEST;   /* abort bad request */
1244                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00564)
1245                                   "Request header field is missing ':' "
1246                                   "separator: %.*s", (int)LOG_NAME_MAX_LEN,
1247                                   last_field);
1248                     return;
1249                 }
1250 
1251                 if (value == last_field) {
1252                     r->status = HTTP_BAD_REQUEST;
1253                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03453)
1254                                   "Request header field name was empty");
1255                     return;
1256                 }
1257 
1258                 *value++ = '\0'; /* NUL-terminate at colon */
1259 
1260                 if (strpbrk(last_field, "\t\n\v\f\r ")) {
1261                     r->status = HTTP_BAD_REQUEST;
1262                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03452)
1263                                   "Request header field name presented"
1264                                   " invalid whitespace");
1265                     return;
1266                 }
1267 
1268                 while (*value == ' ' || *value == '\t') {
1269                      ++value;            /* Skip to start of value   */
1270                 }
1271 
1272                 if (strpbrk(value, "\n\v\f\r")) {
1273                     r->status = HTTP_BAD_REQUEST;
1274                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03451)
1275                                   "Request header field value presented"
1276                                   " bad whitespace");
1277                     return;
1278                 }
1279             }
1280             else /* Using strict RFC7230 parsing */
1281             {
1282                 /* Ensure valid token chars before ':' per RFC 7230 3.2.4 */
1283                 value = (char *)ap_scan_http_token(last_field);
1284                 if ((value == last_field) || *value != ':') {
1285                     r->status = HTTP_BAD_REQUEST;
1286                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02426)
1287                                   "Request header field name is malformed: "
1288                                   "%.*s", (int)LOG_NAME_MAX_LEN, last_field);
1289                     return;
1290                 }
1291 
1292                 *value++ = '\0'; /* NUL-terminate last_field name at ':' */
1293 
1294                 while (*value == ' ' || *value == '\t') {
1295                     ++value;     /* Skip LWS of value */
1296                 }
1297 
1298                 /* Find invalid, non-HT ctrl char, or the trailing NULL */
1299                 tmp_field = (char *)ap_scan_http_field_content(value);
1300 
1301                 /* Reject value for all garbage input (CTRLs excluding HT)
1302                  * e.g. only VCHAR / SP / HT / obs-text are allowed per
1303                  * RFC7230 3.2.6 - leave all more explicit rule enforcement
1304                  * for specific header handler logic later in the cycle
1305                  */
1306                 if (*tmp_field != '\0') {
1307                     r->status = HTTP_BAD_REQUEST;
1308                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02427)
1309                                   "Request header value is malformed: "
1310                                   "%.*s", (int)LOG_NAME_MAX_LEN, value);
1311                     return;
1312                 }
1313             }
1314 
1315             apr_table_addn(r->headers_in, last_field, value);
1316 
1317             /* This last_field header is now stored in headers_in,
1318              * resume processing of the current input line.
1319              */
1320         }
1321 
1322         /* Found the terminating empty end-of-headers line, stop. */
1323         if (len == 0) {
1324             break;
1325         }
1326 
1327         /* Keep track of this new header line so that we can extend it across
1328          * any obs-fold or parse it on the next loop iteration. We referenced
1329          * our previously allocated buffer in r->headers_in,
1330          * so allocate a fresh buffer if required.
1331          */
1332         alloc_len = 0;
1333         last_field = field;
1334         last_len = len;
1335     }
1336 
1337     /* Combine multiple message-header fields with the same
1338      * field-name, following RFC 2616, 4.2.
1339      */
1340     apr_table_compress(r->headers_in, APR_OVERLAP_TABLES_MERGE);
1341 
1342     /* enforce LimitRequestFieldSize for merged headers */
1343     apr_table_do(table_do_fn_check_lengths, r, r->headers_in, NULL);
1344 }
1345 
ap_get_mime_headers(request_rec * r)1346 AP_DECLARE(void) ap_get_mime_headers(request_rec *r)
1347 {
1348     apr_bucket_brigade *tmp_bb;
1349     tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
1350     ap_get_mime_headers_core(r, tmp_bb);
1351     apr_brigade_destroy(tmp_bb);
1352 }
1353 
ap_create_request(conn_rec * conn)1354 AP_DECLARE(request_rec *) ap_create_request(conn_rec *conn)
1355 {
1356     request_rec *r;
1357     apr_pool_t *p;
1358 
1359     apr_pool_create(&p, conn->pool);
1360     apr_pool_tag(p, "request");
1361     r = apr_pcalloc(p, sizeof(request_rec));
1362     AP_READ_REQUEST_ENTRY((intptr_t)r, (uintptr_t)conn);
1363     r->pool            = p;
1364     r->connection      = conn;
1365     r->server          = conn->base_server;
1366 
1367     r->user            = NULL;
1368     r->ap_auth_type    = NULL;
1369 
1370     r->allowed_methods = ap_make_method_list(p, 2);
1371 
1372     r->headers_in      = apr_table_make(r->pool, 25);
1373     r->trailers_in     = apr_table_make(r->pool, 5);
1374     r->subprocess_env  = apr_table_make(r->pool, 25);
1375     r->headers_out     = apr_table_make(r->pool, 12);
1376     r->err_headers_out = apr_table_make(r->pool, 5);
1377     r->trailers_out    = apr_table_make(r->pool, 5);
1378     r->notes           = apr_table_make(r->pool, 5);
1379 
1380     r->request_config  = ap_create_request_config(r->pool);
1381     /* Must be set before we run create request hook */
1382 
1383     r->proto_output_filters = conn->output_filters;
1384     r->output_filters  = r->proto_output_filters;
1385     r->proto_input_filters = conn->input_filters;
1386     r->input_filters   = r->proto_input_filters;
1387     ap_run_create_request(r);
1388     r->per_dir_config  = r->server->lookup_defaults;
1389 
1390     r->sent_bodyct     = 0;                      /* bytect isn't for body */
1391 
1392     r->read_length     = 0;
1393     r->read_body       = REQUEST_NO_BODY;
1394 
1395     r->status          = HTTP_OK;  /* Until further notice */
1396     r->header_only     = 0;
1397     r->the_request     = NULL;
1398 
1399     /* Begin by presuming any module can make its own path_info assumptions,
1400      * until some module interjects and changes the value.
1401      */
1402     r->used_path_info = AP_REQ_DEFAULT_PATH_INFO;
1403 
1404     r->useragent_addr = conn->client_addr;
1405     r->useragent_ip = conn->client_ip;
1406 
1407     return r;
1408 }
1409 
1410 /* Apply the server's timeout/config to the connection/request. */
apply_server_config(request_rec * r)1411 static void apply_server_config(request_rec *r)
1412 {
1413     apr_socket_t *csd;
1414 
1415     csd = ap_get_conn_socket(r->connection);
1416     apr_socket_timeout_set(csd, r->server->timeout);
1417 
1418     r->per_dir_config = r->server->lookup_defaults;
1419 }
1420 
ap_read_request(conn_rec * conn)1421 request_rec *ap_read_request(conn_rec *conn)
1422 {
1423     int access_status;
1424     apr_bucket_brigade *tmp_bb;
1425 
1426     request_rec *r = ap_create_request(conn);
1427 
1428     tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
1429     conn->keepalive = AP_CONN_UNKNOWN;
1430 
1431     ap_run_pre_read_request(r, conn);
1432 
1433     /* Get the request... */
1434     if (!read_request_line(r, tmp_bb) || !ap_parse_request_line(r)) {
1435         apr_brigade_cleanup(tmp_bb);
1436         switch (r->status) {
1437         case HTTP_REQUEST_URI_TOO_LARGE:
1438         case HTTP_BAD_REQUEST:
1439         case HTTP_VERSION_NOT_SUPPORTED:
1440         case HTTP_NOT_IMPLEMENTED:
1441             if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
1442                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00565)
1443                               "request failed: client's request-line exceeds LimitRequestLine (longer than %d)",
1444                               r->server->limit_req_line);
1445             }
1446             else if (r->method == NULL) {
1447                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00566)
1448                               "request failed: malformed request line");
1449             }
1450             access_status = r->status;
1451             goto die_unusable_input;
1452 
1453         case HTTP_REQUEST_TIME_OUT:
1454             /* Just log, no further action on this connection. */
1455             ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, NULL);
1456             if (!r->connection->keepalives)
1457                 ap_run_log_transaction(r);
1458             break;
1459         }
1460         /* Not worth dying with. */
1461         conn->keepalive = AP_CONN_CLOSE;
1462         apr_pool_destroy(r->pool);
1463         goto ignore;
1464     }
1465     apr_brigade_cleanup(tmp_bb);
1466 
1467     /* We may have been in keep_alive_timeout mode, so toggle back
1468      * to the normal timeout mode as we fetch the header lines,
1469      * as necessary.
1470      */
1471     apply_server_config(r);
1472 
1473     if (!r->assbackwards) {
1474         const char *tenc, *clen;
1475 
1476         ap_get_mime_headers_core(r, tmp_bb);
1477         apr_brigade_cleanup(tmp_bb);
1478         if (r->status != HTTP_OK) {
1479             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00567)
1480                           "request failed: error reading the headers");
1481             access_status = r->status;
1482             goto die_unusable_input;
1483         }
1484 
1485         clen = apr_table_get(r->headers_in, "Content-Length");
1486         if (clen) {
1487             apr_off_t cl;
1488 
1489             if (!ap_parse_strict_length(&cl, clen)) {
1490                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(10242)
1491                               "client sent invalid Content-Length "
1492                               "(%s): %s", clen, r->uri);
1493                 access_status = HTTP_BAD_REQUEST;
1494                 goto die_unusable_input;
1495             }
1496         }
1497 
1498         tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
1499         if (tenc) {
1500             /* https://tools.ietf.org/html/rfc7230
1501              * Section 3.3.3.3: "If a Transfer-Encoding header field is
1502              * present in a request and the chunked transfer coding is not
1503              * the final encoding ...; the server MUST respond with the 400
1504              * (Bad Request) status code and then close the connection".
1505              */
1506             if (!ap_is_chunked(r->pool, tenc)) {
1507                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02539)
1508                               "client sent unknown Transfer-Encoding "
1509                               "(%s): %s", tenc, r->uri);
1510                 access_status = HTTP_BAD_REQUEST;
1511                 goto die_unusable_input;
1512             }
1513 
1514             /* https://tools.ietf.org/html/rfc7230
1515              * Section 3.3.3.3: "If a message is received with both a
1516              * Transfer-Encoding and a Content-Length header field, the
1517              * Transfer-Encoding overrides the Content-Length. ... A sender
1518              * MUST remove the received Content-Length field".
1519              */
1520             if (clen) {
1521                 apr_table_unset(r->headers_in, "Content-Length");
1522 
1523                 /* Don't reuse this connection anyway to avoid confusion with
1524                  * intermediaries and request/reponse spltting.
1525                  */
1526                 conn->keepalive = AP_CONN_CLOSE;
1527             }
1528         }
1529     }
1530 
1531     /*
1532      * Add the HTTP_IN filter here to ensure that ap_discard_request_body
1533      * called by ap_die and by ap_send_error_response works correctly on
1534      * status codes that do not cause the connection to be dropped and
1535      * in situations where the connection should be kept alive.
1536      */
1537     ap_add_input_filter_handle(ap_http_input_filter_handle,
1538                                NULL, r, r->connection);
1539 
1540     /* Validate Host/Expect headers and select vhost. */
1541     if (!ap_check_request_header(r)) {
1542         /* we may have switched to another server still */
1543         apply_server_config(r);
1544         access_status = r->status;
1545         goto die_before_hooks;
1546     }
1547 
1548     /* we may have switched to another server */
1549     apply_server_config(r);
1550 
1551     if ((access_status = ap_post_read_request(r))) {
1552         goto die;
1553     }
1554 
1555     AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method,
1556                             (char *)r->uri, (char *)r->server->defn_name,
1557                             r->status);
1558     return r;
1559 
1560     /* Everything falls through on failure */
1561 
1562 die_unusable_input:
1563     /* Input filters are in an undeterminate state, cleanup (including
1564      * CORE_IN's socket) such that any further attempt to read is EOF.
1565      */
1566     {
1567         ap_filter_t *f = conn->input_filters;
1568         while (f) {
1569             if (f->frec == ap_core_input_filter_handle) {
1570                 core_net_rec *net = f->ctx;
1571                 apr_brigade_cleanup(net->in_ctx->b);
1572                 break;
1573             }
1574             ap_remove_input_filter(f);
1575             f = f->next;
1576         }
1577         conn->input_filters = r->input_filters = f;
1578         conn->keepalive = AP_CONN_CLOSE;
1579     }
1580 
1581 die_before_hooks:
1582     /* First call to ap_die() (non recursive) */
1583     r->status = HTTP_OK;
1584 
1585 die:
1586     ap_die(access_status, r);
1587 
1588     /* ap_die() sent the response through the output filters, we must now
1589      * end the request with an EOR bucket for stream/pipeline accounting.
1590      */
1591     {
1592         apr_bucket_brigade *eor_bb;
1593         eor_bb = apr_brigade_create(conn->pool, conn->bucket_alloc);
1594         APR_BRIGADE_INSERT_TAIL(eor_bb,
1595                                 ap_bucket_eor_create(conn->bucket_alloc, r));
1596         ap_pass_brigade(conn->output_filters, eor_bb);
1597         apr_brigade_cleanup(eor_bb);
1598     }
1599 
1600 ignore:
1601     r = NULL;
1602     AP_READ_REQUEST_FAILURE((uintptr_t)r);
1603     return NULL;
1604 }
1605 
ap_post_read_request(request_rec * r)1606 AP_DECLARE(int) ap_post_read_request(request_rec *r)
1607 {
1608     int status;
1609 
1610     if ((status = ap_run_post_read_request(r))) {
1611         return status;
1612     }
1613 
1614     /* Enforce http(s) only scheme for non-forward-proxy requests */
1615     if (!r->proxyreq
1616             && r->parsed_uri.scheme
1617             && (ap_cstr_casecmpn(r->parsed_uri.scheme, "http", 4) != 0
1618                 || (r->parsed_uri.scheme[4] != '\0'
1619                     && (apr_tolower(r->parsed_uri.scheme[4]) != 's'
1620                         || r->parsed_uri.scheme[5] != '\0')))) {
1621         return HTTP_BAD_REQUEST;
1622     }
1623 
1624     return OK;
1625 }
1626 
1627 /* if a request with a body creates a subrequest, remove original request's
1628  * input headers which pertain to the body which has already been read.
1629  * out-of-line helper function for ap_set_sub_req_protocol.
1630  */
1631 
strip_headers_request_body(request_rec * rnew)1632 static void strip_headers_request_body(request_rec *rnew)
1633 {
1634     apr_table_unset(rnew->headers_in, "Content-Encoding");
1635     apr_table_unset(rnew->headers_in, "Content-Language");
1636     apr_table_unset(rnew->headers_in, "Content-Length");
1637     apr_table_unset(rnew->headers_in, "Content-Location");
1638     apr_table_unset(rnew->headers_in, "Content-MD5");
1639     apr_table_unset(rnew->headers_in, "Content-Range");
1640     apr_table_unset(rnew->headers_in, "Content-Type");
1641     apr_table_unset(rnew->headers_in, "Expires");
1642     apr_table_unset(rnew->headers_in, "Last-Modified");
1643     apr_table_unset(rnew->headers_in, "Transfer-Encoding");
1644 }
1645 
1646 /*
1647  * A couple of other functions which initialize some of the fields of
1648  * a request structure, as appropriate for adjuncts of one kind or another
1649  * to a request in progress.  Best here, rather than elsewhere, since
1650  * *someone* has to set the protocol-specific fields...
1651  */
1652 
ap_set_sub_req_protocol(request_rec * rnew,const request_rec * r)1653 AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew,
1654                                          const request_rec *r)
1655 {
1656     rnew->the_request     = r->the_request;  /* Keep original request-line */
1657 
1658     rnew->assbackwards    = 1;   /* Don't send headers from this. */
1659     rnew->no_local_copy   = 1;   /* Don't try to send HTTP_NOT_MODIFIED for a
1660                                   * fragment. */
1661     rnew->method          = "GET";
1662     rnew->method_number   = M_GET;
1663     rnew->protocol        = "INCLUDED";
1664 
1665     rnew->status          = HTTP_OK;
1666 
1667     rnew->headers_in      = apr_table_copy(rnew->pool, r->headers_in);
1668     rnew->trailers_in     = apr_table_copy(rnew->pool, r->trailers_in);
1669 
1670     /* did the original request have a body?  (e.g. POST w/SSI tags)
1671      * if so, make sure the subrequest doesn't inherit body headers
1672      */
1673     if (!r->kept_body && (apr_table_get(r->headers_in, "Content-Length")
1674         || apr_table_get(r->headers_in, "Transfer-Encoding"))) {
1675         strip_headers_request_body(rnew);
1676     }
1677     rnew->subprocess_env  = apr_table_copy(rnew->pool, r->subprocess_env);
1678     rnew->headers_out     = apr_table_make(rnew->pool, 5);
1679     rnew->err_headers_out = apr_table_make(rnew->pool, 5);
1680     rnew->trailers_out    = apr_table_make(rnew->pool, 5);
1681     rnew->notes           = apr_table_make(rnew->pool, 5);
1682 
1683     rnew->expecting_100   = r->expecting_100;
1684     rnew->read_length     = r->read_length;
1685     rnew->read_body       = REQUEST_NO_BODY;
1686 
1687     rnew->main = (request_rec *) r;
1688 }
1689 
end_output_stream(request_rec * r,int status)1690 static void end_output_stream(request_rec *r, int status)
1691 {
1692     conn_rec *c = r->connection;
1693     apr_bucket_brigade *bb;
1694     apr_bucket *b;
1695 
1696     bb = apr_brigade_create(r->pool, c->bucket_alloc);
1697     if (status != OK) {
1698         b = ap_bucket_error_create(status, NULL, r->pool, c->bucket_alloc);
1699         APR_BRIGADE_INSERT_TAIL(bb, b);
1700     }
1701     b = apr_bucket_eos_create(c->bucket_alloc);
1702     APR_BRIGADE_INSERT_TAIL(bb, b);
1703 
1704     ap_pass_brigade(r->output_filters, bb);
1705     apr_brigade_cleanup(bb);
1706 }
1707 
ap_finalize_sub_req_protocol(request_rec * sub)1708 AP_DECLARE(void) ap_finalize_sub_req_protocol(request_rec *sub)
1709 {
1710     /* tell the filter chain there is no more content coming */
1711     if (!sub->eos_sent) {
1712         end_output_stream(sub, OK);
1713     }
1714 }
1715 
1716 /* finalize_request_protocol is called at completion of sending the
1717  * response.  Its sole purpose is to send the terminating protocol
1718  * information for any wrappers around the response message body
1719  * (i.e., transfer encodings).  It should have been named finalize_response.
1720  */
ap_finalize_request_protocol(request_rec * r)1721 AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r)
1722 {
1723     int status = ap_discard_request_body(r);
1724 
1725     /* tell the filter chain there is no more content coming */
1726     if (!r->eos_sent) {
1727         end_output_stream(r, status);
1728     }
1729 }
1730 
1731 /*
1732  * Support for the Basic authentication protocol, and a bit for Digest.
1733  */
ap_note_auth_failure(request_rec * r)1734 AP_DECLARE(void) ap_note_auth_failure(request_rec *r)
1735 {
1736     const char *type = ap_auth_type(r);
1737     if (type) {
1738         ap_run_note_auth_failure(r, type);
1739     }
1740     else {
1741         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00571)
1742                       "need AuthType to note auth failure: %s", r->uri);
1743     }
1744 }
1745 
ap_note_basic_auth_failure(request_rec * r)1746 AP_DECLARE(void) ap_note_basic_auth_failure(request_rec *r)
1747 {
1748     ap_note_auth_failure(r);
1749 }
1750 
ap_note_digest_auth_failure(request_rec * r)1751 AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r)
1752 {
1753     ap_note_auth_failure(r);
1754 }
1755 
ap_get_basic_auth_pw(request_rec * r,const char ** pw)1756 AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
1757 {
1758     const char *auth_line = apr_table_get(r->headers_in,
1759                                           (PROXYREQ_PROXY == r->proxyreq)
1760                                               ? "Proxy-Authorization"
1761                                               : "Authorization");
1762     const char *t;
1763 
1764     if (!(t = ap_auth_type(r)) || ap_cstr_casecmp(t, "Basic"))
1765         return DECLINED;
1766 
1767     if (!ap_auth_name(r)) {
1768         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00572)
1769                       "need AuthName: %s", r->uri);
1770         return HTTP_INTERNAL_SERVER_ERROR;
1771     }
1772 
1773     if (!auth_line) {
1774         ap_note_auth_failure(r);
1775         return HTTP_UNAUTHORIZED;
1776     }
1777 
1778     if (ap_cstr_casecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
1779         /* Client tried to authenticate using wrong auth scheme */
1780         ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00573)
1781                       "client used wrong authentication scheme: %s", r->uri);
1782         ap_note_auth_failure(r);
1783         return HTTP_UNAUTHORIZED;
1784     }
1785 
1786     while (*auth_line == ' ' || *auth_line == '\t') {
1787         auth_line++;
1788     }
1789 
1790     t = ap_pbase64decode(r->pool, auth_line);
1791     r->user = ap_getword_nulls (r->pool, &t, ':');
1792     apr_table_setn(r->notes, AP_GET_BASIC_AUTH_PW_NOTE, "1");
1793     r->ap_auth_type = "Basic";
1794 
1795     *pw = t;
1796 
1797     return OK;
1798 }
1799 
ap_get_basic_auth_components(const request_rec * r,const char ** username,const char ** password)1800 AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r,
1801                                                       const char **username,
1802                                                       const char **password)
1803 {
1804     const char *auth_header;
1805     const char *credentials;
1806     const char *decoded;
1807     const char *user;
1808 
1809     auth_header = (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization"
1810                                                   : "Authorization";
1811     credentials = apr_table_get(r->headers_in, auth_header);
1812 
1813     if (!credentials) {
1814         /* No auth header. */
1815         return APR_EINVAL;
1816     }
1817 
1818     if (ap_cstr_casecmp(ap_getword(r->pool, &credentials, ' '), "Basic")) {
1819         /* These aren't Basic credentials. */
1820         return APR_EINVAL;
1821     }
1822 
1823     while (*credentials == ' ' || *credentials == '\t') {
1824         credentials++;
1825     }
1826 
1827     /* XXX Our base64 decoding functions don't actually error out if the string
1828      * we give it isn't base64; they'll just silently stop and hand us whatever
1829      * they've parsed up to that point.
1830      *
1831      * Since this function is supposed to be a drop-in replacement for the
1832      * deprecated ap_get_basic_auth_pw(), don't fix this for 2.4.x.
1833      */
1834     decoded = ap_pbase64decode(r->pool, credentials);
1835     user = ap_getword_nulls(r->pool, &decoded, ':');
1836 
1837     if (username) {
1838         *username = user;
1839     }
1840     if (password) {
1841         *password = decoded;
1842     }
1843 
1844     return APR_SUCCESS;
1845 }
1846 
1847 struct content_length_ctx {
1848     int data_sent;  /* true if the C-L filter has already sent at
1849                      * least one bucket on to the next output filter
1850                      * for this request
1851                      */
1852     apr_bucket_brigade *tmpbb;
1853 };
1854 
1855 /* This filter computes the content length, but it also computes the number
1856  * of bytes sent to the client.  This means that this filter will always run
1857  * through all of the buckets in all brigades
1858  */
ap_content_length_filter(ap_filter_t * f,apr_bucket_brigade * b)1859 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(
1860     ap_filter_t *f,
1861     apr_bucket_brigade *b)
1862 {
1863     request_rec *r = f->r;
1864     struct content_length_ctx *ctx;
1865     apr_bucket *e;
1866     int eos = 0;
1867     apr_read_type_e eblock = APR_NONBLOCK_READ;
1868 
1869     ctx = f->ctx;
1870     if (!ctx) {
1871         f->ctx = ctx = apr_palloc(r->pool, sizeof(*ctx));
1872         ctx->data_sent = 0;
1873         ctx->tmpbb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
1874     }
1875 
1876     /* Loop through the brigade to count the length. To avoid
1877      * arbitrary memory consumption with morphing bucket types, this
1878      * loop will stop and pass on the brigade when necessary. */
1879     e = APR_BRIGADE_FIRST(b);
1880     while (e != APR_BRIGADE_SENTINEL(b)) {
1881         apr_status_t rv;
1882 
1883         if (APR_BUCKET_IS_EOS(e)) {
1884             eos = 1;
1885             break;
1886         }
1887         /* For a flush bucket, fall through to pass the brigade and
1888          * flush now. */
1889         else if (APR_BUCKET_IS_FLUSH(e)) {
1890             e = APR_BUCKET_NEXT(e);
1891         }
1892         /* For metadata bucket types other than FLUSH, loop. */
1893         else if (APR_BUCKET_IS_METADATA(e)) {
1894             e = APR_BUCKET_NEXT(e);
1895             continue;
1896         }
1897         /* For determinate length data buckets, count the length and
1898          * continue. */
1899         else if (e->length != (apr_size_t)-1) {
1900             r->bytes_sent += e->length;
1901             e = APR_BUCKET_NEXT(e);
1902             continue;
1903         }
1904         /* For indeterminate length data buckets, perform one read. */
1905         else /* e->length == (apr_size_t)-1 */ {
1906             apr_size_t len;
1907             const char *ignored;
1908 
1909             rv = apr_bucket_read(e, &ignored, &len, eblock);
1910             if ((rv != APR_SUCCESS) && !APR_STATUS_IS_EAGAIN(rv)) {
1911                 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00574)
1912                               "ap_content_length_filter: "
1913                               "apr_bucket_read() failed");
1914                 return rv;
1915             }
1916             if (rv == APR_SUCCESS) {
1917                 eblock = APR_NONBLOCK_READ;
1918                 e = APR_BUCKET_NEXT(e);
1919                 r->bytes_sent += len;
1920             }
1921             else if (APR_STATUS_IS_EAGAIN(rv)) {
1922                 apr_bucket *flush;
1923 
1924                 /* Next read must block. */
1925                 eblock = APR_BLOCK_READ;
1926 
1927                 /* Ensure the last bucket to pass down is a flush if
1928                  * the next read will block. */
1929                 flush = apr_bucket_flush_create(f->c->bucket_alloc);
1930                 APR_BUCKET_INSERT_BEFORE(e, flush);
1931             }
1932         }
1933 
1934         /* Optimization: if the next bucket is EOS (directly after a
1935          * bucket morphed to the heap, or a flush), short-cut to
1936          * handle EOS straight away - allowing C-L to be determined
1937          * for content which is already entirely in memory. */
1938         if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) {
1939             continue;
1940         }
1941 
1942         /* On reaching here, pass on everything in the brigade up to
1943          * this point. */
1944         apr_brigade_split_ex(b, e, ctx->tmpbb);
1945 
1946         rv = ap_pass_brigade(f->next, b);
1947         if (rv != APR_SUCCESS) {
1948             return rv;
1949         }
1950         else if (f->c->aborted) {
1951             return APR_ECONNABORTED;
1952         }
1953         apr_brigade_cleanup(b);
1954         APR_BRIGADE_CONCAT(b, ctx->tmpbb);
1955         e = APR_BRIGADE_FIRST(b);
1956 
1957         ctx->data_sent = 1;
1958     }
1959 
1960     /* If we've now seen the entire response and it's otherwise
1961      * okay to set the C-L in the response header, then do so now.
1962      *
1963      * We can only set a C-L in the response header if we haven't already
1964      * sent any buckets on to the next output filter for this request.
1965      */
1966     if (ctx->data_sent == 0 && eos &&
1967         /* don't whack the C-L if it has already been set for a HEAD
1968          * by something like proxy.  the brigade only has an EOS bucket
1969          * in this case, making r->bytes_sent zero.
1970          *
1971          * if r->bytes_sent > 0 we have a (temporary) body whose length may
1972          * have been changed by a filter.  the C-L header might not have been
1973          * updated so we do it here.  long term it would be cleaner to have
1974          * such filters update or remove the C-L header, and just use it
1975          * if present.
1976          */
1977         !((r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)) && r->bytes_sent == 0 &&
1978             apr_table_get(r->headers_out, "Content-Length"))) {
1979         ap_set_content_length(r, r->bytes_sent);
1980     }
1981 
1982     ctx->data_sent = 1;
1983     return ap_pass_brigade(f->next, b);
1984 }
1985 
1986 /*
1987  * Send the body of a response to the client.
1988  */
ap_send_fd(apr_file_t * fd,request_rec * r,apr_off_t offset,apr_size_t len,apr_size_t * nbytes)1989 AP_DECLARE(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r,
1990                                     apr_off_t offset, apr_size_t len,
1991                                     apr_size_t *nbytes)
1992 {
1993     conn_rec *c = r->connection;
1994     apr_bucket_brigade *bb = NULL;
1995     apr_status_t rv;
1996 
1997     bb = apr_brigade_create(r->pool, c->bucket_alloc);
1998 
1999     apr_brigade_insert_file(bb, fd, offset, len, r->pool);
2000 
2001     rv = ap_pass_brigade(r->output_filters, bb);
2002     if (rv != APR_SUCCESS) {
2003         *nbytes = 0; /* no way to tell how many were actually sent */
2004     }
2005     else {
2006         *nbytes = len;
2007     }
2008 
2009     return rv;
2010 }
2011 
2012 #if APR_HAS_MMAP
2013 /* send data from an in-memory buffer */
ap_send_mmap(apr_mmap_t * mm,request_rec * r,apr_size_t offset,apr_size_t length)2014 AP_DECLARE(apr_size_t) ap_send_mmap(apr_mmap_t *mm,
2015                                     request_rec *r,
2016                                     apr_size_t offset,
2017                                     apr_size_t length)
2018 {
2019     conn_rec *c = r->connection;
2020     apr_bucket_brigade *bb = NULL;
2021     apr_bucket *b;
2022 
2023     bb = apr_brigade_create(r->pool, c->bucket_alloc);
2024     b = apr_bucket_mmap_create(mm, offset, length, c->bucket_alloc);
2025     APR_BRIGADE_INSERT_TAIL(bb, b);
2026     ap_pass_brigade(r->output_filters, bb);
2027 
2028     return mm->size; /* XXX - change API to report apr_status_t? */
2029 }
2030 #endif /* APR_HAS_MMAP */
2031 
2032 typedef struct {
2033     apr_bucket_brigade *bb;
2034     apr_bucket_brigade *tmpbb;
2035 } old_write_filter_ctx;
2036 
ap_old_write_filter(ap_filter_t * f,apr_bucket_brigade * bb)2037 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
2038     ap_filter_t *f, apr_bucket_brigade *bb)
2039 {
2040     old_write_filter_ctx *ctx = f->ctx;
2041 
2042     AP_DEBUG_ASSERT(ctx);
2043 
2044     if (ctx->bb != NULL) {
2045         /* whatever is coming down the pipe (we don't care), we
2046          * can simply insert our buffered data at the front and
2047          * pass the whole bundle down the chain.
2048          */
2049         APR_BRIGADE_PREPEND(bb, ctx->bb);
2050     }
2051 
2052     return ap_pass_brigade(f->next, bb);
2053 }
2054 
insert_old_write_filter(request_rec * r)2055 static ap_filter_t *insert_old_write_filter(request_rec *r)
2056 {
2057     ap_filter_t *f;
2058     old_write_filter_ctx *ctx;
2059 
2060     /* future optimization: record some flags in the request_rec to
2061      * say whether we've added our filter, and whether it is first.
2062      */
2063 
2064     /* this will typically exit on the first test */
2065     for (f = r->output_filters; f != NULL; f = f->next) {
2066         if (ap_old_write_func == f->frec)
2067             break;
2068     }
2069 
2070     if (f == NULL) {
2071         /* our filter hasn't been added yet */
2072         ctx = apr_pcalloc(r->pool, sizeof(*ctx));
2073         ctx->tmpbb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2074 
2075         ap_add_output_filter("OLD_WRITE", ctx, r, r->connection);
2076         f = r->output_filters;
2077     }
2078 
2079     return f;
2080 }
2081 
buffer_output(request_rec * r,const char * str,apr_size_t len)2082 static apr_status_t buffer_output(request_rec *r,
2083                                   const char *str, apr_size_t len)
2084 {
2085     conn_rec *c = r->connection;
2086     ap_filter_t *f;
2087     old_write_filter_ctx *ctx;
2088 
2089     if (len == 0)
2090         return APR_SUCCESS;
2091 
2092     f = insert_old_write_filter(r);
2093     ctx = f->ctx;
2094 
2095     /* if the first filter is not our buffering filter, then we have to
2096      * deliver the content through the normal filter chain
2097      */
2098     if (f != r->output_filters) {
2099         apr_status_t rv;
2100         apr_bucket *b = apr_bucket_transient_create(str, len, c->bucket_alloc);
2101         APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, b);
2102 
2103         rv = ap_pass_brigade(r->output_filters, ctx->tmpbb);
2104         apr_brigade_cleanup(ctx->tmpbb);
2105         return rv;
2106     }
2107 
2108     if (ctx->bb == NULL) {
2109         ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
2110     }
2111 
2112     return ap_fwrite(f->next, ctx->bb, str, len);
2113 }
2114 
ap_rputc(int c,request_rec * r)2115 AP_DECLARE(int) ap_rputc(int c, request_rec *r)
2116 {
2117     char c2 = (char)c;
2118 
2119     if (r->connection->aborted) {
2120         return -1;
2121     }
2122 
2123     if (buffer_output(r, &c2, 1) != APR_SUCCESS)
2124         return -1;
2125 
2126     return c;
2127 }
2128 
ap_rwrite(const void * buf,int nbyte,request_rec * r)2129 AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
2130 {
2131     if (r->connection->aborted)
2132         return -1;
2133 
2134     if (buffer_output(r, buf, nbyte) != APR_SUCCESS)
2135         return -1;
2136 
2137     return nbyte;
2138 }
2139 
2140 struct ap_vrprintf_data {
2141     apr_vformatter_buff_t vbuff;
2142     request_rec *r;
2143     char *buff;
2144 };
2145 
2146 /* Flush callback for apr_vformatter; returns -1 on error. */
r_flush(apr_vformatter_buff_t * buff)2147 static int r_flush(apr_vformatter_buff_t *buff)
2148 {
2149     /* callback function passed to ap_vformatter to be called when
2150      * vformatter needs to write into buff and buff.curpos > buff.endpos */
2151 
2152     /* ap_vrprintf_data passed as a apr_vformatter_buff_t, which is then
2153      * "downcast" to an ap_vrprintf_data */
2154     struct ap_vrprintf_data *vd = (struct ap_vrprintf_data*)buff;
2155 
2156     if (vd->r->connection->aborted)
2157         return -1;
2158 
2159     /* r_flush is called when vbuff is completely full */
2160     if (buffer_output(vd->r, vd->buff, AP_IOBUFSIZE)) {
2161         return -1;
2162     }
2163 
2164     /* reset the buffer position */
2165     vd->vbuff.curpos = vd->buff;
2166     vd->vbuff.endpos = vd->buff + AP_IOBUFSIZE;
2167 
2168     return 0;
2169 }
2170 
ap_vrprintf(request_rec * r,const char * fmt,va_list va)2171 AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va)
2172 {
2173     int written;
2174     struct ap_vrprintf_data vd;
2175     char vrprintf_buf[AP_IOBUFSIZE];
2176 
2177     vd.vbuff.curpos = vrprintf_buf;
2178     vd.vbuff.endpos = vrprintf_buf + AP_IOBUFSIZE;
2179     vd.r = r;
2180     vd.buff = vrprintf_buf;
2181 
2182     if (r->connection->aborted)
2183         return -1;
2184 
2185     written = apr_vformatter(r_flush, &vd.vbuff, fmt, va);
2186 
2187     if (written != -1) {
2188         int n = vd.vbuff.curpos - vrprintf_buf;
2189 
2190         /* last call to buffer_output, to finish clearing the buffer */
2191         if (buffer_output(r, vrprintf_buf, n) != APR_SUCCESS)
2192             return -1;
2193 
2194         written += n;
2195     }
2196 
2197     return written;
2198 }
2199 
ap_rprintf(request_rec * r,const char * fmt,...)2200 AP_DECLARE_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt, ...)
2201 {
2202     va_list va;
2203     int n;
2204 
2205     if (r->connection->aborted)
2206         return -1;
2207 
2208     va_start(va, fmt);
2209     n = ap_vrprintf(r, fmt, va);
2210     va_end(va);
2211 
2212     return n;
2213 }
2214 
ap_rvputs(request_rec * r,...)2215 AP_DECLARE_NONSTD(int) ap_rvputs(request_rec *r, ...)
2216 {
2217     va_list va;
2218     const char *s;
2219     apr_size_t len;
2220     apr_size_t written = 0;
2221 
2222     if (r->connection->aborted)
2223         return -1;
2224 
2225     /* ### TODO: if the total output is large, put all the strings
2226      * ### into a single brigade, rather than flushing each time we
2227      * ### fill the buffer
2228      */
2229     va_start(va, r);
2230     while (1) {
2231         s = va_arg(va, const char *);
2232         if (s == NULL)
2233             break;
2234 
2235         len = strlen(s);
2236         if (buffer_output(r, s, len) != APR_SUCCESS) {
2237             va_end(va);
2238             return -1;
2239         }
2240 
2241         written += len;
2242     }
2243     va_end(va);
2244 
2245     return written;
2246 }
2247 
ap_rflush(request_rec * r)2248 AP_DECLARE(int) ap_rflush(request_rec *r)
2249 {
2250     conn_rec *c = r->connection;
2251     apr_bucket *b;
2252     ap_filter_t *f;
2253     old_write_filter_ctx *ctx;
2254     apr_status_t rv;
2255 
2256     f = insert_old_write_filter(r);
2257     ctx = f->ctx;
2258 
2259     b = apr_bucket_flush_create(c->bucket_alloc);
2260     APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, b);
2261 
2262     rv = ap_pass_brigade(r->output_filters, ctx->tmpbb);
2263     apr_brigade_cleanup(ctx->tmpbb);
2264     if (rv != APR_SUCCESS)
2265         return -1;
2266 
2267     return 0;
2268 }
2269 
2270 /*
2271  * This function sets the Last-Modified output header field to the value
2272  * of the mtime field in the request structure - rationalized to keep it from
2273  * being in the future.
2274  */
ap_set_last_modified(request_rec * r)2275 AP_DECLARE(void) ap_set_last_modified(request_rec *r)
2276 {
2277     if (!r->assbackwards) {
2278         apr_time_t mod_time = ap_rationalize_mtime(r, r->mtime);
2279         char *datestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
2280 
2281         apr_rfc822_date(datestr, mod_time);
2282         apr_table_setn(r->headers_out, "Last-Modified", datestr);
2283     }
2284 }
2285 
2286 typedef struct hdr_ptr {
2287     ap_filter_t *f;
2288     apr_bucket_brigade *bb;
2289 } hdr_ptr;
2290 
2291 #if APR_CHARSET_EBCDIC
send_header(void * data,const char * key,const char * val)2292 static int send_header(void *data, const char *key, const char *val)
2293 {
2294     char *header_line = NULL;
2295     hdr_ptr *hdr = (hdr_ptr*)data;
2296 
2297     header_line = apr_pstrcat(hdr->bb->p, key, ": ", val, CRLF, NULL);
2298     ap_xlate_proto_to_ascii(header_line, strlen(header_line));
2299     ap_fputs(hdr->f, hdr->bb, header_line);
2300     return 1;
2301 }
2302 #else
send_header(void * data,const char * key,const char * val)2303 static int send_header(void *data, const char *key, const char *val)
2304 {
2305      ap_fputstrs(((hdr_ptr*)data)->f, ((hdr_ptr*)data)->bb,
2306                  key, ": ", val, CRLF, NULL);
2307      return 1;
2308  }
2309 #endif
2310 
ap_send_interim_response(request_rec * r,int send_headers)2311 AP_DECLARE(void) ap_send_interim_response(request_rec *r, int send_headers)
2312 {
2313     hdr_ptr x;
2314     char *response_line = NULL;
2315     const char *status_line;
2316     request_rec *rr;
2317 
2318     if (r->proto_num < HTTP_VERSION(1,1)) {
2319         /* don't send interim response to HTTP/1.0 Client */
2320         return;
2321     }
2322     if (!ap_is_HTTP_INFO(r->status)) {
2323         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00575)
2324                       "Status is %d - not sending interim response", r->status);
2325         return;
2326     }
2327     if (r->status == HTTP_CONTINUE) {
2328         if (!r->expecting_100) {
2329             /*
2330              * Don't send 100-Continue when there was no Expect: 100-continue
2331              * in the request headers. For origin servers this is a SHOULD NOT
2332              * for proxies it is a MUST NOT according to RFC 2616 8.2.3
2333              */
2334             return;
2335         }
2336 
2337         /* if we send an interim response, we're no longer in a state of
2338          * expecting one.  Also, this could feasibly be in a subrequest,
2339          * so we need to propagate the fact that we responded.
2340          */
2341         for (rr = r; rr != NULL; rr = rr->main) {
2342             rr->expecting_100 = 0;
2343         }
2344     }
2345 
2346     status_line = r->status_line;
2347     if (status_line == NULL) {
2348         status_line = ap_get_status_line_ex(r->pool, r->status);
2349     }
2350     response_line = apr_pstrcat(r->pool,
2351                                 AP_SERVER_PROTOCOL " ", status_line, CRLF,
2352                                 NULL);
2353     ap_xlate_proto_to_ascii(response_line, strlen(response_line));
2354 
2355     x.f = r->connection->output_filters;
2356     x.bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2357 
2358     ap_fputs(x.f, x.bb, response_line);
2359     if (send_headers) {
2360         apr_table_do(send_header, &x, r->headers_out, NULL);
2361         apr_table_clear(r->headers_out);
2362     }
2363     ap_fputs(x.f, x.bb, CRLF_ASCII);
2364     ap_fflush(x.f, x.bb);
2365     apr_brigade_destroy(x.bb);
2366 }
2367 
2368 /*
2369  * Compare two protocol identifier. Result is similar to strcmp():
2370  * 0 gives same precedence, >0 means proto1 is preferred.
2371  */
protocol_cmp(const apr_array_header_t * preferences,const char * proto1,const char * proto2)2372 static int protocol_cmp(const apr_array_header_t *preferences,
2373                         const char *proto1,
2374                         const char *proto2)
2375 {
2376     if (preferences && preferences->nelts > 0) {
2377         int index1 = ap_array_str_index(preferences, proto1, 0);
2378         int index2 = ap_array_str_index(preferences, proto2, 0);
2379         if (index2 > index1) {
2380             return (index1 >= 0) ? 1 : -1;
2381         }
2382         else if (index1 > index2) {
2383             return (index2 >= 0) ? -1 : 1;
2384         }
2385     }
2386     /* both have the same index (maybe -1 or no pref configured) and we compare
2387      * the names so that spdy3 gets precedence over spdy2. That makes
2388      * the outcome at least deterministic. */
2389     return strcmp(proto1, proto2);
2390 }
2391 
ap_get_protocol(conn_rec * c)2392 AP_DECLARE(const char *) ap_get_protocol(conn_rec *c)
2393 {
2394     const char *protocol = ap_run_protocol_get(c);
2395     return protocol? protocol : AP_PROTOCOL_HTTP1;
2396 }
2397 
ap_get_protocol_upgrades(conn_rec * c,request_rec * r,server_rec * s,int report_all,const apr_array_header_t ** pupgrades)2398 AP_DECLARE(apr_status_t) ap_get_protocol_upgrades(conn_rec *c, request_rec *r,
2399                                                   server_rec *s, int report_all,
2400                                                   const apr_array_header_t **pupgrades)
2401 {
2402     apr_pool_t *pool = r? r->pool : c->pool;
2403     core_server_config *conf;
2404     const char *existing;
2405     apr_array_header_t *upgrades = NULL;
2406 
2407     if (!s) {
2408         s = (r? r->server : c->base_server);
2409     }
2410     conf = ap_get_core_module_config(s->module_config);
2411 
2412     if (conf->protocols->nelts > 0) {
2413         existing = ap_get_protocol(c);
2414         if (conf->protocols->nelts > 1
2415             || !ap_array_str_contains(conf->protocols, existing)) {
2416             int i;
2417 
2418             /* possibly more than one choice or one, but not the
2419              * existing. (TODO: maybe 426 and Upgrade then?) */
2420             upgrades = apr_array_make(pool, conf->protocols->nelts + 1,
2421                                       sizeof(char *));
2422             for (i = 0; i < conf->protocols->nelts; i++) {
2423                 const char *p = APR_ARRAY_IDX(conf->protocols, i, char *);
2424                 if (strcmp(existing, p)) {
2425                     /* not the one we have and possible, add in this order */
2426                     APR_ARRAY_PUSH(upgrades, const char*) = p;
2427                 }
2428                 else if (!report_all) {
2429                     break;
2430                 }
2431             }
2432         }
2433     }
2434 
2435     *pupgrades = upgrades;
2436     return APR_SUCCESS;
2437 }
2438 
ap_select_protocol(conn_rec * c,request_rec * r,server_rec * s,const apr_array_header_t * choices)2439 AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r,
2440                                             server_rec *s,
2441                                             const apr_array_header_t *choices)
2442 {
2443     apr_pool_t *pool = r? r->pool : c->pool;
2444     core_server_config *conf;
2445     const char *protocol = NULL, *existing;
2446     apr_array_header_t *proposals;
2447 
2448     if (!s) {
2449         s = (r? r->server : c->base_server);
2450     }
2451     conf = ap_get_core_module_config(s->module_config);
2452 
2453     if (APLOGcdebug(c)) {
2454         const char *p = apr_array_pstrcat(pool, conf->protocols, ',');
2455         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03155)
2456                       "select protocol from %s, choices=%s for server %s",
2457                       p, apr_array_pstrcat(pool, choices, ','),
2458                       s->server_hostname);
2459     }
2460 
2461     if (conf->protocols->nelts <= 0) {
2462         /* nothing configured, by default, we only allow http/1.1 here.
2463          * For now...
2464          */
2465         if (ap_array_str_contains(choices, AP_PROTOCOL_HTTP1)) {
2466             return AP_PROTOCOL_HTTP1;
2467         }
2468         else {
2469             return NULL;
2470         }
2471     }
2472 
2473     proposals = apr_array_make(pool, choices->nelts + 1, sizeof(char *));
2474     ap_run_protocol_propose(c, r, s, choices, proposals);
2475 
2476     /* If the existing protocol has not been proposed, but is a choice,
2477      * add it to the proposals implicitly.
2478      */
2479     existing = ap_get_protocol(c);
2480     if (!ap_array_str_contains(proposals, existing)
2481         && ap_array_str_contains(choices, existing)) {
2482         APR_ARRAY_PUSH(proposals, const char*) = existing;
2483     }
2484 
2485     if (proposals->nelts > 0) {
2486         int i;
2487         const apr_array_header_t *prefs = NULL;
2488 
2489         /* Default for protocols_honor_order is 'on' or != 0 */
2490         if (conf->protocols_honor_order == 0 && choices->nelts > 0) {
2491             prefs = choices;
2492         }
2493         else {
2494             prefs = conf->protocols;
2495         }
2496 
2497         /* Select the most preferred protocol */
2498         if (APLOGcdebug(c)) {
2499             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03156)
2500                           "select protocol, proposals=%s preferences=%s configured=%s",
2501                           apr_array_pstrcat(pool, proposals, ','),
2502                           apr_array_pstrcat(pool, prefs, ','),
2503                           apr_array_pstrcat(pool, conf->protocols, ','));
2504         }
2505         for (i = 0; i < proposals->nelts; ++i) {
2506             const char *p = APR_ARRAY_IDX(proposals, i, const char *);
2507             if (!ap_array_str_contains(conf->protocols, p)) {
2508                 /* not a configured protocol here */
2509                 continue;
2510             }
2511             else if (!protocol
2512                      || (protocol_cmp(prefs, protocol, p) < 0)) {
2513                 /* none selected yet or this one has preference */
2514                 protocol = p;
2515             }
2516         }
2517     }
2518     if (APLOGcdebug(c)) {
2519         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03157)
2520                       "selected protocol=%s",
2521                       protocol? protocol : "(none)");
2522     }
2523 
2524     return protocol;
2525 }
2526 
ap_switch_protocol(conn_rec * c,request_rec * r,server_rec * s,const char * protocol)2527 AP_DECLARE(apr_status_t) ap_switch_protocol(conn_rec *c, request_rec *r,
2528                                             server_rec *s,
2529                                             const char *protocol)
2530 {
2531     const char *current = ap_get_protocol(c);
2532     int rc;
2533 
2534     if (!strcmp(current, protocol)) {
2535         ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(02906)
2536                       "already at it, protocol_switch to %s",
2537                       protocol);
2538         return APR_SUCCESS;
2539     }
2540 
2541     rc = ap_run_protocol_switch(c, r, s, protocol);
2542     switch (rc) {
2543         case DECLINED:
2544             ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02907)
2545                           "no implementation for protocol_switch to %s",
2546                           protocol);
2547             return APR_ENOTIMPL;
2548         case OK:
2549         case DONE:
2550             return APR_SUCCESS;
2551         default:
2552             ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02905)
2553                           "unexpected return code %d from protocol_switch to %s"
2554                           , rc, protocol);
2555             return APR_EOF;
2556     }
2557 }
2558 
ap_is_allowed_protocol(conn_rec * c,request_rec * r,server_rec * s,const char * protocol)2559 AP_DECLARE(int) ap_is_allowed_protocol(conn_rec *c, request_rec *r,
2560                                        server_rec *s, const char *protocol)
2561 {
2562     core_server_config *conf;
2563 
2564     if (!s) {
2565         s = (r? r->server : c->base_server);
2566     }
2567     conf = ap_get_core_module_config(s->module_config);
2568 
2569     if (conf->protocols->nelts > 0) {
2570         return ap_array_str_contains(conf->protocols, protocol);
2571     }
2572     return !strcmp(AP_PROTOCOL_HTTP1, protocol);
2573 }
2574 
2575 
2576 AP_IMPLEMENT_HOOK_VOID(pre_read_request,
2577                        (request_rec *r, conn_rec *c),
2578                        (r, c))
2579 AP_IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,
2580                           (request_rec *r), (r), OK, DECLINED)
2581 AP_IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,
2582                           (request_rec *r), (r), OK, DECLINED)
2583 AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,http_scheme,
2584                             (const request_rec *r), (r), NULL)
2585 AP_IMPLEMENT_HOOK_RUN_FIRST(unsigned short,default_port,
2586                             (const request_rec *r), (r), 0)
2587 AP_IMPLEMENT_HOOK_RUN_FIRST(int, note_auth_failure,
2588                             (request_rec *r, const char *auth_type),
2589                             (r, auth_type), DECLINED)
2590 AP_IMPLEMENT_HOOK_RUN_ALL(int,protocol_propose,
2591                           (conn_rec *c, request_rec *r, server_rec *s,
2592                            const apr_array_header_t *offers,
2593                            apr_array_header_t *proposals),
2594                           (c, r, s, offers, proposals), OK, DECLINED)
2595 AP_IMPLEMENT_HOOK_RUN_FIRST(int,protocol_switch,
2596                             (conn_rec *c, request_rec *r, server_rec *s,
2597                              const char *protocol),
2598                             (c, r, s, protocol), DECLINED)
2599 AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,protocol_get,
2600                             (const conn_rec *c), (c), NULL)
2601