1 /**	$MirOS: src/usr.sbin/httpd/src/main/http_protocol.c,v 1.13 2010/09/21 21:24:40 tg Exp $ */
2 /*	$OpenBSD: http_protocol.c,v 1.32 2008/01/24 11:56:29 krw Exp $ */
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  *    if any, must include the following acknowledgment:
23  *       "This product includes software developed by the
24  *        Apache Software Foundation (http://www.apache.org/)."
25  *    Alternately, this acknowledgment may appear in the software itself,
26  *    if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" must
29  *    not be used to endorse or promote products derived from this
30  *    software without prior written permission. For written
31  *    permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  *    nor may "Apache" appear in their name, without prior written
35  *    permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation.  For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  *
56  * Portions of this software are based upon public domain software
57  * originally written at the National Center for Supercomputing Applications,
58  * University of Illinois, Urbana-Champaign.
59  */
60 
61 /*
62  * http_protocol.c --- routines which directly communicate with the client.
63  *
64  * Code originally by Rob McCool; much redone by Robert S. Thau
65  * and the Apache Group.
66  */
67 
68 #define CORE_PRIVATE
69 #include "httpd.h"
70 #include "http_config.h"
71 #include "http_core.h"
72 #include "http_protocol.h"
73 #include "http_main.h"
74 #include "http_request.h"
75 #include "http_vhost.h"
76 #include "http_log.h"           /* For errors detected in basic auth common
77                                  * support code... */
78 #include "util_date.h"          /* For parseHTTPdate and BAD_DATE */
79 #include <stdarg.h>
80 #include "http_conf_globals.h"
81 #include "util_md5.h"           /* For digestAuth */
82 #include "ap_sha1.h"
83 
84 __RCSID("$MirOS: src/usr.sbin/httpd/src/main/http_protocol.c,v 1.13 2010/09/21 21:24:40 tg Exp $");
85 
86 #define SET_BYTES_SENT(r) \
87   do { if (r->sent_bodyct) \
88           ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
89   } while (0)
90 
91 /*
92  * Builds the content-type that should be sent to the client from the
93  * content-type specified.  The following rules are followed:
94  *    - if type is NULL, type is set to ap_default_type(r)
95  *    - if charset adding is disabled, stop processing and return type.
96  *    - then, if there are no parameters on type, add the default charset
97  *    - return type
98  */
make_content_type(request_rec * r,const char * type)99 static const char *make_content_type(request_rec *r, const char *type) {
100     char *needcset[] = {
101 	"text/plain",
102 	"text/html",
103 	NULL };
104     char **pcset;
105     core_dir_config *conf;
106 
107     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
108                                                    &core_module);
109     if (!type) {
110         type = ap_default_type(r);
111     }
112     if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) {
113         return type;
114     }
115 
116     if (ap_strcasestr(type, "charset=") != NULL) {
117 	/* already has parameter, do nothing */
118 	/* XXX we don't check the validity */
119 	;
120     }
121     else {
122     	/* see if it makes sense to add the charset. At present,
123 	 * we only add it if the Content-type is one of needcset[]
124 	 */
125 	for (pcset = needcset; *pcset ; pcset++) {
126 	    if (ap_strcasestr(type, *pcset) != NULL) {
127 		type = ap_pstrcat(r->pool, type, "; charset=",
128                                   conf->add_default_charset_name, NULL);
129 		break;
130 	    }
131         }
132     }
133     return type;
134 }
135 
136 enum byterange_token {
137     BYTERANGE_OK,
138     BYTERANGE_EMPTY,
139     BYTERANGE_BADSYNTAX,
140     BYTERANGE_UNSATISFIABLE
141 };
142 
143 static enum byterange_token
parse_byterange(request_rec * r,long * start,long * end)144     parse_byterange(request_rec *r, long *start, long *end)
145 {
146     /* parsing first, semantics later */
147 
148     while (ap_isspace(*r->range))
149         ++r->range;
150 
151     /* check for an empty range, which is OK */
152     if (*r->range == '\0') {
153 	return BYTERANGE_EMPTY;
154     }
155     else if (*r->range == ',') {
156 	++r->range;
157 	return BYTERANGE_EMPTY;
158     }
159 
160     if (isdigit((unsigned char)*r->range))
161 	*start = ap_strtol(r->range, (char **)&r->range, 10);
162     else
163 	*start = -1;
164 
165     while (ap_isspace(*r->range))
166         ++r->range;
167 
168     if (*r->range != '-')
169 	return BYTERANGE_BADSYNTAX;
170     ++r->range;
171 
172     while (ap_isspace(*r->range))
173         ++r->range;
174 
175     if (isdigit((unsigned char)*r->range))
176 	*end = ap_strtol(r->range, (char **)&r->range, 10);
177     else
178 	*end = -1;
179 
180     while (ap_isspace(*r->range))
181         ++r->range;
182 
183     /* check the end of the range */
184     if (*r->range == ',') {
185 	++r->range;
186     }
187     else if (*r->range != '\0') {
188 	return BYTERANGE_BADSYNTAX;
189     }
190 
191     /* parsing done; now check the numbers */
192 
193     if (*start < 0) { /* suffix-byte-range-spec */
194 	if (*end < 0) /* no numbers */
195 	    return BYTERANGE_BADSYNTAX;
196 	*start = r->clength - *end;
197 	if (*start < 0)
198 	    *start = 0;
199 	*end = r->clength - 1;
200     }
201     else {
202 	if (*end >= 0 && *start > *end) /* out-of-order range */
203 	    return BYTERANGE_BADSYNTAX;
204 	if (*end < 0 || *end >= r->clength)
205 	    *end = r->clength - 1;
206     }
207     /* RFC 2616 is somewhat unclear about what we should do if the end
208      * is missing and the start is after the clength. The robustness
209      * principle says we should accept it as an unsatisfiable range.
210      * We accept suffix-byte-range-specs like -0 for the same reason.
211      */
212     if (*start >= r->clength)
213 	return BYTERANGE_UNSATISFIABLE;
214 
215     return BYTERANGE_OK;
216 }
217 
218 /* If this function is called with output=1, it will spit out the
219  * correct headers for a byterange chunk. If output=0 it will not
220  * output anything but just return the number of bytes it would have
221  * output. If start or end are less than 0 then it will do a byterange
222  * chunk trailer instead of a header.
223  */
byterange_boundary(request_rec * r,long start,long end,int output)224 static int byterange_boundary(request_rec *r, long start, long end, int output)
225 {
226     int length = 0;
227 
228     if (start < 0 || end < 0) {
229 	if (output)
230 	    ap_rvputs(r, CRLF "--", r->boundary, "--" CRLF, NULL);
231 	else
232 	    length = 4 + strlen(r->boundary) + 4;
233     }
234     else {
235 	const char *ct = make_content_type(r, r->content_type);
236 	char ts[MAX_STRING_LEN];
237 
238 	snprintf(ts, sizeof(ts), "%ld-%ld/%ld", start, end, r->clength);
239 	if (output)
240 	    ap_rvputs(r, CRLF "--", r->boundary, CRLF "Content-type: ",
241 		      ct, CRLF "Content-range: bytes ", ts, CRLF CRLF,
242 		      NULL);
243 	else
244 	    length = 4 + strlen(r->boundary) + 16
245 		+ strlen(ct) + 23 + strlen(ts) + 4;
246     }
247 
248     return length;
249 }
250 
ap_set_byterange(request_rec * r)251 API_EXPORT(int) ap_set_byterange(request_rec *r)
252 {
253     const char *range, *if_range, *match;
254     char *bbuf, *b;
255     u_int32_t rbuf[12]; /* 48 bytes yields 64 base64 chars */
256     long length, start, end, one_start = 0, one_end = 0;
257     size_t u;
258     int ranges, empty;
259 
260     if (!r->clength || r->assbackwards)
261         return 0;
262 
263     /* Check for Range request-header (HTTP/1.1) or Request-Range for
264      * backwards-compatibility with second-draft Luotonen/Franks
265      * byte-ranges (e.g. Netscape Navigator 2-3).
266      *
267      * We support this form, with Request-Range, and (farther down) we
268      * send multipart/x-byteranges instead of multipart/byteranges for
269      * Request-Range based requests to work around a bug in Netscape
270      * Navigator 2-3 and MSIE 3.
271      */
272 
273     if (!(range = ap_table_get(r->headers_in, "Range")))
274         range = ap_table_get(r->headers_in, "Request-Range");
275 
276     if (!range || strncasecmp(range, "bytes=", 6)) {
277         return 0;
278     }
279     range += 6;
280 
281     /* Check the If-Range header for Etag or Date.
282      * Note that this check will return false (as required) if either
283      * of the two etags are weak.
284      */
285     if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
286         if (if_range[0] == '"') {
287             if (!(match = ap_table_get(r->headers_out, "Etag")) ||
288                 (strcmp(if_range, match) != 0))
289                 return 0;
290         }
291         else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||
292                  (strcmp(if_range, match) != 0))
293             return 0;
294     }
295 
296     /*
297      * Parse the byteranges, counting how many of them there are and
298      * the total number of bytes we will send to the client. This is a
299      * dummy run for the while(ap_each_byterange()) loop that the
300      * caller will perform if we return 1.
301      */
302     r->range = range;
303     arc4random_buf(rbuf, sizeof(rbuf));
304     bbuf = ap_palloc(r->pool, ap_base64encode_len(sizeof(rbuf)));
305     ap_base64encode(bbuf, (const unsigned char *)rbuf, sizeof(rbuf));
306     for (b = bbuf; *b != '\0'; b++) {
307         if (((b - bbuf) + 1) % 7 == 0)
308             *b = '-';
309         else if (!isalnum(*b))
310             *b = 'a';
311     }
312 
313     r->boundary = bbuf;
314 
315     length = 0;
316     ranges = 0;
317     empty = 1;
318     do {
319 	switch (parse_byterange(r, &start, &end)) {
320 	case BYTERANGE_UNSATISFIABLE:
321 	    empty = 0;
322 	    break;
323 	default:
324 	    /* be more defensive here? */
325 	case BYTERANGE_BADSYNTAX:
326 	    r->boundary = NULL;
327 	    r->range = NULL;
328 	    return 0;
329 	case BYTERANGE_EMPTY:
330 	    break;
331 	case BYTERANGE_OK:
332 	    ++ranges;
333 	    length += byterange_boundary(r, start, end, 0)
334 		+ end - start + 1;
335 	    /* save in case of unsatisfiable ranges */
336 	    one_start = start;
337 	    one_end = end;
338 	    break;
339 	}
340     } while (*r->range != '\0');
341 
342     if (ranges == 0) {
343 	/* no ranges or only unsatisfiable ranges */
344 	if (empty || if_range) {
345 	    r->boundary = NULL;
346 	    r->range = NULL;
347 	    return 0;
348 	}
349 	else {
350 	    ap_table_setn(r->headers_out, "Content-Range",
351 		ap_psprintf(r->pool, "bytes */%ld", r->clength));
352 	    ap_set_content_length(r, 0);
353 	    r->boundary = NULL;
354 	    r->range = range;
355 	    r->header_only = 1;
356 	    r->status = HTTP_RANGE_NOT_SATISFIABLE;
357 	    return 1;
358 	}
359     }
360     else if (ranges == 1) {
361 	/* simple handling of a single range -- no boundaries */
362         ap_table_setn(r->headers_out, "Content-Range",
363 	    ap_psprintf(r->pool, "bytes %ld-%ld/%ld",
364 		one_start, one_end, r->clength));
365 	ap_table_setn(r->headers_out, "Content-Length",
366 	    ap_psprintf(r->pool, "%ld", one_end - one_start + 1));
367 	r->boundary = NULL;
368 	r->byterange = 1;
369 	r->range = range;
370 	r->status = PARTIAL_CONTENT;
371 	return 1;
372     }
373     else {
374 	/* multiple ranges */
375 	length += byterange_boundary(r, -1, -1, 0);
376 	ap_table_setn(r->headers_out, "Content-Length",
377 	    ap_psprintf(r->pool, "%ld", length));
378 	r->byterange = 2;
379 	r->range = range;
380 	r->status = PARTIAL_CONTENT;
381 	return 1;
382     }
383 }
384 
ap_each_byterange(request_rec * r,long * offset,long * length)385 API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length)
386 {
387     long start, end;
388 
389     do {
390 	if (parse_byterange(r, &start, &end) == BYTERANGE_OK) {
391 	    if (r->byterange > 1)
392 		byterange_boundary(r, start, end, 1);
393 	    *offset = start;
394 	    *length = end - start + 1;
395 	    return 1;
396 	}
397     } while (*r->range != '\0');
398     if (r->byterange > 1)
399 	byterange_boundary(r, -1, -1, 1);
400     return 0;
401 }
402 
ap_set_content_length(request_rec * r,long clength)403 API_EXPORT(int) ap_set_content_length(request_rec *r, long clength)
404 {
405     r->clength = clength;
406     ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength));
407     return 0;
408 }
409 
ap_set_keepalive(request_rec * r)410 API_EXPORT(int) ap_set_keepalive(request_rec *r)
411 {
412     int ka_sent = 0;
413     int wimpy = ap_find_token(r->pool,
414                            ap_table_get(r->headers_out, "Connection"), "close");
415     const char *conn = ap_table_get(r->headers_in, "Connection");
416 
417     /* The following convoluted conditional determines whether or not
418      * the current connection should remain persistent after this response
419      * (a.k.a. HTTP Keep-Alive) and whether or not the output message
420      * body should use the HTTP/1.1 chunked transfer-coding.  In English,
421      *
422      *   IF  we have not marked this connection as errored;
423      *   and the response body has a defined length due to the status code
424      *       being 304 or 204, the request method being HEAD, already
425      *       having defined Content-Length or Transfer-Encoding: chunked, or
426      *       the request version being HTTP/1.1 and thus capable of being set
427      *       as chunked [we know the (r->chunked = 1) side-effect is ugly];
428      *   and the server configuration enables keep-alive;
429      *   and the server configuration has a reasonable inter-request timeout;
430      *   and there is no maximum # requests or the max hasn't been reached;
431      *   and the response status does not require a close;
432      *   and the response generator has not already indicated close;
433      *   and the client did not request non-persistence (Connection: close);
434      *   and    we haven't been configured to ignore the buggy twit
435      *       or they're a buggy twit coming through a HTTP/1.1 proxy
436      *   and    the client is requesting an HTTP/1.0-style keep-alive
437      *       or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
438      *   THEN we can be persistent, which requires more headers be output.
439      *
440      * Note that the condition evaluation order is extremely important.
441      */
442     if ((r->connection->keepalive != -1) &&
443         ((r->status == HTTP_NOT_MODIFIED) ||
444          (r->status == HTTP_NO_CONTENT) ||
445          r->header_only ||
446          ap_table_get(r->headers_out, "Content-Length") ||
447          ap_find_last_token(r->pool,
448                          ap_table_get(r->headers_out, "Transfer-Encoding"),
449                          "chunked") ||
450          ((r->proto_num >= HTTP_VERSION(1,1)) &&
451 	  (r->chunked = 1))) && /* THIS CODE IS CORRECT, see comment above. */
452         r->server->keep_alive &&
453         (r->server->keep_alive_timeout > 0) &&
454         ((r->server->keep_alive_max == 0) ||
455          (r->server->keep_alive_max > r->connection->keepalives)) &&
456         !ap_status_drops_connection(r->status) &&
457         !wimpy &&
458         !ap_find_token(r->pool, conn, "close") &&
459         (!ap_table_get(r->subprocess_env, "nokeepalive") ||
460          ap_table_get(r->headers_in, "Via")) &&
461         ((ka_sent = ap_find_token(r->pool, conn, "keep-alive")) ||
462          (r->proto_num >= HTTP_VERSION(1,1)))
463        ) {
464         int left = r->server->keep_alive_max - r->connection->keepalives;
465 
466         r->connection->keepalive = 1;
467         r->connection->keepalives++;
468 
469         /* If they sent a Keep-Alive token, send one back */
470         if (ka_sent) {
471             if (r->server->keep_alive_max)
472 		ap_table_setn(r->headers_out, "Keep-Alive",
473 		    ap_psprintf(r->pool, "timeout=%d, max=%d",
474                             r->server->keep_alive_timeout, left));
475             else
476 		ap_table_setn(r->headers_out, "Keep-Alive",
477 		    ap_psprintf(r->pool, "timeout=%d",
478                             r->server->keep_alive_timeout));
479             ap_table_mergen(r->headers_out, "Connection", "Keep-Alive");
480         }
481 
482         return 1;
483     }
484 
485     /* Otherwise, we need to indicate that we will be closing this
486      * connection immediately after the current response.
487      *
488      * We only really need to send "close" to HTTP/1.1 clients, but we
489      * always send it anyway, because a broken proxy may identify itself
490      * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
491      * to a HTTP/1.1 client. Better safe than sorry.
492      */
493     if (!wimpy)
494 	ap_table_mergen(r->headers_out, "Connection", "close");
495 
496     r->connection->keepalive = 0;
497 
498     return 0;
499 }
500 
501 /*
502  * Return the latest rational time from a request/mtime (modification time)
503  * pair.  We return the mtime unless it's in the future, in which case we
504  * return the current time.  We use the request time as a reference in order
505  * to limit the number of calls to time().  We don't check for futurosity
506  * unless the mtime is at least as new as the reference.
507  */
ap_rationalize_mtime(request_rec * r,time_t mtime)508 API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime)
509 {
510     time_t now;
511 
512     /* For all static responses, it's almost certain that the file was
513      * last modified before the beginning of the request.  So there's
514      * no reason to call time(NULL) again.  But if the response has been
515      * created on demand, then it might be newer than the time the request
516      * started.  In this event we really have to call time(NULL) again
517      * so that we can give the clients the most accurate Last-Modified.  If we
518      * were given a time in the future, we return the current time - the
519      * Last-Modified can't be in the future.
520      */
521     now = (mtime < r->request_time) ? r->request_time : time(NULL);
522     return (mtime > now) ? now : mtime;
523 }
524 
ap_meets_conditions(request_rec * r)525 API_EXPORT(int) ap_meets_conditions(request_rec *r)
526 {
527     const char *etag = ap_table_get(r->headers_out, "ETag");
528     const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
529     time_t mtime;
530 
531     /* Check for conditional requests --- note that we only want to do
532      * this if we are successful so far and we are not processing a
533      * subrequest or an ErrorDocument.
534      *
535      * The order of the checks is important, since ETag checks are supposed
536      * to be more accurate than checks relative to the modification time.
537      * However, not all documents are guaranteed to *have* ETags, and some
538      * might have Last-Modified values w/o ETags, so this gets a little
539      * complicated.
540      */
541 
542     if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
543         return OK;
544     }
545 
546     mtime = (r->mtime != 0) ? r->mtime : time(NULL);
547 
548     /* If an If-Match request-header field was given
549      * AND the field value is not "*" (meaning match anything)
550      * AND if our strong ETag does not match any entity tag in that field,
551      *     respond with a status of 412 (Precondition Failed).
552      */
553     if ((if_match = ap_table_get(r->headers_in, "If-Match")) != NULL) {
554         if (if_match[0] != '*' &&
555             (etag == NULL || etag[0] == 'W' ||
556              !ap_find_list_item(r->pool, if_match, etag))) {
557             return HTTP_PRECONDITION_FAILED;
558         }
559     }
560     else {
561         /* Else if a valid If-Unmodified-Since request-header field was given
562          * AND the requested resource has been modified since the time
563          * specified in this field, then the server MUST
564          *     respond with a status of 412 (Precondition Failed).
565          */
566         if_unmodified = ap_table_get(r->headers_in, "If-Unmodified-Since");
567         if (if_unmodified != NULL) {
568             time_t ius = ap_parseHTTPdate(if_unmodified);
569 
570             if ((ius != BAD_DATE) && (mtime > ius)) {
571                 return HTTP_PRECONDITION_FAILED;
572             }
573         }
574     }
575 
576     /* If an If-None-Match request-header field was given
577      * AND the field value is "*" (meaning match anything)
578      *     OR our ETag matches any of the entity tags in that field, fail.
579      *
580      * If the request method was GET or HEAD, failure means the server
581      *    SHOULD respond with a 304 (Not Modified) response.
582      * For all other request methods, failure means the server MUST
583      *    respond with a status of 412 (Precondition Failed).
584      *
585      * GET or HEAD allow weak etag comparison, all other methods require
586      * strong comparison.  We can only use weak if it's not a range request.
587      */
588     if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
589     if (if_nonematch != NULL) {
590         if (r->method_number == M_GET) {
591             if (if_nonematch[0] == '*')
592                 return HTTP_NOT_MODIFIED;
593             if (etag != NULL) {
594                 if (ap_table_get(r->headers_in, "Range")) {
595                     if (etag[0] != 'W' &&
596                         ap_find_list_item(r->pool, if_nonematch, etag)) {
597                         return HTTP_NOT_MODIFIED;
598                     }
599                 }
600                 else if (strstr(if_nonematch, etag)) {
601                     return HTTP_NOT_MODIFIED;
602                 }
603             }
604         }
605         else if (if_nonematch[0] == '*' ||
606                  (etag != NULL &&
607                   ap_find_list_item(r->pool, if_nonematch, etag))) {
608             return HTTP_PRECONDITION_FAILED;
609         }
610     }
611     /* Else if a valid If-Modified-Since request-header field was given
612      * AND it is a GET or HEAD request
613      * AND the requested resource has not been modified since the time
614      * specified in this field, then the server MUST
615      *    respond with a status of 304 (Not Modified).
616      * A date later than the server's current request time is invalid.
617      */
618     else if ((r->method_number == M_GET)
619              && ((if_modified_since =
620                   ap_table_get(r->headers_in, "If-Modified-Since")) != NULL)) {
621         time_t ims = ap_parseHTTPdate(if_modified_since);
622 
623         if ((ims >= mtime) && (ims <= r->request_time)) {
624             return HTTP_NOT_MODIFIED;
625         }
626     }
627     return OK;
628 }
629 
630 /*
631  * Construct an entity tag (ETag) from resource information.  If it's a real
632  * file, build in some of the file characteristics.  If the modification time
633  * is newer than (request-time minus 1 second), mark the ETag as weak - it
634  * could be modified again in as short an interval.  We rationalize the
635  * modification time we're given to keep it from being in the future.
636  */
ap_make_etag_orig(request_rec * r,int force_weak)637 API_EXPORT(char *) ap_make_etag_orig(request_rec *r, int force_weak)
638 {
639     char *etag;
640     char *weak;
641     core_dir_config *cfg;
642     etag_components_t etag_bits;
643 
644     cfg = (core_dir_config *)ap_get_module_config(r->per_dir_config,
645                                                   &core_module);
646     etag_bits = (cfg->etag_bits & (~ cfg->etag_remove)) | cfg->etag_add;
647     if (etag_bits == ETAG_UNSET) {
648         etag_bits = ETAG_BACKWARD;
649     }
650     /*
651      * Make an ETag header out of various pieces of information. We use
652      * the last-modified date and, if we have a real file, the
653      * length and inode number - note that this doesn't have to match
654      * the content-length (i.e. includes), it just has to be unique
655      * for the file.
656      *
657      * If the request was made within a second of the last-modified date,
658      * we send a weak tag instead of a strong one, since it could
659      * be modified again later in the second, and the validation
660      * would be incorrect.
661      */
662 
663     weak = ((r->request_time - r->mtime > 1) && !force_weak) ? "" : "W/";
664 
665     if (r->finfo.st_mode != 0) {
666         char **ent;
667         array_header *components;
668         int i;
669 
670         /*
671          * If it's a file (or we wouldn't be here) and no ETags
672          * should be set for files, return an empty string and
673          * note it for ap_send_header_field() to ignore.
674          */
675         if (etag_bits & ETAG_NONE) {
676             ap_table_setn(r->notes, "no-etag", "omit");
677             return "";
678         }
679 
680         components = ap_make_array(r->pool, 4, sizeof(char *));
681         if (etag_bits & ETAG_INODE) {
682             ent = (char **) ap_push_array(components);
683             *ent = ap_psprintf(r->pool, "%lx",
684                                (unsigned long) r->finfo.st_ino);
685         }
686         if (etag_bits & ETAG_SIZE) {
687             ent = (char **) ap_push_array(components);
688             *ent = ap_psprintf(r->pool, "%lx",
689                                (unsigned long) r->finfo.st_size);
690         }
691         if (etag_bits & ETAG_MTIME) {
692             ent = (char **) ap_push_array(components);
693             *ent = ap_psprintf(r->pool, "%lx", (unsigned long) r->mtime);
694         }
695         ent = (char **) components->elts;
696         etag = ap_pstrcat(r->pool, weak, "\"", NULL);
697         for (i = 0; i < components->nelts; ++i) {
698             etag = ap_psprintf(r->pool, "%s%s%s", etag,
699                                (i == 0 ? "" : "-"),
700                                ent[i]);
701         }
702         etag = ap_pstrcat(r->pool, etag, "\"", NULL);
703     }
704     else {
705         etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,
706                     (unsigned long) r->mtime);
707     }
708 
709     return etag;
710 }
711 
ap_set_etag(request_rec * r)712 API_EXPORT(void) ap_set_etag(request_rec *r)
713 {
714     char *etag;
715     char *variant_etag, *vlv;
716     int vlv_weak;
717 
718     if (!r->vlist_validator) {
719         etag = ap_make_etag(r, 0);
720 
721         /* If we get a blank etag back, don't set the header. */
722         if (!etag[0]) {
723             return;
724         }
725     }
726     else {
727         /* If we have a variant list validator (vlv) due to the
728          * response being negotiated, then we create a structured
729          * entity tag which merges the variant etag with the variant
730          * list validator (vlv).  This merging makes revalidation
731          * somewhat safer, ensures that caches which can deal with
732          * Vary will (eventually) be updated if the set of variants is
733          * changed, and is also a protocol requirement for transparent
734          * content negotiation.
735          */
736 
737         /* if the variant list validator is weak, we make the whole
738          * structured etag weak.  If we would not, then clients could
739          * have problems merging range responses if we have different
740          * variants with the same non-globally-unique strong etag.
741          */
742 
743         vlv = r->vlist_validator;
744         vlv_weak = (vlv[0] == 'W');
745 
746         variant_etag = ap_make_etag(r, vlv_weak);
747 
748         /* If we get a blank etag back, don't append vlv and stop now. */
749         if (!variant_etag[0]) {
750             return;
751         }
752 
753         /* merge variant_etag and vlv into a structured etag */
754         variant_etag[strlen(variant_etag) - 1] = '\0';
755         if (vlv_weak)
756             vlv += 3;
757         else
758             vlv++;
759         etag = ap_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
760     }
761 
762     ap_table_setn(r->headers_out, "ETag", etag);
763 }
764 
765 /*
766  * This function sets the Last-Modified output header field to the value
767  * of the mtime field in the request structure - rationalized to keep it from
768  * being in the future.
769  */
ap_set_last_modified(request_rec * r)770 API_EXPORT(void) ap_set_last_modified(request_rec *r)
771 {
772     time_t mod_time = ap_rationalize_mtime(r, r->mtime);
773 
774     ap_table_setn(r->headers_out, "Last-Modified",
775               ap_gm_timestr_822(r->pool, mod_time));
776 }
777 
778 /* Get the method number associated with the given string, assumed to
779  * contain an HTTP method.  Returns M_INVALID if not recognized.
780  *
781  * This is the first step toward placing method names in a configurable
782  * list.  Hopefully it (and other routines) can eventually be moved to
783  * something like a mod_http_methods.c, complete with config stuff.
784  */
ap_method_number_of(const char * method)785 API_EXPORT(int) ap_method_number_of(const char *method)
786 {
787     switch (*method) {
788         case 'H':
789            if (strcmp(method, "HEAD") == 0)
790                return M_GET;   /* see header_only in request_rec */
791            break;
792         case 'G':
793            if (strcmp(method, "GET") == 0)
794                return M_GET;
795            break;
796         case 'P':
797            if (strcmp(method, "POST") == 0)
798                return M_POST;
799            if (strcmp(method, "PUT") == 0)
800                return M_PUT;
801            if (strcmp(method, "PATCH") == 0)
802                return M_PATCH;
803            if (strcmp(method, "PROPFIND") == 0)
804                return M_PROPFIND;
805            if (strcmp(method, "PROPPATCH") == 0)
806                return M_PROPPATCH;
807            break;
808         case 'D':
809            if (strcmp(method, "DELETE") == 0)
810                return M_DELETE;
811            break;
812         case 'C':
813            if (strcmp(method, "CONNECT") == 0)
814                return M_CONNECT;
815            if (strcmp(method, "COPY") == 0)
816                return M_COPY;
817            break;
818         case 'M':
819            if (strcmp(method, "MKCOL") == 0)
820                return M_MKCOL;
821            if (strcmp(method, "MOVE") == 0)
822                return M_MOVE;
823            break;
824         case 'O':
825            if (strcmp(method, "OPTIONS") == 0)
826                return M_OPTIONS;
827            break;
828         case 'L':
829            if (strcmp(method, "LOCK") == 0)
830                return M_LOCK;
831            break;
832         case 'U':
833            if (strcmp(method, "UNLOCK") == 0)
834                return M_UNLOCK;
835            break;
836     }
837     return M_INVALID;
838 }
839 
840 /* Get a line of protocol input, including any continuation lines
841  * caused by MIME folding (or broken clients) if fold != 0, and place it
842  * in the buffer s, of size n bytes, without the ending newline.
843  *
844  * Returns -1 on error, or the length of s.
845  *
846  * Note: Because bgets uses 1 char for newline and 1 char for NUL,
847  *       the most we can get is (n - 2) actual characters if it
848  *       was ended by a newline, or (n - 1) characters if the line
849  *       length exceeded (n - 1).  So, if the result == (n - 1),
850  *       then the actual input line exceeded the buffer length,
851  *       and it would be a good idea for the caller to puke 400 or 414.
852  */
ap_getline(char * s,int n,BUFF * in,int fold)853 API_EXPORT(int) ap_getline(char *s, int n, BUFF *in, int fold)
854 {
855     char *pos, next;
856     int retval;
857     int total = 0;
858 
859     pos = s;
860 
861     do {
862         retval = ap_bgets(pos, n, in);     /* retval == -1 if error, 0 if EOF */
863 
864         if (retval <= 0) {
865             total = ((retval < 0) && (total == 0)) ? -1 : total;
866             break;
867         }
868 
869         /* retval is the number of characters read, not including NUL      */
870 
871         n -= retval;            /* Keep track of how much of s is full     */
872         pos += (retval - 1);    /* and where s ends                        */
873         total += retval;        /* and how long s has become               */
874 
875         if (*pos == '\n') {     /* Did we get a full line of input?        */
876             /*
877              * Trim any extra trailing spaces or tabs except for the first
878              * space or tab at the beginning of a blank string.  This makes
879              * it much easier to check field values for exact matches, and
880              * saves memory as well.  Terminate string at end of line.
881              */
882             while (pos > (s + 1) && (*(pos - 1) == ' ' || *(pos - 1) == '\t')) {
883                 --pos;          /* trim extra trailing spaces or tabs      */
884                 --total;        /* but not one at the beginning of line    */
885                 ++n;
886             }
887             *pos = '\0';
888             --total;
889             ++n;
890         }
891         else
892             break;       /* if not, input line exceeded buffer size */
893 
894         /* Continue appending if line folding is desired and
895          * the last line was not empty and we have room in the buffer and
896          * the next line begins with a continuation character.
897          */
898     } while (fold && (retval != 1) && (n > 1)
899                   && (ap_blookc(&next, in) == 1)
900                   && ((next == ' ') || (next == '\t')));
901 
902     return total;
903 }
904 
905 /* parse_uri: break apart the uri
906  * Side Effects:
907  * - sets r->args to rest after '?' (or NULL if no '?')
908  * - sets r->uri to request uri (without r->args part)
909  * - sets r->hostname (if not set already) from request (scheme://host:port)
910  */
ap_parse_uri(request_rec * r,const char * uri)911 CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
912 {
913     int status = HTTP_OK;
914 
915     r->unparsed_uri = ap_pstrdup(r->pool, uri);
916 
917     if (r->method_number == M_CONNECT) {
918 	status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
919     } else {
920 	/* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
921 	status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
922     }
923 
924     if (ap_is_HTTP_SUCCESS(status)) {
925 	/* if it has a scheme we may need to do absoluteURI vhost stuff */
926 	if (r->parsed_uri.scheme
927 	    && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
928 	    r->hostname = r->parsed_uri.hostname;
929 	} else if (r->method_number == M_CONNECT) {
930 	    r->hostname = r->parsed_uri.hostname;
931 	}
932 	r->args = r->parsed_uri.query;
933 	r->uri = r->parsed_uri.path ? r->parsed_uri.path
934 				    : ap_pstrdup(r->pool, "/");
935     }
936     else {
937 	r->args = NULL;
938 	r->hostname = NULL;
939 	r->status = status;             /* set error status */
940 	r->uri = ap_pstrdup(r->pool, uri);
941     }
942 }
943 
read_request_line(request_rec * r)944 static int read_request_line(request_rec *r)
945 {
946     char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* ap_getline's two extra for \n\0 */
947     const char *ll = l;
948     const char *uri;
949     conn_rec *conn = r->connection;
950     unsigned int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
951     int len = 0;
952     int valid_protocol = 1;
953 
954     /* Read past empty lines until we get a real request line,
955      * a read error, the connection closes (EOF), or we timeout.
956      *
957      * We skip empty lines because browsers have to tack a CRLF on to the end
958      * of POSTs to support old CERN webservers.  But note that we may not
959      * have flushed any previous response completely to the client yet.
960      * We delay the flush as long as possible so that we can improve
961      * performance for clients that are pipelining requests.  If a request
962      * is pipelined then we won't block during the (implicit) read() below.
963      * If the requests aren't pipelined, then the client is still waiting
964      * for the final buffer flush from us, and we will block in the implicit
965      * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
966      * have to block during a read.
967      */
968     ap_bsetflag(conn->client, B_SAFEREAD, 1);
969     while ((len = ap_getline(l, sizeof(l), conn->client, 0)) <= 0) {
970         if ((len < 0) || ap_bgetflag(conn->client, B_EOF)) {
971             ap_bsetflag(conn->client, B_SAFEREAD, 0);
972 	    /* this is a hack to make sure that request time is set,
973 	     * it's not perfect, but it's better than nothing
974 	     */
975 	    r->request_time = time(0);
976             return 0;
977         }
978     }
979     /* we've probably got something to do, ignore graceful restart requests */
980     signal(SIGUSR1, SIG_IGN);
981 
982     ap_bsetflag(conn->client, B_SAFEREAD, 0);
983 
984     r->request_time = time(NULL);
985     r->the_request = ap_pstrdup(r->pool, l);
986     r->method = ap_getword_white(r->pool, &ll);
987     uri = ap_getword_white(r->pool, &ll);
988 
989     /* Provide quick information about the request method as soon as known */
990 
991     r->method_number = ap_method_number_of(r->method);
992     if (r->method_number == M_GET && r->method[0] == 'H') {
993         r->header_only = 1;
994     }
995 
996     ap_parse_uri(r, uri);
997 
998     /* ap_getline returns (size of max buffer - 1) if it fills up the
999      * buffer before finding the end-of-line.  This is only going to
1000      * happen if it exceeds the configured limit for a request-line.
1001      */
1002     if (len > r->server->limit_req_line) {
1003         r->status    = HTTP_REQUEST_URI_TOO_LARGE;
1004         r->proto_num = HTTP_VERSION(1,0);
1005         r->protocol  = ap_pstrdup(r->pool, "HTTP/1.0");
1006         return 0;
1007     }
1008 
1009     r->assbackwards = (ll[0] == '\0');
1010     r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
1011 
1012     /* Avoid sscanf in the common case */
1013     if (strlen(r->protocol) == 8
1014         && r->protocol[0] == 'H' && r->protocol[1] == 'T'
1015 	&& r->protocol[2] == 'T' && r->protocol[3] == 'P'
1016         && r->protocol[4] == '/' && isdigit((unsigned char)r->protocol[5])
1017 	&& r->protocol[6] == '.' && isdigit((unsigned char)r->protocol[7])) {
1018         r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
1019     }
1020     else {
1021         char lint[2];
1022         char http[5];
1023 	if (3 == sscanf(r->protocol, "%4s/%u.%u%1s", http, &major, &minor, lint)
1024             && (strcasecmp("http", http) == 0)
1025 	    && (minor < HTTP_VERSION(1,0)) ) /* don't allow HTTP/0.1000 */
1026 	    r->proto_num = HTTP_VERSION(major, minor);
1027 	else {
1028 	    r->proto_num = HTTP_VERSION(1,0);
1029 	    valid_protocol = 0;
1030 	}
1031     }
1032 
1033     /* Check for a valid protocol, and disallow everything but whitespace
1034      * after the protocol string. A protocol string of nothing but
1035      * whitespace is considered valid */
1036     if (ap_protocol_req_check && !valid_protocol) {
1037         int n = 0;
1038 	while (ap_isspace(r->protocol[n]))
1039 	    ++n;
1040 	if (r->protocol[n] != '\0') {
1041 	    r->status    = HTTP_BAD_REQUEST;
1042 	    r->proto_num = HTTP_VERSION(1,0);
1043 	    r->protocol  = ap_pstrdup(r->pool, "HTTP/1.0");
1044 	    ap_table_setn(r->notes, "error-notes",
1045                      "The request line contained invalid characters "
1046                      "following the protocol string.<P>\n");
1047 	    return 0;
1048 	}
1049     }
1050 
1051     return 1;
1052 }
1053 
get_mime_headers(request_rec * r)1054 static void get_mime_headers(request_rec *r)
1055 {
1056     char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* ap_getline's two extra */
1057     conn_rec *c = r->connection;
1058     char *value;
1059     char *copy;
1060     int len;
1061     int fields_read = 0;
1062     table *tmp_headers;
1063 
1064     /* We'll use ap_overlap_tables later to merge these into r->headers_in. */
1065     tmp_headers = ap_make_table(r->pool, 50);
1066 
1067     /*
1068      * Read header lines until we get the empty separator line, a read error,
1069      * the connection closes (EOF), reach the server limit, or we timeout.
1070      */
1071     while ((len = ap_getline(field, sizeof(field), c->client, 1)) > 0) {
1072 
1073         if (r->server->limit_req_fields &&
1074             (++fields_read > r->server->limit_req_fields)) {
1075             r->status = HTTP_BAD_REQUEST;
1076             ap_table_setn(r->notes, "error-notes",
1077                           "The number of request header fields exceeds "
1078                           "this server's limit.<P>\n");
1079             return;
1080         }
1081         /* ap_getline returns (size of max buffer - 1) if it fills up the
1082          * buffer before finding the end-of-line.  This is only going to
1083          * happen if it exceeds the configured limit for a field size.
1084          */
1085         if (len > r->server->limit_req_fieldsize) {
1086             r->status = HTTP_BAD_REQUEST;
1087             ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
1088                 "Size of a request header field exceeds server limit.<P>\n"
1089                 "<PRE>\n", ap_escape_html(r->pool, field), "</PRE>\n", NULL));
1090             return;
1091         }
1092         copy = ap_palloc(r->pool, len + 1);
1093         memcpy(copy, field, len + 1);
1094 
1095         if (!(value = strchr(copy, ':'))) {     /* Find the colon separator */
1096             r->status = HTTP_BAD_REQUEST;       /* or abort the bad request */
1097             ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
1098                 "Request header field is missing colon separator.<P>\n"
1099                 "<PRE>\n", ap_escape_html(r->pool, copy), "</PRE>\n", NULL));
1100             return;
1101         }
1102 
1103         *value = '\0';
1104         ++value;
1105         while (*value == ' ' || *value == '\t')
1106             ++value;            /* Skip to start of value   */
1107 
1108 	ap_table_addn(tmp_headers, copy, value);
1109     }
1110 
1111     ap_overlap_tables(r->headers_in, tmp_headers, AP_OVERLAP_TABLES_MERGE);
1112 }
1113 
ap_read_request(conn_rec * conn)1114 API_EXPORT(request_rec *) ap_read_request(conn_rec *conn)
1115 {
1116     request_rec *r;
1117     pool *p;
1118     const char *expect;
1119     int access_status;
1120 
1121     p = ap_make_sub_pool(conn->pool);
1122     r = ap_pcalloc(p, sizeof(request_rec));
1123     r->pool            = p;
1124     r->connection      = conn;
1125     conn->server       = conn->base_server;
1126     r->server          = conn->server;
1127 
1128     conn->keptalive    = conn->keepalive == 1;
1129     conn->keepalive    = 0;
1130 
1131     conn->user         = NULL;
1132     conn->ap_auth_type    = NULL;
1133 
1134     r->headers_in      = ap_make_table(r->pool, 50);
1135     r->subprocess_env  = ap_make_table(r->pool, 50);
1136     r->headers_out     = ap_make_table(r->pool, 12);
1137     r->err_headers_out = ap_make_table(r->pool, 5);
1138     r->notes           = ap_make_table(r->pool, 5);
1139 
1140     r->request_config  = ap_create_request_config(r->pool);
1141     r->per_dir_config  = r->server->lookup_defaults;
1142 
1143     r->sent_bodyct     = 0;                      /* bytect isn't for body */
1144 
1145     r->read_length     = 0;
1146     r->read_body       = REQUEST_NO_BODY;
1147 
1148     r->status          = HTTP_REQUEST_TIME_OUT;  /* Until we get a request */
1149     r->the_request     = NULL;
1150 
1151     r->ctx = ap_ctx_new(r->pool);
1152 
1153     switch (conn->remote_addr.ss_family) {
1154     case AF_INET:
1155 	ap_table_setn(r->notes, "address-family", "IPv4");
1156 	break;
1157 #ifdef INET6
1158     case AF_INET6:
1159 	ap_table_setn(r->notes, "address-family", "IPv6");
1160 	break;
1161 #endif
1162     }
1163 
1164     /* Get the request... */
1165 
1166     ap_keepalive_timeout("read request line", r);
1167     if (!read_request_line(r)) {
1168         ap_kill_timeout(r);
1169         if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
1170 
1171             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1172                          "request failed: URI too long");
1173             ap_send_error_response(r, 0);
1174             ap_log_transaction(r);
1175             return r;
1176         }
1177         else if (r->status == HTTP_BAD_REQUEST) {
1178             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1179                          "request failed: erroneous characters after protocol string: %s",
1180 			 ap_escape_logitem(r->pool, r->the_request));
1181             ap_send_error_response(r, 0);
1182             ap_log_transaction(r);
1183             return r;
1184         }
1185         return NULL;
1186     }
1187     if (!r->assbackwards) {
1188         ap_hard_timeout("read request headers", r);
1189         get_mime_headers(r);
1190         ap_kill_timeout(r);
1191         if (r->status != HTTP_REQUEST_TIME_OUT) {
1192             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1193                          "request failed: error reading the headers");
1194             ap_send_error_response(r, 0);
1195             ap_log_transaction(r);
1196             return r;
1197         }
1198     }
1199     else {
1200         ap_kill_timeout(r);
1201 
1202         if (r->header_only) {
1203             /*
1204              * Client asked for headers only with HTTP/0.9, which doesn't send
1205              * headers! Have to dink things just to make sure the error message
1206              * comes through...
1207              */
1208             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1209                           "client sent invalid HTTP/0.9 request: HEAD %s",
1210                           r->uri);
1211             r->header_only = 0;
1212             r->status = HTTP_BAD_REQUEST;
1213             ap_send_error_response(r, 0);
1214             ap_log_transaction(r);
1215             return r;
1216         }
1217     }
1218 
1219     r->status = HTTP_OK;                         /* Until further notice. */
1220 
1221     /* update what we think the virtual host is based on the headers we've
1222      * now read. may update status.
1223      */
1224     ap_update_vhost_from_headers(r);
1225 
1226     /* we may have switched to another server */
1227     r->per_dir_config = r->server->lookup_defaults;
1228 
1229     conn->keptalive = 0;        /* We now have a request to play with */
1230 
1231     if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) ||
1232         ((r->proto_num == HTTP_VERSION(1,1)) &&
1233          !ap_table_get(r->headers_in, "Host"))) {
1234         /*
1235          * Client sent us an HTTP/1.1 or later request without telling us the
1236          * hostname, either with a full URL or a Host: header. We therefore
1237          * need to (as per the 1.1 spec) send an error.  As a special case,
1238          * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
1239          * a Host: header, and the server MUST respond with 400 if it doesn't.
1240          */
1241         r->status = HTTP_BAD_REQUEST;
1242         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1243                       "client sent HTTP/1.1 request without hostname "
1244                       "(see RFC2616 section 14.23): %s", r->uri);
1245     }
1246     if (r->status != HTTP_OK) {
1247         ap_send_error_response(r, 0);
1248         ap_log_transaction(r);
1249         return r;
1250     }
1251 
1252     if ((access_status = ap_run_post_read_request(r))) {
1253         ap_die(access_status, r);
1254         ap_log_transaction(r);
1255         return NULL;
1256     }
1257 
1258     if (((expect = ap_table_get(r->headers_in, "Expect")) != NULL) &&
1259         (expect[0] != '\0')) {
1260         /*
1261          * The Expect header field was added to HTTP/1.1 after RFC 2068
1262          * as a means to signal when a 100 response is desired and,
1263          * unfortunately, to signal a poor man's mandatory extension that
1264          * the server must understand or return 417 Expectation Failed.
1265          */
1266         if (strcasecmp(expect, "100-continue") == 0) {
1267             r->expecting_100 = 1;
1268         }
1269         else {
1270             r->status = HTTP_EXPECTATION_FAILED;
1271             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
1272                           "client sent an unrecognized expectation value of "
1273                           "Expect: %s", expect);
1274             ap_send_error_response(r, 0);
1275             (void) ap_discard_request_body(r);
1276             ap_log_transaction(r);
1277             return r;
1278         }
1279     }
1280 
1281     return r;
1282 }
1283 
1284 /*
1285  * A couple of other functions which initialize some of the fields of
1286  * a request structure, as appropriate for adjuncts of one kind or another
1287  * to a request in progress.  Best here, rather than elsewhere, since
1288  * *someone* has to set the protocol-specific fields...
1289  */
1290 
ap_set_sub_req_protocol(request_rec * rnew,const request_rec * r)1291 API_EXPORT(void) ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
1292 {
1293     const char *ccp;
1294 
1295     rnew->the_request     = r->the_request;  /* Keep original request-line */
1296 
1297     rnew->assbackwards    = 1;   /* Don't send headers from this. */
1298     rnew->no_local_copy   = 1;   /* Don't try to send USE_LOCAL_COPY for a
1299                                   * fragment. */
1300     rnew->method          = "GET";
1301     rnew->method_number   = M_GET;
1302     rnew->protocol        = "INCLUDED";
1303 
1304     rnew->status          = HTTP_OK;
1305 
1306     rnew->headers_in      = r->headers_in;
1307     rnew->subprocess_env  = ap_copy_table(rnew->pool, r->subprocess_env);
1308     rnew->headers_out     = ap_make_table(rnew->pool, 5);
1309     rnew->err_headers_out = ap_make_table(rnew->pool, 5);
1310     rnew->notes           = ap_make_table(rnew->pool, 5);
1311 
1312     rnew->expecting_100   = r->expecting_100;
1313     rnew->read_length     = r->read_length;
1314     rnew->read_body       = REQUEST_NO_BODY;
1315 
1316     rnew->main = (request_rec *) r;
1317 
1318     if ((ccp = ap_table_get(r->notes, "address-family")) != NULL)
1319 	ap_table_setn(rnew->notes, "address-family", ccp);
1320 
1321     rnew->ctx = r->ctx;
1322 
1323 }
1324 
ap_finalize_sub_req_protocol(request_rec * sub)1325 API_EXPORT(void) ap_finalize_sub_req_protocol(request_rec *sub)
1326 {
1327     SET_BYTES_SENT(sub->main);
1328 }
1329 
1330 /*
1331  * Support for the Basic authentication protocol, and a bit for Digest.
1332  */
1333 
ap_note_auth_failure(request_rec * r)1334 API_EXPORT(void) ap_note_auth_failure(request_rec *r)
1335 {
1336     if (!strcasecmp(ap_auth_type(r), "Basic"))
1337         ap_note_basic_auth_failure(r);
1338     else if (!strcasecmp(ap_auth_type(r), "Digest"))
1339         ap_note_digest_auth_failure(r);
1340 }
1341 
ap_note_basic_auth_failure(request_rec * r)1342 API_EXPORT(void) ap_note_basic_auth_failure(request_rec *r)
1343 {
1344     if (strcasecmp(ap_auth_type(r), "Basic"))
1345         ap_note_auth_failure(r);
1346     else
1347         ap_table_setn(r->err_headers_out,
1348                   r->proxyreq == STD_PROXY ? "Proxy-Authenticate"
1349 		      : "WWW-Authenticate",
1350                   ap_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), "\"",
1351                           NULL));
1352 }
1353 
ap_note_digest_auth_failure(request_rec * r)1354 API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r)
1355 {
1356     /* We need to create a nonce which:
1357      * a) changes all the time (see r->request_time)
1358      *    below and
1359      * b) of which we can verify that it is our own
1360      *    fairly easily when it comes to veryfing
1361      *    the digest coming back in the response.
1362      * c) and which as a whole should not
1363      *    be unlikely to be in use anywhere else.
1364      */
1365     char * nonce_prefix = ap_md5(r->pool,
1366            (unsigned char *)
1367            ap_psprintf(r->pool, "%s%qu",
1368                        ap_auth_nonce(r), (int64_t)r->request_time));
1369 
1370     ap_table_setn(r->err_headers_out,
1371 	    r->proxyreq == STD_PROXY ? "Proxy-Authenticate"
1372 		  : "WWW-Authenticate",
1373            ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%s%qu\"",
1374                ap_auth_name(r), nonce_prefix, (int64_t)r->request_time));
1375 }
1376 
ap_get_basic_auth_pw(request_rec * r,const char ** pw)1377 API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
1378 {
1379     const char *auth_line = ap_table_get(r->headers_in,
1380 					 r->proxyreq == STD_PROXY
1381 					 ? "Proxy-Authorization"
1382 					 : "Authorization");
1383     const char *t;
1384 
1385     if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic"))
1386         return DECLINED;
1387 
1388     if (!ap_auth_name(r)) {
1389         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
1390 		    r, "need AuthName: %s", r->uri);
1391         return SERVER_ERROR;
1392     }
1393 
1394     if (!auth_line) {
1395         ap_note_basic_auth_failure(r);
1396         return AUTH_REQUIRED;
1397     }
1398 
1399     if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
1400         /* Client tried to authenticate using wrong auth scheme */
1401         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1402                     "client used wrong authentication scheme: %s", r->uri);
1403         ap_note_basic_auth_failure(r);
1404         return AUTH_REQUIRED;
1405     }
1406 
1407     while (*auth_line== ' ' || *auth_line== '\t')
1408         auth_line++;
1409 
1410     t = ap_pbase64decode(r->pool, auth_line);
1411     /* Note that this allocation has to be made from r->connection->pool
1412      * because it has the lifetime of the connection.  The other allocations
1413      * are temporary and can be tossed away any time.
1414      */
1415     r->connection->user = ap_getword_nulls (r->connection->pool, &t, ':');
1416     r->connection->ap_auth_type = "Basic";
1417 
1418     *pw = t;
1419 
1420     return OK;
1421 }
1422 
1423 /* New Apache routine to map status codes into array indicies
1424  *  e.g.  100 -> 0,  101 -> 1,  200 -> 2 ...
1425  * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
1426  * and must be listed in order.
1427  */
1428 
1429 static const char * const status_lines[RESPONSE_CODES] =
1430 {
1431     "100 Continue",
1432     "101 Switching Protocols",
1433     "102 Processing",
1434 #define LEVEL_200  3
1435     "200 OK",
1436     "201 Created",
1437     "202 Accepted",
1438     "203 Non-Authoritative Information",
1439     "204 No Content",
1440     "205 Reset Content",
1441     "206 Partial Content",
1442     "207 Multi-Status",
1443 #define LEVEL_300 11
1444     "300 Multiple Choices",
1445     "301 Moved Permanently",
1446     "302 Found",
1447     "303 See Other",
1448     "304 Not Modified",
1449     "305 Use Proxy",
1450     "306 unused",
1451     "307 Temporary Redirect",
1452 #define LEVEL_400 19
1453     "400 Bad Request",
1454     "401 Authorization Required",
1455     "402 Payment Required",
1456     "403 Forbidden",
1457     "404 Not Found",
1458     "405 Method Not Allowed",
1459     "406 Not Acceptable",
1460     "407 Proxy Authentication Required",
1461     "408 Request Time-out",
1462     "409 Conflict",
1463     "410 Gone",
1464     "411 Length Required",
1465     "412 Precondition Failed",
1466     "413 Request Entity Too Large",
1467     "414 Request-URI Too Large",
1468     "415 Unsupported Media Type",
1469     "416 Requested Range Not Satisfiable",
1470     "417 Expectation Failed",
1471     "418 unused",
1472     "419 unused",
1473     "420 unused",
1474     "421 unused",
1475     "422 Unprocessable Entity",
1476     "423 Locked",
1477     "424 Failed Dependency",
1478 #define LEVEL_500 44
1479     "500 Internal Server Error",
1480     "501 Method Not Implemented",
1481     "502 Bad Gateway",
1482     "503 Service Temporarily Unavailable",
1483     "504 Gateway Time-out",
1484     "505 HTTP Version Not Supported",
1485     "506 Variant Also Negotiates",
1486     "507 Insufficient Storage",
1487     "508 unused",
1488     "509 unused",
1489     "510 Not Extended"
1490 };
1491 
1492 /* The index is found by its offset from the x00 code of each level.
1493  * Although this is fast, it will need to be replaced if some nutcase
1494  * decides to define a high-numbered code before the lower numbers.
1495  * If that sad event occurs, replace the code below with a linear search
1496  * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
1497  */
ap_index_of_response(int status)1498 API_EXPORT(int) ap_index_of_response(int status)
1499 {
1500     static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
1501     LEVEL_500, RESPONSE_CODES};
1502     int i, pos;
1503 
1504     if (status < 100)           /* Below 100 is illegal for HTTP status */
1505         return LEVEL_500;
1506 
1507     for (i = 0; i < 5; i++) {
1508         status -= 100;
1509         if (status < 100) {
1510             pos = (status + shortcut[i]);
1511             if (pos < shortcut[i + 1])
1512                 return pos;
1513             else
1514                 return LEVEL_500;       /* status unknown (falls in gap) */
1515         }
1516     }
1517     return LEVEL_500;           /* 600 or above is also illegal */
1518 }
1519 
1520 /* Send a single HTTP header field to the client.  Note that this function
1521  * is used in calls to table_do(), so their interfaces are co-dependent.
1522  * In other words, don't change this one without checking table_do in alloc.c.
1523  * It returns true unless there was a write error of some kind.
1524  */
ap_send_header_field(request_rec * r,const char * fieldname,const char * fieldval)1525 API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r,
1526                                             const char *fieldname,
1527                                             const char *fieldval)
1528 {
1529     if (strcasecmp(fieldname, "ETag") == 0) {
1530         if (ap_table_get(r->notes, "no-etag") != NULL) {
1531             return 1;
1532         }
1533     }
1534     return (0 < ap_rvputs(r, fieldname, ": ", fieldval, CRLF, NULL));
1535 }
1536 
ap_basic_http_header(request_rec * r)1537 API_EXPORT(void) ap_basic_http_header(request_rec *r)
1538 {
1539     char *protocol;
1540 
1541     if (r->assbackwards)
1542         return;
1543 
1544     if (!r->status_line)
1545         r->status_line = status_lines[ap_index_of_response(r->status)];
1546 
1547     /* kluge around broken browsers when indicated by force-response-1.0
1548      */
1549     if (r->proto_num == HTTP_VERSION(1,0)
1550        && ap_table_get(r->subprocess_env, "force-response-1.0")) {
1551 
1552         protocol = "HTTP/1.0";
1553         r->connection->keepalive = -1;
1554     }
1555     else
1556         protocol = SERVER_PROTOCOL;
1557 
1558     /* output the HTTP/1.x Status-Line */
1559     ap_rvputs(r, protocol, " ", r->status_line, CRLF, NULL);
1560 
1561     /* output the date header */
1562     ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time));
1563 
1564     /* keep the set-by-proxy server header, otherwise
1565      * generate a new server header */
1566     if (r->proxyreq) {
1567         const char *server = ap_table_get(r->headers_out, "Server");
1568         if (server) {
1569             ap_send_header_field(r, "Server", server);
1570         }
1571     }
1572     else {
1573         ap_send_header_field(r, "Server", ap_get_server_version());
1574     }
1575 
1576     /* unset so we don't send them again */
1577     ap_table_unset(r->headers_out, "Date");        /* Avoid bogosity */
1578     ap_table_unset(r->headers_out, "Server");
1579 }
1580 
1581 /* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2
1582  * have a header parsing bug.  If the terminating \r\n occur starting
1583  * at offset 256, 257 or 258 of output then it will not properly parse
1584  * the headers.  Curiously it doesn't exhibit this problem at 512, 513.
1585  * We are guessing that this is because their initial read of a new request
1586  * uses a 256 byte buffer, and subsequent reads use a larger buffer.
1587  * So the problem might exist at different offsets as well.
1588  *
1589  * This should also work on keepalive connections assuming they use the
1590  * same small buffer for the first read of each new request.
1591  *
1592  * At any rate, we check the bytes written so far and, if we are about to
1593  * tickle the bug, we instead insert a bogus padding header.  Since the bug
1594  * manifests as a broken image in Navigator, users blame the server.  :(
1595  * It is more expensive to check the User-Agent than it is to just add the
1596  * bytes, so we haven't used the BrowserMatch feature here.
1597  */
terminate_header(BUFF * client)1598 static void terminate_header(BUFF *client)
1599 {
1600     long int bs;
1601 
1602     ap_bgetopt(client, BO_BYTECT, &bs);
1603     if (bs >= 255 && bs <= 257)
1604         ap_bputs("X-Pad: avoid browser bug" CRLF, client);
1605 
1606     ap_bputs(CRLF, client);  /* Send the terminating empty line */
1607 }
1608 
1609 /* Build the Allow field-value from the request handler method mask.
1610  * Note that we always allow TRACE, since it is handled below.
1611  */
make_allow(request_rec * r)1612 static char *make_allow(request_rec *r)
1613 {
1614     return 2 + ap_pstrcat(r->pool,
1615                    (r->allowed & (1 << M_GET))       ? ", GET, HEAD" : "",
1616                    (r->allowed & (1 << M_POST))      ? ", POST"      : "",
1617                    (r->allowed & (1 << M_PUT))       ? ", PUT"       : "",
1618                    (r->allowed & (1 << M_DELETE))    ? ", DELETE"    : "",
1619                    (r->allowed & (1 << M_CONNECT))   ? ", CONNECT"   : "",
1620                    (r->allowed & (1 << M_OPTIONS))   ? ", OPTIONS"   : "",
1621                    (r->allowed & (1 << M_PATCH))     ? ", PATCH"     : "",
1622                    (r->allowed & (1 << M_PROPFIND))  ? ", PROPFIND"  : "",
1623                    (r->allowed & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
1624                    (r->allowed & (1 << M_MKCOL))     ? ", MKCOL"     : "",
1625                    (r->allowed & (1 << M_COPY))      ? ", COPY"      : "",
1626                    (r->allowed & (1 << M_MOVE))      ? ", MOVE"      : "",
1627                    (r->allowed & (1 << M_LOCK))      ? ", LOCK"      : "",
1628                    (r->allowed & (1 << M_UNLOCK))    ? ", UNLOCK"    : "",
1629                    ", TRACE",
1630                    NULL);
1631 }
1632 
ap_send_http_trace(request_rec * r)1633 API_EXPORT(int) ap_send_http_trace(request_rec *r)
1634 {
1635     int rv;
1636 
1637     /* Get the original request */
1638     while (r->prev)
1639         r = r->prev;
1640 
1641     if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY)))
1642         return rv;
1643 
1644     ap_hard_timeout("send TRACE", r);
1645 
1646     r->content_type = "message/http";
1647     ap_send_http_header(r);
1648 
1649     /* Now we recreate the request, and echo it back */
1650 
1651     ap_rvputs(r, r->the_request, CRLF, NULL);
1652 
1653     ap_table_do((int (*) (void *, const char *, const char *))
1654                 ap_send_header_field, (void *) r, r->headers_in, NULL);
1655     ap_rputs(CRLF, r);
1656 
1657     ap_kill_timeout(r);
1658     return OK;
1659 }
1660 
ap_send_http_options(request_rec * r)1661 API_EXPORT(int) ap_send_http_options(request_rec *r)
1662 {
1663     const long int zero = 0L;
1664 
1665     if (r->assbackwards)
1666         return DECLINED;
1667 
1668     ap_hard_timeout("send OPTIONS", r);
1669 
1670     ap_basic_http_header(r);
1671 
1672     ap_table_setn(r->headers_out, "Content-Length", "0");
1673     ap_table_setn(r->headers_out, "Allow", make_allow(r));
1674     ap_set_keepalive(r);
1675 
1676     ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
1677              (void *) r, r->headers_out, NULL);
1678 
1679     terminate_header(r->connection->client);
1680 
1681     ap_kill_timeout(r);
1682     ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
1683 
1684     return OK;
1685 }
1686 
1687 /*
1688  * Here we try to be compatible with clients that want multipart/x-byteranges
1689  * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
1690  * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
1691  * that the browser supports an older protocol. We also check User-Agent
1692  * for Microsoft Internet Explorer 3, which needs this as well.
1693  */
use_range_x(request_rec * r)1694 static int use_range_x(request_rec *r)
1695 {
1696     const char *ua;
1697     return (ap_table_get(r->headers_in, "Request-Range") ||
1698             ((ua = ap_table_get(r->headers_in, "User-Agent"))
1699              && strstr(ua, "MSIE 3")));
1700 }
1701 
1702 /* This routine is called by ap_table_do and merges all instances of
1703  * the passed field values into a single array that will be further
1704  * processed by some later routine.  Originally intended to help split
1705  * and recombine multiple Vary fields, though it is generic to any field
1706  * consisting of comma/space-separated tokens.
1707  */
uniq_field_values(void * d,const char * key,const char * val)1708 static int uniq_field_values(void *d, const char *key, const char *val)
1709 {
1710     array_header *values;
1711     char *start;
1712     char *e;
1713     char **strpp;
1714     int  i;
1715 
1716     values = (array_header *)d;
1717 
1718     e = ap_pstrdup(values->pool, val);
1719 
1720     do {
1721         /* Find a non-empty fieldname */
1722 
1723         while (*e == ',' || ap_isspace(*e)) {
1724             ++e;
1725         }
1726         if (*e == '\0') {
1727             break;
1728         }
1729         start = e;
1730         while (*e != '\0' && *e != ',' && !ap_isspace(*e)) {
1731             ++e;
1732         }
1733         if (*e != '\0') {
1734             *e++ = '\0';
1735         }
1736 
1737         /* Now add it to values if it isn't already represented.
1738          * Could be replaced by a ap_array_strcasecmp() if we had one.
1739          */
1740         for (i = 0, strpp = (char **) values->elts; i < values->nelts;
1741              ++i, ++strpp) {
1742             if (*strpp && strcasecmp(*strpp, start) == 0) {
1743                 break;
1744             }
1745         }
1746         if (i == values->nelts) {  /* if not found */
1747            *(char **)ap_push_array(values) = start;
1748         }
1749     } while (*e != '\0');
1750 
1751     return 1;
1752 }
1753 
1754 /*
1755  * Since some clients choke violently on multiple Vary fields, or
1756  * Vary fields with duplicate tokens, combine any multiples and remove
1757  * any duplicates.
1758  */
fixup_vary(request_rec * r)1759 static void fixup_vary(request_rec *r)
1760 {
1761     array_header *varies;
1762 
1763     varies = ap_make_array(r->pool, 5, sizeof(char *));
1764 
1765     /* Extract all Vary fields from the headers_out, separate each into
1766      * its comma-separated fieldname values, and then add them to varies
1767      * if not already present in the array.
1768      */
1769     ap_table_do((int (*)(void *, const char *, const char *))uniq_field_values,
1770 		(void *) varies, r->headers_out, "Vary", NULL);
1771 
1772     /* If we found any, replace old Vary fields with unique-ified value */
1773 
1774     if (varies->nelts > 0) {
1775 	ap_table_setn(r->headers_out, "Vary",
1776 		      ap_array_pstrcat(r->pool, varies, ','));
1777     }
1778 }
1779 
ap_send_http_header(request_rec * r)1780 API_EXPORT(void) ap_send_http_header(request_rec *r)
1781 {
1782     int i;
1783     const long int zero = 0L;
1784 
1785     if (r->assbackwards) {
1786         if (!r->main)
1787             ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
1788         r->sent_bodyct = 1;
1789         return;
1790     }
1791 
1792     /*
1793      * Now that we are ready to send a response, we need to combine the two
1794      * header field tables into a single table.  If we don't do this, our
1795      * later attempts to set or unset a given fieldname might be bypassed.
1796      */
1797     if (!ap_is_empty_table(r->err_headers_out))
1798         r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
1799                                         r->headers_out);
1800 
1801     /*
1802      * Remove the 'Vary' header field if the client can't handle it.
1803      * Since this will have nasty effects on HTTP/1.1 caches, force
1804      * the response into HTTP/1.0 mode.
1805      */
1806     if (ap_table_get(r->subprocess_env, "force-no-vary") != NULL) {
1807 	ap_table_unset(r->headers_out, "Vary");
1808 	r->proto_num = HTTP_VERSION(1,0);
1809 	ap_table_set(r->subprocess_env, "force-response-1.0", "1");
1810     }
1811     else {
1812 	fixup_vary(r);
1813     }
1814 
1815     ap_hard_timeout("send headers", r);
1816 
1817     ap_basic_http_header(r);
1818 
1819     ap_set_keepalive(r);
1820 
1821     if (r->chunked) {
1822         ap_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
1823         ap_table_unset(r->headers_out, "Content-Length");
1824     }
1825 
1826     if (r->byterange > 1)
1827         ap_table_setn(r->headers_out, "Content-Type",
1828                   ap_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
1829                           "byteranges; boundary=", r->boundary, NULL));
1830     else ap_table_setn(r->headers_out, "Content-Type", make_content_type(r,
1831 	r->content_type));
1832 
1833     if (r->content_encoding)
1834         ap_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
1835 
1836     if (r->content_languages && r->content_languages->nelts) {
1837         for (i = 0; i < r->content_languages->nelts; ++i) {
1838             ap_table_mergen(r->headers_out, "Content-Language",
1839                         ((char **) (r->content_languages->elts))[i]);
1840         }
1841     }
1842     else if (r->content_language)
1843         ap_table_setn(r->headers_out, "Content-Language", r->content_language);
1844 
1845     /*
1846      * Control cachability for non-cachable responses if not already set by
1847      * some other part of the server configuration.
1848      */
1849     if (r->no_cache && !ap_table_get(r->headers_out, "Expires"))
1850         ap_table_addn(r->headers_out, "Expires",
1851                   ap_gm_timestr_822(r->pool, r->request_time));
1852 
1853     /* Send the entire table of header fields, terminated by an empty line. */
1854 
1855     ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
1856              (void *) r, r->headers_out, NULL);
1857 
1858     terminate_header(r->connection->client);
1859 
1860     ap_kill_timeout(r);
1861 
1862     ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
1863     r->sent_bodyct = 1;         /* Whatever follows is real body stuff... */
1864 
1865     /* Set buffer flags for the body */
1866     if (r->chunked)
1867         ap_bsetflag(r->connection->client, B_CHUNK, 1);
1868 }
1869 
1870 /* finalize_request_protocol is called at completion of sending the
1871  * response.  It's sole purpose is to send the terminating protocol
1872  * information for any wrappers around the response message body
1873  * (i.e., transfer encodings).  It should have been named finalize_response.
1874  */
ap_finalize_request_protocol(request_rec * r)1875 API_EXPORT(void) ap_finalize_request_protocol(request_rec *r)
1876 {
1877     if (r->chunked && !r->connection->aborted) {
1878         /*
1879          * Turn off chunked encoding --- we can only do this once.
1880          */
1881         r->chunked = 0;
1882         ap_bsetflag(r->connection->client, B_CHUNK, 0);
1883 
1884         ap_soft_timeout("send ending chunk", r);
1885         ap_rputs("0" CRLF, r);
1886         /* If we had footer "headers", we'd send them now */
1887         ap_rputs(CRLF, r);
1888         ap_kill_timeout(r);
1889 
1890     }
1891 }
1892 
1893 /* Here we deal with getting the request message body from the client.
1894  * Whether or not the request contains a body is signaled by the presence
1895  * of a non-zero Content-Length or by a Transfer-Encoding: chunked.
1896  *
1897  * Note that this is more complicated than it was in Apache 1.1 and prior
1898  * versions, because chunked support means that the module does less.
1899  *
1900  * The proper procedure is this:
1901  *
1902  * 1. Call setup_client_block() near the beginning of the request
1903  *    handler. This will set up all the necessary properties, and will
1904  *    return either OK, or an error code. If the latter, the module should
1905  *    return that error code. The second parameter selects the policy to
1906  *    apply if the request message indicates a body, and how a chunked
1907  *    transfer-coding should be interpreted. Choose one of
1908  *
1909  *    REQUEST_NO_BODY          Send 413 error if message has any body
1910  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
1911  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
1912  *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
1913  *
1914  *    In order to use the last two options, the caller MUST provide a buffer
1915  *    large enough to hold a chunk-size line, including any extensions.
1916  *
1917  * 2. When you are ready to read a body (if any), call should_client_block().
1918  *    This will tell the module whether or not to read input. If it is 0,
1919  *    the module should assume that there is no message body to read.
1920  *    This step also sends a 100 Continue response to HTTP/1.1 clients,
1921  *    so should not be called until the module is *definitely* ready to
1922  *    read content. (otherwise, the point of the 100 response is defeated).
1923  *    Never call this function more than once.
1924  *
1925  * 3. Finally, call get_client_block in a loop. Pass it a buffer and its size.
1926  *    It will put data into the buffer (not necessarily a full buffer), and
1927  *    return the length of the input block. When it is done reading, it will
1928  *    return 0 if EOF, or -1 if there was an error.
1929  *    If an error occurs on input, we force an end to keepalive.
1930  */
1931 
ap_setup_client_block(request_rec * r,int read_policy)1932 API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy)
1933 {
1934     const char *tenc = ap_table_get(r->headers_in, "Transfer-Encoding");
1935     const char *lenp = ap_table_get(r->headers_in, "Content-Length");
1936     unsigned long max_body;
1937 
1938     r->read_body = read_policy;
1939     r->read_chunked = 0;
1940     r->remaining = 0;
1941 
1942     if (tenc) {
1943         if (strcasecmp(tenc, "chunked")) {
1944             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1945                         "Unknown Transfer-Encoding %s", tenc);
1946             return HTTP_NOT_IMPLEMENTED;
1947         }
1948         if (r->read_body == REQUEST_CHUNKED_ERROR) {
1949             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1950                         "chunked Transfer-Encoding forbidden: %s", r->uri);
1951             return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
1952         }
1953 
1954         r->read_chunked = 1;
1955     }
1956     else if (lenp) {
1957         const char *pos = lenp;
1958         int conversion_error = 0;
1959 
1960         while (ap_isspace(*pos))
1961             ++pos;
1962 
1963         if (*pos == '\0') {
1964             /* special case test - a C-L field NULL or all blanks is
1965              * assumed OK and defaults to 0. Otherwise, we do a
1966              * strict check of the field */
1967             r->remaining = 0;
1968         }
1969         else {
1970             char *endstr;
1971             errno = 0;
1972             r->remaining = ap_strtol(lenp, &endstr, 10);
1973             if (errno || (endstr && *endstr) || (r->remaining < 0)) {
1974                 conversion_error = 1;
1975             }
1976         }
1977 
1978         if (conversion_error) {
1979             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1980                         "Invalid Content-Length");
1981             return HTTP_BAD_REQUEST;
1982         }
1983     }
1984 
1985     if ((r->read_body == REQUEST_NO_BODY) &&
1986         (r->read_chunked || (r->remaining > 0))) {
1987         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1988                     "%s with body is not allowed for %s", r->method, r->uri);
1989         return HTTP_REQUEST_ENTITY_TOO_LARGE;
1990     }
1991 
1992     max_body = ap_get_limit_req_body(r);
1993     if (max_body && ((unsigned long)r->remaining > max_body)
1994                  && (r->remaining >= 0)) {
1995         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1996           "Request content-length of %s is larger than the configured "
1997           "limit of %lu", lenp, max_body);
1998         return HTTP_REQUEST_ENTITY_TOO_LARGE;
1999     }
2000 
2001     return OK;
2002 }
2003 
ap_should_client_block(request_rec * r)2004 API_EXPORT(int) ap_should_client_block(request_rec *r)
2005 {
2006     /* First check if we have already read the request body */
2007 
2008     if (r->read_length || (!r->read_chunked && (r->remaining <= 0)))
2009         return 0;
2010 
2011     if (r->expecting_100 && r->proto_num >= HTTP_VERSION(1,1)) {
2012         /* sending 100 Continue interim response */
2013         ap_rvputs(r, SERVER_PROTOCOL, " ", status_lines[0], CRLF CRLF,
2014                   NULL);
2015         ap_rflush(r);
2016     }
2017 
2018     return 1;
2019 }
2020 
2021 /**
2022  * Parse a chunk extension, detect overflow.
2023  * There are two error cases:
2024  *  1) If the conversion would require too many bits, a -1 is returned.
2025  *  2) If the conversion used the correct number of bits, but an overflow
2026  *     caused only the sign bit to flip, then that negative number is
2027  *     returned.
2028  * In general, any negative number can be considered an overflow error.
2029  */
ap_get_chunk_size(char * b)2030 API_EXPORT(long) ap_get_chunk_size(char *b)
2031 {
2032     long chunksize = 0;
2033     long chunkbits = sizeof(long) * 8;
2034 
2035     /* Skip leading zeros */
2036     while (*b == '0') {
2037         ++b;
2038     }
2039 
2040     while (ap_isxdigit(*b) && (chunkbits > 0)) {
2041         int xvalue = 0;
2042 
2043         if (*b >= '0' && *b <= '9') {
2044             xvalue = *b - '0';
2045         }
2046         else if (*b >= 'A' && *b <= 'F') {
2047             xvalue = *b - 'A' + 0xa;
2048         }
2049         else if (*b >= 'a' && *b <= 'f') {
2050             xvalue = *b - 'a' + 0xa;
2051         }
2052 
2053         chunksize = (chunksize << 4) | xvalue;
2054         chunkbits -= 4;
2055         ++b;
2056     }
2057     if (ap_isxdigit(*b) && (chunkbits <= 0)) {
2058         /* overflow */
2059         return -1;
2060     }
2061 
2062     return chunksize;
2063 }
2064 
2065 /* get_client_block is called in a loop to get the request message body.
2066  * This is quite simple if the client includes a content-length
2067  * (the normal case), but gets messy if the body is chunked. Note that
2068  * r->remaining is used to maintain state across calls and that
2069  * r->read_length is the total number of bytes given to the caller
2070  * across all invocations.  It is messy because we have to be careful not
2071  * to read past the data provided by the client, since these reads block.
2072  * Returns 0 on End-of-body, -1 on error or premature chunk end.
2073  *
2074  * Reading the chunked encoding requires a buffer size large enough to
2075  * hold a chunk-size line, including any extensions. For now, we'll leave
2076  * that to the caller, at least until we can come up with a better solution.
2077  */
ap_get_client_block(request_rec * r,char * buffer,int bufsiz)2078 API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
2079 {
2080     int c;
2081     long len_read, len_to_read;
2082     long chunk_start = 0;
2083     unsigned long max_body;
2084 
2085     if (!r->read_chunked) {     /* Content-length read */
2086         len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
2087         len_read = ap_bread(r->connection->client, buffer, len_to_read);
2088         if (len_read <= 0) {
2089             if (len_read < 0)
2090                 r->connection->keepalive = -1;
2091             return len_read;
2092         }
2093         r->read_length += len_read;
2094         r->remaining -= len_read;
2095         return len_read;
2096     }
2097 
2098     /*
2099      * Handle chunked reading Note: we are careful to shorten the input
2100      * bufsiz so that there will always be enough space for us to add a CRLF
2101      * (if necessary).
2102      */
2103     if (r->read_body == REQUEST_CHUNKED_PASS)
2104         bufsiz -= 2;
2105     if (bufsiz <= 0)
2106         return -1;              /* Cannot read chunked with a small buffer */
2107 
2108     /* Check to see if we have already read too much request data.
2109      * For efficiency reasons, we only check this at the top of each
2110      * caller read pass, since the limit exists just to stop infinite
2111      * length requests and nobody cares if it goes over by one buffer.
2112      */
2113     max_body = ap_get_limit_req_body(r);
2114     if (max_body && ((unsigned long) r->read_length > max_body)
2115                  && (r->read_length >= 0)) {
2116         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
2117             "Chunked request body is larger than the configured limit of %lu",
2118             max_body);
2119         r->connection->keepalive = -1;
2120         return -1;
2121     }
2122 
2123     if (r->remaining == 0) {    /* Start of new chunk */
2124 
2125         chunk_start = ap_getline(buffer, bufsiz, r->connection->client, 0);
2126         if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
2127             || !ap_isxdigit(*buffer)) {
2128             r->connection->keepalive = -1;
2129             return -1;
2130         }
2131 
2132         len_to_read = ap_get_chunk_size(buffer);
2133 
2134         if (len_to_read == 0) { /* Last chunk indicated, get footers */
2135             if (r->read_body == REQUEST_CHUNKED_DECHUNK) {
2136                 get_mime_headers(r);
2137                 snprintf(buffer, bufsiz, "%ld", r->read_length);
2138                 ap_table_unset(r->headers_in, "Transfer-Encoding");
2139                 ap_table_setn(r->headers_in, "Content-Length",
2140                     ap_pstrdup(r->pool, buffer));
2141                 return 0;
2142             }
2143             r->remaining = -1;  /* Indicate footers in-progress */
2144         }
2145         else if (len_to_read < 0) {
2146             r->connection->keepalive = -1;
2147             return -1;
2148         }
2149         else {
2150             r->remaining = len_to_read;
2151         }
2152         if (r->read_body == REQUEST_CHUNKED_PASS) {
2153             buffer[chunk_start++] = CR; /* Restore chunk-size line end  */
2154             buffer[chunk_start++] = LF;
2155             buffer += chunk_start;      /* and pass line on to caller   */
2156             bufsiz -= chunk_start;
2157         }
2158         else {
2159             /* REQUEST_CHUNKED_DECHUNK -- do not include the length of the
2160              * header in the return value
2161              */
2162             chunk_start = 0;
2163         }
2164     }
2165                                 /* When REQUEST_CHUNKED_PASS, we are */
2166     if (r->remaining == -1) {   /* reading footers until empty line  */
2167         len_read = chunk_start;
2168 
2169         while ((bufsiz > 1) && ((len_read =
2170                   ap_getline(buffer, bufsiz, r->connection->client, 1)) > 0)) {
2171 
2172             if (len_read != (bufsiz - 1)) {
2173                 buffer[len_read++] = CR;        /* Restore footer line end  */
2174                 buffer[len_read++] = LF;
2175             }
2176             chunk_start += len_read;
2177             buffer += len_read;
2178             bufsiz -= len_read;
2179         }
2180         if (len_read < 0) {
2181             r->connection->keepalive = -1;
2182             return -1;
2183         }
2184 
2185         if (len_read == 0) {    /* Indicates an empty line */
2186             buffer[0] = CR;
2187             buffer[1] = LF;
2188             chunk_start += 2;
2189             r->remaining = -2;
2190         }
2191         r->read_length += chunk_start;
2192         return chunk_start;
2193     }
2194                                 /* When REQUEST_CHUNKED_PASS, we     */
2195     if (r->remaining == -2) {   /* finished footers when last called */
2196         r->remaining = 0;       /* so now we must signal EOF         */
2197         return 0;
2198     }
2199 
2200     /* Otherwise, we are in the midst of reading a chunk of data */
2201 
2202     len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
2203 
2204     len_read = ap_bread(r->connection->client, buffer, len_to_read);
2205     if (len_read <= 0) {
2206         r->connection->keepalive = -1;
2207         return -1;
2208     }
2209 
2210     r->remaining -= len_read;
2211 
2212     if (r->remaining == 0) {    /* End of chunk, get trailing CRLF */
2213 
2214         if ((c = ap_bgetc(r->connection->client)) == CR) {
2215             c = ap_bgetc(r->connection->client);
2216         }
2217 
2218         if (c != LF) {
2219             r->connection->keepalive = -1;
2220             return -1;
2221         }
2222         if (r->read_body == REQUEST_CHUNKED_PASS) {
2223             buffer[len_read++] = CR;
2224             buffer[len_read++] = LF;
2225         }
2226     }
2227     r->read_length += (chunk_start + len_read);
2228 
2229     return (chunk_start + len_read);
2230 }
2231 
2232 /* In HTTP/1.1, any method can have a body.  However, most GET handlers
2233  * wouldn't know what to do with a request body if they received one.
2234  * This helper routine tests for and reads any message body in the request,
2235  * simply discarding whatever it receives.  We need to do this because
2236  * failing to read the request body would cause it to be interpreted
2237  * as the next request on a persistent connection.
2238  *
2239  * Since we return an error status if the request is malformed, this
2240  * routine should be called at the beginning of a no-body handler, e.g.,
2241  *
2242  *    if ((retval = ap_discard_request_body(r)) != OK)
2243  *        return retval;
2244  */
ap_discard_request_body(request_rec * r)2245 API_EXPORT(int) ap_discard_request_body(request_rec *r)
2246 {
2247     int rv;
2248 
2249     if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_PASS)))
2250         return rv;
2251 
2252     /* In order to avoid sending 100 Continue when we already know the
2253      * final response status, and yet not kill the connection if there is
2254      * no request body to be read, we need to duplicate the test from
2255      * ap_should_client_block() here negated rather than call it directly.
2256      */
2257     if ((r->read_length == 0) && (r->read_chunked || (r->remaining > 0))) {
2258         char dumpbuf[HUGE_STRING_LEN];
2259 
2260         if (r->expecting_100) {
2261             r->connection->keepalive = -1;
2262             return OK;
2263         }
2264         ap_hard_timeout("reading request body", r);
2265         while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
2266             continue;
2267         ap_kill_timeout(r);
2268 
2269         if (rv < 0)
2270             return HTTP_BAD_REQUEST;
2271     }
2272     return OK;
2273 }
2274 
2275 /*
2276  * Send the body of a response to the client.
2277  */
ap_send_fd(FILE * f,request_rec * r)2278 API_EXPORT(long) ap_send_fd(FILE *f, request_rec *r)
2279 {
2280     return ap_send_fd_length(f, r, -1);
2281 }
2282 
ap_send_fd_length(FILE * f,request_rec * r,long length)2283 API_EXPORT(long) ap_send_fd_length(FILE *f, request_rec *r, long length)
2284 {
2285     char buf[IOBUFSIZE];
2286     long total_bytes_sent = 0;
2287     register int n, w, o, len;
2288 
2289     if (length == 0)
2290         return 0;
2291 
2292     ap_soft_timeout("send body", r);
2293 
2294     while (!r->connection->aborted) {
2295         if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
2296             len = length - total_bytes_sent;
2297         else
2298             len = IOBUFSIZE;
2299 
2300         while ((n = fread(buf, sizeof(char), len, f)) < 1
2301                && ferror(f) && errno == EINTR && !r->connection->aborted)
2302             continue;
2303 
2304         if (n < 1) {
2305             break;
2306         }
2307         o = 0;
2308 
2309         while (n && !r->connection->aborted) {
2310             w = ap_bwrite(r->connection->client, &buf[o], n);
2311             if (w > 0) {
2312                 ap_reset_timeout(r); /* reset timeout after successful write */
2313                 total_bytes_sent += w;
2314                 n -= w;
2315                 o += w;
2316             }
2317             else if (w < 0) {
2318                 if (!r->connection->aborted) {
2319                     ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2320                      "client stopped connection before send body completed");
2321                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2322                     r->connection->aborted = 1;
2323                 }
2324                 break;
2325             }
2326         }
2327     }
2328 
2329     ap_kill_timeout(r);
2330     SET_BYTES_SENT(r);
2331     return total_bytes_sent;
2332 }
2333 
2334 /*
2335  * Send the body of a response to the client.
2336  */
ap_send_fb(BUFF * fb,request_rec * r)2337 API_EXPORT(long) ap_send_fb(BUFF *fb, request_rec *r)
2338 {
2339     return ap_send_fb_length(fb, r, -1);
2340 }
2341 
ap_send_fb_length(BUFF * fb,request_rec * r,long length)2342 API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
2343 {
2344     char buf[IOBUFSIZE];
2345     long total_bytes_sent = 0;
2346     register int n, w, o, len, fd;
2347     fd_set fds;
2348 
2349     if (length == 0)
2350         return 0;
2351 
2352     /* Make fb unbuffered and non-blocking */
2353     ap_bsetflag(fb, B_RD, 0);
2354     ap_bnonblock(fb, B_RD);
2355     fd = ap_bfileno(fb, B_RD);
2356     if (fd >= FD_SETSIZE) {
2357 	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
2358 	    "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
2359 	    "found, you probably need to rebuild Apache with a "
2360 	    "larger FD_SETSIZE", fd, FD_SETSIZE);
2361 	return 0;
2362     }
2363 
2364     ap_soft_timeout("send body", r);
2365 
2366     FD_ZERO(&fds);
2367     while (!r->connection->aborted) {
2368         if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
2369             len = length - total_bytes_sent;
2370         else
2371             len = IOBUFSIZE;
2372 
2373         do {
2374             n = ap_bread(fb, buf, len);
2375             if (n >= 0)
2376                 break;
2377             if (r->connection->aborted)
2378                 break;
2379             if (n < 0 && errno != EAGAIN)
2380                 break;
2381 
2382             /* we need to block, so flush the output first */
2383             if (ap_bflush(r->connection->client) < 0) {
2384                 ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2385                     "client stopped connection before send body completed");
2386                 ap_bsetflag(r->connection->client, B_EOUT, 1);
2387                 r->connection->aborted = 1;
2388                 break;
2389             }
2390             FD_SET(fd, &fds);
2391             /*
2392              * we don't care what select says, we might as well loop back
2393              * around and try another read
2394              */
2395             ap_select(fd + 1, &fds, NULL, NULL, NULL);
2396         } while (!r->connection->aborted);
2397 
2398         if (n < 1 || r->connection->aborted) {
2399             break;
2400         }
2401         o = 0;
2402 
2403         while (n && !r->connection->aborted) {
2404             w = ap_bwrite(r->connection->client, &buf[o], n);
2405             if (w > 0) {
2406                 ap_reset_timeout(r); /* reset timeout after successful write */
2407                 total_bytes_sent += w;
2408                 n -= w;
2409                 o += w;
2410             }
2411             else if (w < 0) {
2412                 if (!r->connection->aborted) {
2413                     ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2414                        "client stopped connection before send body completed");
2415                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2416                     r->connection->aborted = 1;
2417                 }
2418                 break;
2419             }
2420         }
2421     }
2422 
2423     ap_kill_timeout(r);
2424     SET_BYTES_SENT(r);
2425     return total_bytes_sent;
2426 }
2427 
2428 
2429 
2430 /* The code writes MMAP_SEGMENT_SIZE bytes at a time.  This is due to Apache's
2431  * timeout model, which is a timeout per-write rather than a time for the
2432  * entire transaction to complete.  Essentially this should be small enough
2433  * so that in one Timeout period, your slowest clients should be reasonably
2434  * able to receive this many bytes.
2435  *
2436  * To take advantage of zero-copy TCP under Solaris 2.6 this should be a
2437  * multiple of 16k.  (And you need a SunATM2.0 network card.)
2438  */
2439 #ifndef MMAP_SEGMENT_SIZE
2440 #define MMAP_SEGMENT_SIZE       32768
2441 #endif
2442 
2443 /* send data from an in-memory buffer */
ap_send_mmap(void * mm,request_rec * r,size_t offset,size_t length)2444 API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
2445                              size_t length)
2446 {
2447     size_t total_bytes_sent = 0;
2448     int n, w;
2449 
2450     if (length == 0)
2451         return 0;
2452 
2453     ap_soft_timeout("send mmap", r);
2454 
2455     length += offset;
2456     while (!r->connection->aborted && offset < length) {
2457         if (length - offset > MMAP_SEGMENT_SIZE) {
2458             n = MMAP_SEGMENT_SIZE;
2459         }
2460         else {
2461             n = length - offset;
2462         }
2463 
2464         while (n && !r->connection->aborted) {
2465             w = ap_bwrite(r->connection->client, (char *) mm + offset, n);
2466             if (w > 0) {
2467                 ap_reset_timeout(r); /* reset timeout after successful write */
2468                 total_bytes_sent += w;
2469                 n -= w;
2470                 offset += w;
2471             }
2472             else if (w < 0) {
2473                 if (!r->connection->aborted) {
2474                     ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2475                        "client stopped connection before send mmap completed");
2476                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2477                     r->connection->aborted = 1;
2478                 }
2479                 break;
2480             }
2481         }
2482     }
2483 
2484     ap_kill_timeout(r);
2485     SET_BYTES_SENT(r);
2486     return total_bytes_sent;
2487 }
2488 
ap_rputc(int c,request_rec * r)2489 API_EXPORT(int) ap_rputc(int c, request_rec *r)
2490 {
2491     if (r->connection->aborted)
2492         return EOF;
2493 
2494     if (ap_bputc(c, r->connection->client) < 0) {
2495         if (!r->connection->aborted) {
2496             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2497                 "client stopped connection before rputc completed");
2498             ap_bsetflag(r->connection->client, B_EOUT, 1);
2499             r->connection->aborted = 1;
2500         }
2501         return EOF;
2502     }
2503     SET_BYTES_SENT(r);
2504     return c;
2505 }
2506 
ap_rputs(const char * str,request_rec * r)2507 API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
2508 {
2509     int rcode;
2510 
2511     if (r->connection->aborted)
2512         return EOF;
2513 
2514     rcode = ap_bputs(str, r->connection->client);
2515     if (rcode < 0) {
2516         if (!r->connection->aborted) {
2517             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2518                 "client stopped connection before rputs completed");
2519             ap_bsetflag(r->connection->client, B_EOUT, 1);
2520             r->connection->aborted = 1;
2521         }
2522         return EOF;
2523     }
2524     SET_BYTES_SENT(r);
2525     return rcode;
2526 }
2527 
ap_rwrite(const void * buf,int nbyte,request_rec * r)2528 API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
2529 {
2530     int n;
2531 
2532     if (r->connection->aborted)
2533         return -1;
2534 
2535     n = ap_bwrite(r->connection->client, buf, nbyte);
2536     if (n < 0) {
2537         if (!r->connection->aborted) {
2538             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2539                 "client stopped connection before rwrite completed");
2540             ap_bsetflag(r->connection->client, B_EOUT, 1);
2541             r->connection->aborted = 1;
2542         }
2543         return -1;
2544     }
2545     SET_BYTES_SENT(r);
2546     return n;
2547 }
2548 
ap_vrprintf(request_rec * r,const char * fmt,va_list ap)2549 API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list ap)
2550 {
2551     int n;
2552 
2553     if (r->connection->aborted)
2554         return -1;
2555 
2556     n = ap_vbprintf(r->connection->client, fmt, ap);
2557 
2558     if (n < 0) {
2559         if (!r->connection->aborted) {
2560             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2561                 "client stopped connection before vrprintf completed");
2562             ap_bsetflag(r->connection->client, B_EOUT, 1);
2563             r->connection->aborted = 1;
2564         }
2565         return -1;
2566     }
2567     SET_BYTES_SENT(r);
2568     return n;
2569 }
2570 
ap_rprintf(request_rec * r,const char * fmt,...)2571 API_EXPORT_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt,...)
2572 {
2573     va_list vlist;
2574     int n;
2575 
2576     if (r->connection->aborted)
2577         return -1;
2578 
2579     va_start(vlist, fmt);
2580     n = ap_vbprintf(r->connection->client, fmt, vlist);
2581     va_end(vlist);
2582 
2583     if (n < 0) {
2584         if (!r->connection->aborted) {
2585             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2586                 "client stopped connection before rprintf completed");
2587             ap_bsetflag(r->connection->client, B_EOUT, 1);
2588             r->connection->aborted = 1;
2589         }
2590         return -1;
2591     }
2592     SET_BYTES_SENT(r);
2593     return n;
2594 }
2595 
ap_rvputs(request_rec * r,...)2596 API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
2597 {
2598     va_list args;
2599     int i, j, k;
2600     const char *x;
2601     BUFF *fb = r->connection->client;
2602 
2603     if (r->connection->aborted)
2604         return EOF;
2605 
2606     va_start(args, r);
2607     for (k = 0;;) {
2608         x = va_arg(args, const char *);
2609         if (x == NULL)
2610             break;
2611         j = strlen(x);
2612         i = ap_bwrite(fb, x, j);
2613         if (i != j) {
2614             va_end(args);
2615             if (!r->connection->aborted) {
2616                 ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2617                     "client stopped connection before rvputs completed");
2618                 ap_bsetflag(r->connection->client, B_EOUT, 1);
2619                 r->connection->aborted = 1;
2620             }
2621             return EOF;
2622         }
2623         k += i;
2624     }
2625     va_end(args);
2626 
2627     SET_BYTES_SENT(r);
2628     return k;
2629 }
2630 
ap_rflush(request_rec * r)2631 API_EXPORT(int) ap_rflush(request_rec *r)
2632 {
2633     if (ap_bflush(r->connection->client) < 0) {
2634         if (!r->connection->aborted) {
2635             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2636                 "client stopped connection before rflush completed");
2637             ap_bsetflag(r->connection->client, B_EOUT, 1);
2638             r->connection->aborted = 1;
2639         }
2640         return EOF;
2641     }
2642     return 0;
2643 }
2644 
2645 /* We should have named this send_canned_response, since it is used for any
2646  * response that can be generated by the server from the request record.
2647  * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
2648  * and 5xx (server error) messages that have not been redirected to another
2649  * handler via the ErrorDocument feature.
2650  */
ap_send_error_response(request_rec * r,int recursive_error)2651 API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error)
2652 {
2653     int status = r->status;
2654     int idx = ap_index_of_response(status);
2655     char *custom_response;
2656     const char *location = ap_table_get(r->headers_out, "Location");
2657 
2658     /*
2659      * It's possible that the Location field might be in r->err_headers_out
2660      * instead of r->headers_out; use the latter if possible, else the
2661      * former.
2662      */
2663     if (location == NULL) {
2664 	location = ap_table_get(r->err_headers_out, "Location");
2665     }
2666     /* We need to special-case the handling of 204 and 304 responses,
2667      * since they have specific HTTP requirements and do not include a
2668      * message body.  Note that being assbackwards here is not an option.
2669      */
2670     if (status == HTTP_NOT_MODIFIED) {
2671         if (!ap_is_empty_table(r->err_headers_out))
2672             r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
2673                                                r->headers_out);
2674         ap_hard_timeout("send 304", r);
2675 
2676         ap_basic_http_header(r);
2677         ap_set_keepalive(r);
2678 
2679         ap_table_do((int (*)(void *, const char *, const char *)) ap_send_header_field,
2680                     (void *) r, r->headers_out,
2681                     "Connection",
2682                     "Keep-Alive",
2683                     "ETag",
2684                     "Content-Location",
2685                     "Expires",
2686                     "Cache-Control",
2687                     "Vary",
2688                     "Warning",
2689                     "WWW-Authenticate",
2690                     "Proxy-Authenticate",
2691                     NULL);
2692 
2693         terminate_header(r->connection->client);
2694 
2695         ap_kill_timeout(r);
2696         return;
2697     }
2698 
2699     if (status == HTTP_NO_CONTENT) {
2700         ap_send_http_header(r);
2701         ap_finalize_request_protocol(r);
2702         return;
2703     }
2704 
2705     if (!r->assbackwards) {
2706         table *tmp = r->headers_out;
2707 
2708         /* For all HTTP/1.x responses for which we generate the message,
2709          * we need to avoid inheriting the "normal status" header fields
2710          * that may have been set by the request handler before the
2711          * error or redirect, except for Location on external redirects.
2712          */
2713         r->headers_out = r->err_headers_out;
2714         r->err_headers_out = tmp;
2715         ap_clear_table(r->err_headers_out);
2716 
2717         if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
2718             if ((location != NULL) && *location) {
2719 	        ap_table_setn(r->headers_out, "Location", location);
2720             }
2721             else {
2722                 location = "";   /* avoids coredump when printing, below */
2723             }
2724         }
2725 
2726         r->content_language = NULL;
2727         r->content_languages = NULL;
2728         r->content_encoding = NULL;
2729         r->clength = 0;
2730         if (ap_table_get(r->subprocess_env,
2731                          "suppress-error-charset") != NULL) {
2732             r->content_type = "text/html";
2733         }
2734         else {
2735             r->content_type = "text/html; charset=iso-8859-1";
2736         }
2737 
2738         if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
2739             ap_table_setn(r->headers_out, "Allow", make_allow(r));
2740 
2741         ap_send_http_header(r);
2742 
2743         if (r->header_only) {
2744             ap_finalize_request_protocol(r);
2745             ap_rflush(r);
2746             return;
2747         }
2748     }
2749 
2750     ap_hard_timeout("send error body", r);
2751 
2752     if ((custom_response = ap_response_code_string(r, idx))) {
2753         /*
2754          * We have a custom response output. This should only be
2755          * a text-string to write back. But if the ErrorDocument
2756          * was a local redirect and the requested resource failed
2757          * for any reason, the custom_response will still hold the
2758          * redirect URL. We don't really want to output this URL
2759          * as a text message, so first check the custom response
2760          * string to ensure that it is a text-string (using the
2761          * same test used in ap_die(), i.e. does it start with a ").
2762          * If it doesn't, we've got a recursive error, so find
2763          * the original error and output that as well.
2764          */
2765         if (custom_response[0] == '\"') {
2766             ap_rputs(custom_response + 1, r);
2767             ap_kill_timeout(r);
2768             ap_finalize_request_protocol(r);
2769             ap_rflush(r);
2770             return;
2771         }
2772         /*
2773          * Redirect failed, so get back the original error
2774          */
2775         while (r->prev && (r->prev->status != HTTP_OK))
2776             r = r->prev;
2777     }
2778     {
2779         const char *title = status_lines[idx];
2780         const char *h1;
2781         const char *error_notes;
2782 
2783         /* Accept a status_line set by a module, but only if it begins
2784          * with the 3 digit status code
2785          */
2786         if (r->status_line != NULL
2787             && strlen(r->status_line) > 4       /* long enough */
2788             && isdigit((unsigned char)r->status_line[0])
2789             && isdigit((unsigned char)r->status_line[1])
2790             && isdigit((unsigned char)r->status_line[2])
2791             && ap_isspace(r->status_line[3])
2792             && ap_isalnum(r->status_line[4])) {
2793             title = r->status_line;
2794         }
2795 
2796         /* folks decided they didn't want the error code in the H1 text */
2797         h1 = &title[4];
2798 
2799         ap_rvputs(r,
2800                   DOCTYPE_HTML_2_0
2801                   "<HTML><HEAD>\n<TITLE>", title,
2802                   "</TITLE>\n</HEAD><BODY>\n<H1>", h1, "</H1>\n",
2803                   NULL);
2804 
2805 	switch (status) {
2806 	case HTTP_MOVED_PERMANENTLY:
2807 	case HTTP_MOVED_TEMPORARILY:
2808 	case HTTP_TEMPORARY_REDIRECT:
2809 	    ap_rvputs(r, "The document has moved <A HREF=\"",
2810 		      ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
2811 		      NULL);
2812 	    break;
2813 	case HTTP_SEE_OTHER:
2814 	    ap_rvputs(r, "The answer to your request is located <A HREF=\"",
2815 		      ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
2816 		      NULL);
2817 	    break;
2818 	case HTTP_USE_PROXY:
2819 	    ap_rvputs(r, "This resource is only accessible "
2820 		      "through the proxy\n",
2821 		      ap_escape_html(r->pool, location),
2822 		      "<BR>\nYou will need to ",
2823 		      "configure your client to use that proxy.<P>\n", NULL);
2824 	    break;
2825 	case HTTP_PROXY_AUTHENTICATION_REQUIRED:
2826 	case AUTH_REQUIRED:
2827 	    ap_rputs("This server could not verify that you\n"
2828 	             "are authorized to access the document\n"
2829 	             "requested.  Either you supplied the wrong\n"
2830 	             "credentials (e.g., bad password), or your\n"
2831 	             "browser doesn't understand how to supply\n"
2832 	             "the credentials required.<P>\n", r);
2833 	    break;
2834 	case BAD_REQUEST:
2835 	    ap_rputs("Your browser sent a request that "
2836 	             "this server could not understand.<P>\n", r);
2837 	    if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2838 		ap_rvputs(r, error_notes, "<P>\n", NULL);
2839 	    }
2840 	    break;
2841 	case HTTP_FORBIDDEN:
2842 	    ap_rvputs(r, "You don't have permission to access ",
2843 		      ap_escape_html(r->pool, r->uri),
2844 		      "\non this server.<P>\n", NULL);
2845 	    break;
2846 	case NOT_FOUND:
2847 	    ap_rvputs(r, "The requested URL ",
2848 		      ap_escape_html(r->pool, r->uri),
2849 		      " was not found on this server.<P>\n", NULL);
2850 	    break;
2851 	case METHOD_NOT_ALLOWED:
2852 	    ap_rvputs(r, "The requested method ", r->method,
2853 		      " is not allowed "
2854 		      "for the URL ", ap_escape_html(r->pool, r->uri),
2855 		      ".<P>\n", NULL);
2856 	    break;
2857 	case NOT_ACCEPTABLE:
2858 	    ap_rvputs(r,
2859 		      "An appropriate representation of the "
2860 		      "requested resource ",
2861 		      ap_escape_html(r->pool, r->uri),
2862 		      " could not be found on this server.<P>\n", NULL);
2863 	    /* fall through */
2864 	case MULTIPLE_CHOICES:
2865 	    {
2866 		const char *list;
2867 		if ((list = ap_table_get(r->notes, "variant-list")))
2868 		    ap_rputs(list, r);
2869 	    }
2870 	    break;
2871 	case LENGTH_REQUIRED:
2872 	    ap_rvputs(r, "A request of the requested method ", r->method,
2873 		      " requires a valid Content-length.<P>\n", NULL);
2874 	    if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2875 		ap_rvputs(r, error_notes, "<P>\n", NULL);
2876 	    }
2877 	    break;
2878 	case PRECONDITION_FAILED:
2879 	    ap_rvputs(r, "The precondition on the request for the URL ",
2880 		      ap_escape_html(r->pool, r->uri),
2881 		      " evaluated to false.<P>\n", NULL);
2882 	    break;
2883 	case HTTP_NOT_IMPLEMENTED:
2884 	    ap_rvputs(r, ap_escape_html(r->pool, r->method), " to ",
2885 		      ap_escape_html(r->pool, r->uri),
2886 		      " not supported.<P>\n", NULL);
2887 	    if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2888 		ap_rvputs(r, error_notes, "<P>\n", NULL);
2889 	    }
2890 	    break;
2891 	case BAD_GATEWAY:
2892 	    ap_rputs("The proxy server received an invalid" CRLF
2893 	             "response from an upstream server.<P>" CRLF, r);
2894 	    if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2895 		ap_rvputs(r, error_notes, "<P>\n", NULL);
2896 	    }
2897 	    break;
2898 	case VARIANT_ALSO_VARIES:
2899 	    ap_rvputs(r, "A variant for the requested resource\n<PRE>\n",
2900 		      ap_escape_html(r->pool, r->uri),
2901 		      "\n</PRE>\nis itself a negotiable resource. "
2902 		      "This indicates a configuration error.<P>\n", NULL);
2903 	    break;
2904 	case HTTP_REQUEST_TIME_OUT:
2905 	    ap_rputs("Server timeout waiting for the HTTP request from the client.\n", r);
2906 	    break;
2907 	case HTTP_GONE:
2908 	    ap_rvputs(r, "The requested resource<BR>",
2909 		      ap_escape_html(r->pool, r->uri),
2910 		      "<BR>\nis no longer available on this server ",
2911 		      "and there is no forwarding address.\n",
2912 		      "Please remove all references to this resource.\n",
2913 		      NULL);
2914 	    break;
2915 	case HTTP_REQUEST_ENTITY_TOO_LARGE:
2916 	    ap_rvputs(r, "The requested resource<BR>",
2917 		      ap_escape_html(r->pool, r->uri), "<BR>\n",
2918 		      "does not allow request data with ", r->method,
2919 		      " requests, or the amount of data provided in\n",
2920 		      "the request exceeds the capacity limit.\n", NULL);
2921 	    break;
2922 	case HTTP_REQUEST_URI_TOO_LARGE:
2923 	    ap_rputs("The requested URL's length exceeds the capacity\n"
2924 	             "limit for this server.<P>\n", r);
2925 	    if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2926 		ap_rvputs(r, error_notes, "<P>\n", NULL);
2927 	    }
2928 	    break;
2929 	case HTTP_UNSUPPORTED_MEDIA_TYPE:
2930 	    ap_rputs("The supplied request data is not in a format\n"
2931 	             "acceptable for processing by this resource.\n", r);
2932 	    break;
2933 	case HTTP_RANGE_NOT_SATISFIABLE:
2934 	    ap_rputs("None of the range-specifier values in the Range\n"
2935 	             "request-header field overlap the current extent\n"
2936 	             "of the selected resource.\n", r);
2937 	    break;
2938 	case HTTP_EXPECTATION_FAILED:
2939 	    ap_rvputs(r, "The expectation given in the Expect request-header"
2940 	              "\nfield could not be met by this server.<P>\n"
2941 	              "The client sent<PRE>\n    Expect: ",
2942 	              ap_escape_html(r->pool, ap_table_get(r->headers_in,
2943 		      "Expect")), "\n</PRE>\n"
2944 	              "but we only allow the 100-continue expectation.\n",
2945 	              NULL);
2946 	    break;
2947 	case HTTP_UNPROCESSABLE_ENTITY:
2948 	    ap_rputs("The server understands the media type of the\n"
2949 	             "request entity, but was unable to process the\n"
2950 	             "contained instructions.\n", r);
2951 	    break;
2952 	case HTTP_LOCKED:
2953 	    ap_rputs("The requested resource is currently locked.\n"
2954 	             "The lock must be released or proper identification\n"
2955 	             "given before the method can be applied.\n", r);
2956 	    break;
2957 	case HTTP_FAILED_DEPENDENCY:
2958 	    ap_rputs("The method could not be performed on the resource\n"
2959 	             "because the requested action depended on another\n"
2960 	             "action and that other action failed.\n", r);
2961 	    break;
2962 	case HTTP_INSUFFICIENT_STORAGE:
2963 	    ap_rputs("The method could not be performed on the resource\n"
2964 	             "because the server is unable to store the\n"
2965 	             "representation needed to successfully complete the\n"
2966 	             "request.  There is insufficient free space left in\n"
2967 	             "your storage allocation.\n", r);
2968 	    break;
2969 	case HTTP_SERVICE_UNAVAILABLE:
2970 	    ap_rputs("The server is temporarily unable to service your\n"
2971 	             "request due to maintenance downtime or capacity\n"
2972 	             "problems. Please try again later.\n", r);
2973 	    break;
2974 	case HTTP_GATEWAY_TIME_OUT:
2975 	    ap_rputs("The proxy server did not receive a timely response\n"
2976 	             "from the upstream server.\n", r);
2977 	    break;
2978 	case HTTP_NOT_EXTENDED:
2979 	    ap_rputs("A mandatory extension policy in the request is not\n"
2980 	             "accepted by the server for this resource.\n", r);
2981 	    break;
2982 	default:            /* HTTP_INTERNAL_SERVER_ERROR */
2983 	    /*
2984 	     * This comparison to expose error-notes could be modified to
2985 	     * use a configuration directive and export based on that
2986 	     * directive.  For now "*" is used to designate an error-notes
2987 	     * that is totally safe for any user to see (ie lacks paths,
2988 	     * database passwords, etc.)
2989 	     */
2990 	    if (((error_notes = ap_table_get(r->notes, "error-notes")) != NULL)
2991 		&& (h1 = ap_table_get(r->notes, "verbose-error-to")) != NULL
2992 		&& (strcmp(h1, "*") == 0)) {
2993 	        ap_rvputs(r, error_notes, "<P>\n", NULL);
2994 	    }
2995 	    else {
2996 	        ap_rvputs(r, "The server encountered an internal error or\n"
2997 	             "misconfiguration and was unable to complete\n"
2998 	             "your request.<P>\n"
2999 	             "Please contact the server administrator,\n ",
3000 	             ap_escape_html(r->pool, r->server->server_admin),
3001 	             " and inform them of the time the error occurred,\n"
3002 	             "and anything you might have done that may have\n"
3003 	             "caused the error.<P>\n"
3004 		     "More information about this error may be available\n"
3005 		     "in the server error log.<P>\n", NULL);
3006 	    }
3007 	 /*
3008 	  * It would be nice to give the user the information they need to
3009 	  * fix the problem directly since many users don't have access to
3010 	  * the error_log (think University sites) even though they can easily
3011 	  * get this error by misconfiguring an htaccess file.  However, the
3012 	  * error notes tend to include the real file pathname in this case,
3013 	  * which some people consider to be a breach of privacy.  Until we
3014 	  * can figure out a way to remove the pathname, leave this commented.
3015 	  *
3016 	  * if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
3017 	  *     ap_rvputs(r, error_notes, "<P>\n", NULL);
3018 	  * }
3019 	  */
3020 	    break;
3021 	}
3022 
3023         if (recursive_error) {
3024             ap_rvputs(r, "<P>Additionally, a ",
3025                       status_lines[ap_index_of_response(recursive_error)],
3026                       "\nerror was encountered while trying to use an "
3027                       "ErrorDocument to handle the request.\n", NULL);
3028         }
3029         ap_rputs(ap_psignature("<HR>\n", r), r);
3030         ap_rputs("</BODY></HTML>\n", r);
3031     }
3032     ap_kill_timeout(r);
3033     ap_finalize_request_protocol(r);
3034     ap_rflush(r);
3035 }
3036 
3037 /*
3038  * The shared hash context, copies of which are used by all children for
3039  * etag generation.  ap_init_etag() must be called once before all the
3040  * children are created.  We use a secret hash initialization value
3041  * so that people can't brute-force inode numbers.
3042  */
3043 static AP_SHA1_CTX baseCtx;
3044 
ap_create_etag_state(pool * pconf)3045 int ap_create_etag_state(pool *pconf)
3046 {
3047     unsigned int u;
3048     int fd;
3049     char *filename;
3050     unsigned char rnd[16];
3051 
3052     filename = ap_server_root_relative(pconf, "logs/etag-state");
3053     ap_server_strip_chroot(filename, 0);
3054 
3055     if ((fd = open(filename, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, 0640)) ==
3056       -1) {
3057         ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
3058           "could not create %s", filename);
3059         exit(-1);
3060     }
3061 
3062     if (fchown(fd, -1, ap_group_id) == -1) {
3063         ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
3064           "could not chown %s", filename);
3065         exit(-1);
3066     }
3067 
3068     /* generate random bytes and write them */
3069     arc4random_buf(rnd, sizeof(rnd));
3070     if (write(fd, &rnd, sizeof(rnd)) != 16) {
3071             ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
3072               "could not write to %s", filename);
3073             exit(-1);
3074     }
3075 
3076     close (fd);
3077     return (0);
3078 }
3079 
ap_read_etag_state(pool * pconf)3080 int ap_read_etag_state(pool *pconf)
3081 {
3082     struct stat st;
3083     unsigned int u;
3084     int fd;
3085     char *filename;
3086     unsigned char rnd[16];
3087 
3088     ap_SHA1Init(&baseCtx);
3089 
3090     filename = ap_server_root_relative(pconf, "logs/etag-state");
3091     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, NULL,
3092       "Initializing etag from %s", filename);
3093 
3094     ap_server_strip_chroot(filename, 0);
3095 
3096     if ((fd = open(filename, O_RDONLY|O_NOFOLLOW, 0640)) == -1)
3097 	return (-1);
3098 
3099     fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP);
3100     fchown(fd, -1, ap_group_id);
3101 
3102     if (fstat(fd, &st) == -1) {
3103         ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
3104           "could not fstat %s", filename);
3105         exit(-1);
3106     }
3107 
3108     if (st.st_size != sizeof(rnd)) {
3109 	return (-1);
3110     }
3111 
3112     /* read 4 random 32-bit uints from file and update the hash context */
3113         if (read(fd, &rnd, sizeof(rnd)) != sizeof(rnd))
3114             return (-1);
3115 
3116         ap_SHA1Update_binary(&baseCtx, (const unsigned char *)&rnd,
3117           sizeof(rnd));
3118 
3119     if (close(fd) == -1) {
3120         ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
3121           "could not properly close %s", filename);
3122         exit(-1);
3123     }
3124     return (0);
3125 }
3126 
ap_init_etag(pool * pconf)3127 API_EXPORT(void) ap_init_etag(pool *pconf)
3128 {
3129     if (ap_read_etag_state(pconf) == -1) {
3130         ap_create_etag_state(pconf);
3131         if (ap_read_etag_state(pconf) == -1) {
3132             ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
3133               "could not initialize etag state");
3134             exit(-1);
3135         }
3136     }
3137 }
3138 
ap_make_etag(request_rec * r,int force_weak)3139 API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak)
3140 {
3141     AP_SHA1_CTX hashCtx;
3142     core_dir_config *cfg;
3143     etag_components_t etag_bits;
3144     int weak;
3145     unsigned char md[SHA_DIGESTSIZE];
3146 
3147     memcpy(&hashCtx, &baseCtx, sizeof(hashCtx));
3148 
3149     cfg = (core_dir_config *)ap_get_module_config(r->per_dir_config,
3150       &core_module);
3151     etag_bits = (cfg->etag_bits & (~ cfg->etag_remove)) | cfg->etag_add;
3152     if (etag_bits == ETAG_UNSET)
3153         etag_bits = ETAG_BACKWARD;
3154 
3155     weak = ((r->request_time - r->mtime <= 1) || force_weak);
3156 
3157     if (r->finfo.st_mode != 0) {
3158         if (etag_bits & ETAG_NONE) {
3159             ap_table_setn(r->notes, "no-etag", "omit");
3160             return "";
3161         }
3162         if (etag_bits & ETAG_INODE) {
3163             ap_SHA1Update_binary(&hashCtx,
3164               (const unsigned char *)&r->finfo.st_dev,
3165               sizeof(r->finfo.st_dev));
3166             ap_SHA1Update_binary(&hashCtx,
3167               (const unsigned char *)&r->finfo.st_ino,
3168               sizeof(r->finfo.st_ino));
3169         }
3170         if (etag_bits & ETAG_SIZE)
3171             ap_SHA1Update_binary(&hashCtx,
3172               (const unsigned char *)&r->finfo.st_size,
3173               sizeof(r->finfo.st_size));
3174         if (etag_bits & ETAG_MTIME)
3175             ap_SHA1Update_binary(&hashCtx,
3176               (const unsigned char *)&r->mtime,
3177               sizeof(r->mtime));
3178     }
3179     else {
3180         weak = 1;
3181         ap_SHA1Update_binary(&hashCtx, (const unsigned char *)&r->mtime,
3182           sizeof(r->mtime));
3183     }
3184     ap_SHA1Final(md, &hashCtx);
3185     return ap_psprintf(r->pool, "%s\""
3186       "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
3187         "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
3188         "\"", weak ? "W/" : "",
3189       md[0], md[1], md[2], md[3], md[4], md[5], md[6], md[7],
3190       md[8], md[9], md[10], md[11], md[12], md[13], md[14], md[15],
3191       md[16], md[17], md[18], md[19]);
3192 }
3193