xref: /openbsd-src/usr.sbin/httpd/server_http.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: server_http.c,v 1.137 2020/02/25 15:18:41 sthen Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 - 2018 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/socket.h>
22 #include <sys/tree.h>
23 
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <limits.h>
32 #include <fnmatch.h>
33 #include <stdio.h>
34 #include <time.h>
35 #include <resolv.h>
36 #include <event.h>
37 #include <ctype.h>
38 #include <vis.h>
39 
40 #include "httpd.h"
41 #include "http.h"
42 #include "patterns.h"
43 
44 static int	 server_httpmethod_cmp(const void *, const void *);
45 static int	 server_httperror_cmp(const void *, const void *);
46 void		 server_httpdesc_free(struct http_descriptor *);
47 int		 server_http_authenticate(struct server_config *,
48 		    struct client *);
49 char		*server_expand_http(struct client *, const char *,
50 		    char *, size_t);
51 
52 static struct http_method	 http_methods[] = HTTP_METHODS;
53 static struct http_error	 http_errors[] = HTTP_ERRORS;
54 
55 void
56 server_http(void)
57 {
58 	DPRINTF("%s: sorting lookup tables, pid %d", __func__, getpid());
59 
60 	/* Sort the HTTP lookup arrays */
61 	qsort(http_methods, sizeof(http_methods) /
62 	    sizeof(http_methods[0]) - 1,
63 	    sizeof(http_methods[0]), server_httpmethod_cmp);
64 	qsort(http_errors, sizeof(http_errors) /
65 	    sizeof(http_errors[0]) - 1,
66 	    sizeof(http_errors[0]), server_httperror_cmp);
67 }
68 
69 void
70 server_http_init(struct server *srv)
71 {
72 	/* nothing */
73 }
74 
75 int
76 server_httpdesc_init(struct client *clt)
77 {
78 	struct http_descriptor	*desc;
79 
80 	if ((desc = calloc(1, sizeof(*desc))) == NULL)
81 		return (-1);
82 	RB_INIT(&desc->http_headers);
83 	clt->clt_descreq = desc;
84 
85 	if ((desc = calloc(1, sizeof(*desc))) == NULL) {
86 		/* req will be cleaned up later */
87 		return (-1);
88 	}
89 	RB_INIT(&desc->http_headers);
90 	clt->clt_descresp = desc;
91 
92 	return (0);
93 }
94 
95 void
96 server_httpdesc_free(struct http_descriptor *desc)
97 {
98 	if (desc == NULL)
99 		return;
100 
101 	free(desc->http_path);
102 	desc->http_path = NULL;
103 	free(desc->http_path_alias);
104 	desc->http_path_alias = NULL;
105 	free(desc->http_query);
106 	desc->http_query = NULL;
107 	free(desc->http_query_alias);
108 	desc->http_query_alias = NULL;
109 	free(desc->http_version);
110 	desc->http_version = NULL;
111 	free(desc->http_host);
112 	desc->http_host = NULL;
113 
114 	kv_purge(&desc->http_headers);
115 	desc->http_lastheader = NULL;
116 	desc->http_method = 0;
117 	desc->http_chunked = 0;
118 }
119 
120 int
121 server_http_authenticate(struct server_config *srv_conf, struct client *clt)
122 {
123 	char			 decoded[1024];
124 	FILE			*fp = NULL;
125 	struct http_descriptor	*desc = clt->clt_descreq;
126 	const struct auth	*auth = srv_conf->auth;
127 	struct kv		*ba, key;
128 	size_t			 linesize = 0;
129 	ssize_t			 linelen;
130 	int			 ret = -1;
131 	char			*line = NULL, *user = NULL, *pass = NULL;
132 	char			*clt_user = NULL, *clt_pass = NULL;
133 
134 	memset(decoded, 0, sizeof(decoded));
135 	key.kv_key = "Authorization";
136 
137 	if ((ba = kv_find(&desc->http_headers, &key)) == NULL ||
138 	    ba->kv_value == NULL)
139 		goto done;
140 
141 	if (strncmp(ba->kv_value, "Basic ", strlen("Basic ")) != 0)
142 		goto done;
143 
144 	if (b64_pton(strchr(ba->kv_value, ' ') + 1, (uint8_t *)decoded,
145 	    sizeof(decoded)) <= 0)
146 		goto done;
147 
148 	if ((clt_pass = strchr(decoded, ':')) == NULL)
149 		goto done;
150 
151 	clt_user = decoded;
152 	*clt_pass++ = '\0';
153 	if ((clt->clt_remote_user = strdup(clt_user)) == NULL)
154 		goto done;
155 
156 	if ((fp = fopen(auth->auth_htpasswd, "r")) == NULL)
157 		goto done;
158 
159 	while ((linelen = getline(&line, &linesize, fp)) != -1) {
160 		if (line[linelen - 1] == '\n')
161 			line[linelen - 1] = '\0';
162 		user = line;
163 		pass = strchr(line, ':');
164 
165 		if (pass == NULL) {
166 			explicit_bzero(line, linelen);
167 			continue;
168 		}
169 
170 		*pass++ = '\0';
171 
172 		if (strcmp(clt_user, user) != 0) {
173 			explicit_bzero(line, linelen);
174 			continue;
175 		}
176 
177 		if (crypt_checkpass(clt_pass, pass) == 0) {
178 			explicit_bzero(line, linelen);
179 			ret = 0;
180 			break;
181 		}
182 	}
183 done:
184 	free(line);
185 	if (fp != NULL)
186 		fclose(fp);
187 
188 	if (ba != NULL && ba->kv_value != NULL) {
189 		explicit_bzero(ba->kv_value, strlen(ba->kv_value));
190 		explicit_bzero(decoded, sizeof(decoded));
191 	}
192 
193 	return (ret);
194 }
195 
196 void
197 server_read_http(struct bufferevent *bev, void *arg)
198 {
199 	struct client		*clt = arg;
200 	struct http_descriptor	*desc = clt->clt_descreq;
201 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
202 	char			*line = NULL, *key, *value;
203 	const char		*errstr;
204 	size_t			 size, linelen;
205 	struct kv		*hdr = NULL;
206 
207 	getmonotime(&clt->clt_tv_last);
208 
209 	size = EVBUFFER_LENGTH(src);
210 	DPRINTF("%s: session %d: size %lu, to read %lld",
211 	    __func__, clt->clt_id, size, clt->clt_toread);
212 	if (!size) {
213 		clt->clt_toread = TOREAD_HTTP_HEADER;
214 		goto done;
215 	}
216 
217 	while (!clt->clt_headersdone) {
218 		if (!clt->clt_line) {
219 			/* Peek into the buffer to see if it looks like HTTP */
220 			key = EVBUFFER_DATA(src);
221 			if (!isalpha((unsigned char)*key)) {
222 				server_abort_http(clt, 400,
223 				    "invalid request line");
224 				goto abort;
225 			}
226 		}
227 
228 		if ((line = evbuffer_readln(src,
229 		    &linelen, EVBUFFER_EOL_CRLF_STRICT)) == NULL) {
230 			/* No newline found after too many bytes */
231 			if (size > SERVER_MAXHEADERLENGTH) {
232 				server_abort_http(clt, 413,
233 				    "request line too long");
234 				goto abort;
235 			}
236 			break;
237 		}
238 
239 		/*
240 		 * An empty line indicates the end of the request.
241 		 * libevent already stripped the \r\n for us.
242 		 */
243 		if (!linelen) {
244 			clt->clt_headersdone = 1;
245 			free(line);
246 			break;
247 		}
248 		key = line;
249 
250 		/* Limit the total header length minus \r\n */
251 		clt->clt_headerlen += linelen;
252 		if (clt->clt_headerlen > SERVER_MAXHEADERLENGTH) {
253 			server_abort_http(clt, 413, "request too large");
254 			goto abort;
255 		}
256 
257 		/*
258 		 * The first line is the GET/POST/PUT/... request,
259 		 * subsequent lines are HTTP headers.
260 		 */
261 		if (++clt->clt_line == 1)
262 			value = strchr(key, ' ');
263 		else if (*key == ' ' || *key == '\t')
264 			/* Multiline headers wrap with a space or tab */
265 			value = NULL;
266 		else
267 			value = strchr(key, ':');
268 		if (value == NULL) {
269 			if (clt->clt_line == 1) {
270 				server_abort_http(clt, 400, "malformed");
271 				goto abort;
272 			}
273 
274 			/* Append line to the last header, if present */
275 			if (kv_extend(&desc->http_headers,
276 			    desc->http_lastheader, line) == NULL)
277 				goto fail;
278 
279 			free(line);
280 			continue;
281 		}
282 		if (*value == ':') {
283 			*value++ = '\0';
284 			value += strspn(value, " \t\r\n");
285 		} else {
286 			*value++ = '\0';
287 		}
288 
289 		DPRINTF("%s: session %d: header '%s: %s'", __func__,
290 		    clt->clt_id, key, value);
291 
292 		/*
293 		 * Identify and handle specific HTTP request methods
294 		 */
295 		if (clt->clt_line == 1) {
296 			if ((desc->http_method = server_httpmethod_byname(key))
297 			    == HTTP_METHOD_NONE) {
298 				server_abort_http(clt, 400, "malformed");
299 				goto abort;
300 			}
301 
302 			/*
303 			 * Decode request path and query
304 			 */
305 			desc->http_path = strdup(value);
306 			if (desc->http_path == NULL)
307 				goto fail;
308 
309 			desc->http_version = strchr(desc->http_path, ' ');
310 			if (desc->http_version == NULL) {
311 				server_abort_http(clt, 400, "malformed");
312 				goto abort;
313 			}
314 
315 			*desc->http_version++ = '\0';
316 			desc->http_query = strchr(desc->http_path, '?');
317 			if (desc->http_query != NULL)
318 				*desc->http_query++ = '\0';
319 
320 			/*
321 			 * Have to allocate the strings because they could
322 			 * be changed independently by the filters later.
323 			 */
324 			if ((desc->http_version =
325 			    strdup(desc->http_version)) == NULL)
326 				goto fail;
327 
328 			if (desc->http_query != NULL &&
329 			    (desc->http_query =
330 			    strdup(desc->http_query)) == NULL)
331 				goto fail;
332 
333 		} else if (desc->http_method != HTTP_METHOD_NONE &&
334 		    strcasecmp("Content-Length", key) == 0) {
335 			if (desc->http_method == HTTP_METHOD_TRACE ||
336 			    desc->http_method == HTTP_METHOD_CONNECT) {
337 				/*
338 				 * These method should not have a body
339 				 * and thus no Content-Length header.
340 				 */
341 				server_abort_http(clt, 400, "malformed");
342 				goto abort;
343 			}
344 
345 			/*
346 			 * Need to read data from the client after the
347 			 * HTTP header.
348 			 * XXX What about non-standard clients not using
349 			 * the carriage return? And some browsers seem to
350 			 * include the line length in the content-length.
351 			 */
352 			clt->clt_toread = strtonum(value, 0, LLONG_MAX,
353 			    &errstr);
354 			if (errstr) {
355 				server_abort_http(clt, 500, errstr);
356 				goto abort;
357 			}
358 		}
359 
360 		if (strcasecmp("Transfer-Encoding", key) == 0 &&
361 		    strcasecmp("chunked", value) == 0)
362 			desc->http_chunked = 1;
363 
364 		if (clt->clt_line != 1) {
365 			if ((hdr = kv_add(&desc->http_headers, key,
366 			    value)) == NULL)
367 				goto fail;
368 
369 			desc->http_lastheader = hdr;
370 		}
371 
372 		free(line);
373 	}
374 	if (clt->clt_headersdone) {
375 		if (desc->http_method == HTTP_METHOD_NONE) {
376 			server_abort_http(clt, 406, "no method");
377 			return;
378 		}
379 
380 		switch (desc->http_method) {
381 		case HTTP_METHOD_CONNECT:
382 			/* Data stream */
383 			clt->clt_toread = TOREAD_UNLIMITED;
384 			bev->readcb = server_read;
385 			break;
386 		case HTTP_METHOD_GET:
387 		case HTTP_METHOD_HEAD:
388 		/* WebDAV methods */
389 		case HTTP_METHOD_COPY:
390 		case HTTP_METHOD_MOVE:
391 			clt->clt_toread = 0;
392 			break;
393 		case HTTP_METHOD_DELETE:
394 		case HTTP_METHOD_OPTIONS:
395 		case HTTP_METHOD_POST:
396 		case HTTP_METHOD_PUT:
397 		case HTTP_METHOD_RESPONSE:
398 		/* WebDAV methods */
399 		case HTTP_METHOD_PROPFIND:
400 		case HTTP_METHOD_PROPPATCH:
401 		case HTTP_METHOD_MKCOL:
402 		case HTTP_METHOD_LOCK:
403 		case HTTP_METHOD_UNLOCK:
404 		case HTTP_METHOD_VERSION_CONTROL:
405 		case HTTP_METHOD_REPORT:
406 		case HTTP_METHOD_CHECKOUT:
407 		case HTTP_METHOD_CHECKIN:
408 		case HTTP_METHOD_UNCHECKOUT:
409 		case HTTP_METHOD_MKWORKSPACE:
410 		case HTTP_METHOD_UPDATE:
411 		case HTTP_METHOD_LABEL:
412 		case HTTP_METHOD_MERGE:
413 		case HTTP_METHOD_BASELINE_CONTROL:
414 		case HTTP_METHOD_MKACTIVITY:
415 		case HTTP_METHOD_ORDERPATCH:
416 		case HTTP_METHOD_ACL:
417 		case HTTP_METHOD_MKREDIRECTREF:
418 		case HTTP_METHOD_UPDATEREDIRECTREF:
419 		case HTTP_METHOD_SEARCH:
420 		case HTTP_METHOD_PATCH:
421 			/* HTTP request payload */
422 			if (clt->clt_toread > 0)
423 				bev->readcb = server_read_httpcontent;
424 
425 			/* Single-pass HTTP body */
426 			if (clt->clt_toread < 0) {
427 				clt->clt_toread = TOREAD_UNLIMITED;
428 				bev->readcb = server_read;
429 			}
430 			break;
431 		default:
432 			server_abort_http(clt, 405, "method not allowed");
433 			return;
434 		}
435 		if (desc->http_chunked) {
436 			/* Chunked transfer encoding */
437 			clt->clt_toread = TOREAD_HTTP_CHUNK_LENGTH;
438 			bev->readcb = server_read_httpchunks;
439 		}
440 
441  done:
442 		if (clt->clt_toread != 0)
443 			bufferevent_disable(bev, EV_READ);
444 		server_response(httpd_env, clt);
445 		return;
446 	}
447 	if (clt->clt_done) {
448 		server_close(clt, "done");
449 		return;
450 	}
451 	if (EVBUFFER_LENGTH(src) && bev->readcb != server_read_http)
452 		bev->readcb(bev, arg);
453 	bufferevent_enable(bev, EV_READ);
454 	return;
455  fail:
456 	server_abort_http(clt, 500, strerror(errno));
457  abort:
458 	free(line);
459 }
460 
461 void
462 server_read_httpcontent(struct bufferevent *bev, void *arg)
463 {
464 	struct client		*clt = arg;
465 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
466 	size_t			 size;
467 
468 	getmonotime(&clt->clt_tv_last);
469 
470 	size = EVBUFFER_LENGTH(src);
471 	DPRINTF("%s: session %d: size %lu, to read %lld", __func__,
472 	    clt->clt_id, size, clt->clt_toread);
473 	if (!size)
474 		return;
475 
476 	if (clt->clt_toread > 0) {
477 		/* Read content data */
478 		if ((off_t)size > clt->clt_toread) {
479 			size = clt->clt_toread;
480 			if (fcgi_add_stdin(clt, src) == -1)
481 				goto fail;
482 			clt->clt_toread = 0;
483 		} else {
484 			if (fcgi_add_stdin(clt, src) == -1)
485 				goto fail;
486 			clt->clt_toread -= size;
487 		}
488 		DPRINTF("%s: done, size %lu, to read %lld", __func__,
489 		    size, clt->clt_toread);
490 	}
491 	if (clt->clt_toread == 0) {
492 		fcgi_add_stdin(clt, NULL);
493 		clt->clt_toread = TOREAD_HTTP_HEADER;
494 		bufferevent_disable(bev, EV_READ);
495 		bev->readcb = server_read_http;
496 		return;
497 	}
498 	if (clt->clt_done)
499 		goto done;
500 	if (bev->readcb != server_read_httpcontent)
501 		bev->readcb(bev, arg);
502 
503 	return;
504  done:
505 	return;
506  fail:
507 	server_close(clt, strerror(errno));
508 }
509 
510 void
511 server_read_httpchunks(struct bufferevent *bev, void *arg)
512 {
513 	struct client		*clt = arg;
514 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
515 	char			*line;
516 	long long		 llval;
517 	size_t			 size;
518 
519 	getmonotime(&clt->clt_tv_last);
520 
521 	size = EVBUFFER_LENGTH(src);
522 	DPRINTF("%s: session %d: size %lu, to read %lld", __func__,
523 	    clt->clt_id, size, clt->clt_toread);
524 	if (!size)
525 		return;
526 
527 	if (clt->clt_toread > 0) {
528 		/* Read chunk data */
529 		if ((off_t)size > clt->clt_toread) {
530 			size = clt->clt_toread;
531 			if (server_bufferevent_write_chunk(clt, src, size)
532 			    == -1)
533 				goto fail;
534 			clt->clt_toread = 0;
535 		} else {
536 			if (server_bufferevent_write_buffer(clt, src) == -1)
537 				goto fail;
538 			clt->clt_toread -= size;
539 		}
540 		DPRINTF("%s: done, size %lu, to read %lld", __func__,
541 		    size, clt->clt_toread);
542 	}
543 	switch (clt->clt_toread) {
544 	case TOREAD_HTTP_CHUNK_LENGTH:
545 		line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
546 		if (line == NULL) {
547 			/* Ignore empty line, continue */
548 			bufferevent_enable(bev, EV_READ);
549 			return;
550 		}
551 		if (strlen(line) == 0) {
552 			free(line);
553 			goto next;
554 		}
555 
556 		/*
557 		 * Read prepended chunk size in hex, ignore the trailer.
558 		 * The returned signed value must not be negative.
559 		 */
560 		if (sscanf(line, "%llx", &llval) != 1 || llval < 0) {
561 			free(line);
562 			server_close(clt, "invalid chunk size");
563 			return;
564 		}
565 
566 		if (server_bufferevent_print(clt, line) == -1 ||
567 		    server_bufferevent_print(clt, "\r\n") == -1) {
568 			free(line);
569 			goto fail;
570 		}
571 		free(line);
572 
573 		if ((clt->clt_toread = llval) == 0) {
574 			DPRINTF("%s: last chunk", __func__);
575 			clt->clt_toread = TOREAD_HTTP_CHUNK_TRAILER;
576 		}
577 		break;
578 	case TOREAD_HTTP_CHUNK_TRAILER:
579 		/* Last chunk is 0 bytes followed by trailer and empty line */
580 		line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
581 		if (line == NULL) {
582 			/* Ignore empty line, continue */
583 			bufferevent_enable(bev, EV_READ);
584 			return;
585 		}
586 		if (server_bufferevent_print(clt, line) == -1 ||
587 		    server_bufferevent_print(clt, "\r\n") == -1) {
588 			free(line);
589 			goto fail;
590 		}
591 		if (strlen(line) == 0) {
592 			/* Switch to HTTP header mode */
593 			clt->clt_toread = TOREAD_HTTP_HEADER;
594 			bev->readcb = server_read_http;
595 		}
596 		free(line);
597 		break;
598 	case 0:
599 		/* Chunk is terminated by an empty newline */
600 		line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
601 		free(line);
602 		if (server_bufferevent_print(clt, "\r\n") == -1)
603 			goto fail;
604 		clt->clt_toread = TOREAD_HTTP_CHUNK_LENGTH;
605 		break;
606 	}
607 
608  next:
609 	if (clt->clt_done)
610 		goto done;
611 	if (EVBUFFER_LENGTH(src))
612 		bev->readcb(bev, arg);
613 	bufferevent_enable(bev, EV_READ);
614 	return;
615 
616  done:
617 	server_close(clt, "last http chunk read (done)");
618 	return;
619  fail:
620 	server_close(clt, strerror(errno));
621 }
622 
623 void
624 server_read_httprange(struct bufferevent *bev, void *arg)
625 {
626 	struct client		*clt = arg;
627 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
628 	size_t			 size;
629 	struct media_type	*media;
630 	struct range_data	*r = &clt->clt_ranges;
631 	struct range		*range;
632 
633 	getmonotime(&clt->clt_tv_last);
634 
635 	if (r->range_toread > 0) {
636 		size = EVBUFFER_LENGTH(src);
637 		if (!size)
638 			return;
639 
640 		/* Read chunk data */
641 		if ((off_t)size > r->range_toread) {
642 			size = r->range_toread;
643 			if (server_bufferevent_write_chunk(clt, src, size)
644 			    == -1)
645 				goto fail;
646 			r->range_toread = 0;
647 		} else {
648 			if (server_bufferevent_write_buffer(clt, src) == -1)
649 				goto fail;
650 			r->range_toread -= size;
651 		}
652 		if (r->range_toread < 1)
653 			r->range_toread = TOREAD_HTTP_RANGE;
654 		DPRINTF("%s: done, size %lu, to read %lld", __func__,
655 		    size, r->range_toread);
656 	}
657 
658 	switch (r->range_toread) {
659 	case TOREAD_HTTP_RANGE:
660 		if (r->range_index >= r->range_count) {
661 			if (r->range_count > 1) {
662 				/* Add end marker */
663 				if (server_bufferevent_printf(clt,
664 				    "\r\n--%llu--\r\n",
665 				    clt->clt_boundary) == -1)
666 					goto fail;
667 			}
668 			r->range_toread = TOREAD_HTTP_NONE;
669 			break;
670 		}
671 
672 		range = &r->range[r->range_index];
673 
674 		if (r->range_count > 1) {
675 			media = r->range_media;
676 			if (server_bufferevent_printf(clt,
677 			    "\r\n--%llu\r\n"
678 			    "Content-Type: %s/%s\r\n"
679 			    "Content-Range: bytes %lld-%lld/%zu\r\n\r\n",
680 			    clt->clt_boundary,
681 			    media->media_type, media->media_subtype,
682 			    range->start, range->end, r->range_total) == -1)
683 				goto fail;
684 		}
685 		r->range_toread = range->end - range->start + 1;
686 
687 		if (lseek(clt->clt_fd, range->start, SEEK_SET) == -1)
688 			goto fail;
689 
690 		/* Throw away bytes that are already in the input buffer */
691 		evbuffer_drain(src, EVBUFFER_LENGTH(src));
692 
693 		/* Increment for the next part */
694 		r->range_index++;
695 		break;
696 	case TOREAD_HTTP_NONE:
697 		goto done;
698 	case 0:
699 		break;
700 	}
701 
702 	if (clt->clt_done)
703 		goto done;
704 
705 	if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(clt->clt_bev)) > (size_t)
706 	    SERVER_MAX_PREFETCH * clt->clt_sndbufsiz) {
707 		bufferevent_disable(clt->clt_srvbev, EV_READ);
708 		clt->clt_srvbev_throttled = 1;
709 	}
710 
711 	return;
712  done:
713 	(*bev->errorcb)(bev, EVBUFFER_READ, bev->cbarg);
714 	return;
715  fail:
716 	server_close(clt, strerror(errno));
717 }
718 
719 void
720 server_reset_http(struct client *clt)
721 {
722 	struct server		*srv = clt->clt_srv;
723 
724 	server_log(clt, NULL);
725 
726 	server_httpdesc_free(clt->clt_descreq);
727 	server_httpdesc_free(clt->clt_descresp);
728 	clt->clt_headerlen = 0;
729 	clt->clt_headersdone = 0;
730 	clt->clt_done = 0;
731 	clt->clt_line = 0;
732 	clt->clt_chunk = 0;
733 	free(clt->clt_remote_user);
734 	clt->clt_remote_user = NULL;
735 	clt->clt_bev->readcb = server_read_http;
736 	clt->clt_srv_conf = &srv->srv_conf;
737 	str_match_free(&clt->clt_srv_match);
738 }
739 
740 ssize_t
741 server_http_time(time_t t, char *tmbuf, size_t len)
742 {
743 	struct tm		 tm;
744 
745 	/* New HTTP/1.1 RFC 7231 prefers IMF-fixdate from RFC 5322 */
746 	if (t == -1 || gmtime_r(&t, &tm) == NULL)
747 		return (-1);
748 	else
749 		return (strftime(tmbuf, len, "%a, %d %h %Y %T %Z", &tm));
750 }
751 
752 const char *
753 server_http_host(struct sockaddr_storage *ss, char *buf, size_t len)
754 {
755 	char		hbuf[HOST_NAME_MAX+1];
756 	in_port_t	port;
757 
758 	if (print_host(ss, buf, len) == NULL)
759 		return (NULL);
760 
761 	port = ntohs(server_socket_getport(ss));
762 	if (port == HTTP_PORT)
763 		return (buf);
764 
765 	switch (ss->ss_family) {
766 	case AF_INET:
767 		if ((size_t)snprintf(hbuf, sizeof(hbuf),
768 		    "%s:%u", buf, port) >= sizeof(hbuf))
769 			return (NULL);
770 		break;
771 	case AF_INET6:
772 		if ((size_t)snprintf(hbuf, sizeof(hbuf),
773 		    "[%s]:%u", buf, port) >= sizeof(hbuf))
774 			return (NULL);
775 		break;
776 	}
777 
778 	if (strlcpy(buf, hbuf, len) >= len)
779 		return (NULL);
780 
781 	return (buf);
782 }
783 
784 char *
785 server_http_parsehost(char *host, char *buf, size_t len, int *portval)
786 {
787 	char		*start, *end, *port;
788 	const char	*errstr = NULL;
789 
790 	if (strlcpy(buf, host, len) >= len) {
791 		log_debug("%s: host name too long", __func__);
792 		return (NULL);
793 	}
794 
795 	start = buf;
796 	end = port = NULL;
797 
798 	if (*start == '[' && (end = strchr(start, ']')) != NULL) {
799 		/* Address enclosed in [] with port, eg. [2001:db8::1]:80 */
800 		start++;
801 		*end++ = '\0';
802 		if ((port = strchr(end, ':')) == NULL || *port == '\0')
803 			port = NULL;
804 		else
805 			port++;
806 		memmove(buf, start, strlen(start) + 1);
807 	} else if ((end = strchr(start, ':')) != NULL) {
808 		/* Name or address with port, eg. www.example.com:80 */
809 		*end++ = '\0';
810 		port = end;
811 	} else {
812 		/* Name or address with default port, eg. www.example.com */
813 		port = NULL;
814 	}
815 
816 	if (port != NULL) {
817 		/* Save the requested port */
818 		*portval = strtonum(port, 0, 0xffff, &errstr);
819 		if (errstr != NULL) {
820 			log_debug("%s: invalid port: %s", __func__,
821 			    strerror(errno));
822 			return (NULL);
823 		}
824 		*portval = htons(*portval);
825 	} else {
826 		/* Port not given, indicate the default port */
827 		*portval = -1;
828 	}
829 
830 	return (start);
831 }
832 
833 void
834 server_abort_http(struct client *clt, unsigned int code, const char *msg)
835 {
836 	struct server_config	*srv_conf = clt->clt_srv_conf;
837 	struct bufferevent	*bev = clt->clt_bev;
838 	struct http_descriptor	*desc = clt->clt_descreq;
839 	const char		*httperr = NULL, *style;
840 	char			*httpmsg, *body = NULL, *extraheader = NULL;
841 	char			 tmbuf[32], hbuf[128], *hstsheader = NULL;
842 	char			*clenheader = NULL;
843 	char			 buf[IBUF_READ_SIZE];
844 	char			*escapedmsg = NULL;
845 	int			 bodylen;
846 
847 	if (code == 0) {
848 		server_close(clt, "dropped");
849 		return;
850 	}
851 
852 	if ((httperr = server_httperror_byid(code)) == NULL)
853 		httperr = "Unknown Error";
854 
855 	if (bev == NULL)
856 		goto done;
857 
858 	if (server_log_http(clt, code, 0) == -1)
859 		goto done;
860 
861 	/* Some system information */
862 	if (print_host(&srv_conf->ss, hbuf, sizeof(hbuf)) == NULL)
863 		goto done;
864 
865 	if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0)
866 		goto done;
867 
868 	/* Do not send details of the Internal Server Error */
869 	switch (code) {
870 	case 301:
871 	case 302:
872 	case 303:
873 	case 307:
874 	case 308:
875 		if (msg == NULL)
876 			break;
877 		memset(buf, 0, sizeof(buf));
878 		if (server_expand_http(clt, msg, buf, sizeof(buf)) == NULL)
879 			goto done;
880 		if (asprintf(&extraheader, "Location: %s\r\n", buf) == -1) {
881 			code = 500;
882 			extraheader = NULL;
883 		}
884 		msg = buf;
885 		break;
886 	case 401:
887 		if (msg == NULL)
888 			break;
889 		if (stravis(&escapedmsg, msg, VIS_DQ) == -1) {
890 			code = 500;
891 			extraheader = NULL;
892 		} else if (asprintf(&extraheader,
893 		    "WWW-Authenticate: Basic realm=\"%s\"\r\n", escapedmsg)
894 		    == -1) {
895 			code = 500;
896 			extraheader = NULL;
897 		}
898 		break;
899 	case 416:
900 		if (msg == NULL)
901 			break;
902 		if (asprintf(&extraheader,
903 		    "Content-Range: %s\r\n", msg) == -1) {
904 			code = 500;
905 			extraheader = NULL;
906 		}
907 		break;
908 	default:
909 		/*
910 		 * Do not send details of the error.  Traditionally,
911 		 * web servers responsed with the request path on 40x
912 		 * errors which could be abused to inject JavaScript etc.
913 		 * Instead of sanitizing the path here, we just don't
914 		 * reprint it.
915 		 */
916 		break;
917 	}
918 
919 	free(escapedmsg);
920 
921 	/* A CSS stylesheet allows minimal customization by the user */
922 	style = "body { background-color: white; color: black; font-family: "
923 	    "'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; }\n"
924 	    "hr { border: 0; border-bottom: 1px dashed; }\n";
925 
926 	/* Generate simple HTML error document */
927 	if ((bodylen = asprintf(&body,
928 	    "<!DOCTYPE html>\n"
929 	    "<html>\n"
930 	    "<head>\n"
931 	    "<meta http-equiv=\"Content-Type\" content=\"text/html; "
932 	    "charset=utf-8\"/>\n"
933 	    "<title>%03d %s</title>\n"
934 	    "<style type=\"text/css\"><!--\n%s\n--></style>\n"
935 	    "</head>\n"
936 	    "<body>\n"
937 	    "<h1>%03d %s</h1>\n"
938 	    "<hr>\n<address>%s</address>\n"
939 	    "</body>\n"
940 	    "</html>\n",
941 	    code, httperr, style, code, httperr, HTTPD_SERVERNAME)) == -1) {
942 		body = NULL;
943 		goto done;
944 	}
945 
946 	if (srv_conf->flags & SRVFLAG_SERVER_HSTS &&
947 	    srv_conf->flags & SRVFLAG_TLS) {
948 		if (asprintf(&hstsheader, "Strict-Transport-Security: "
949 		    "max-age=%d%s%s\r\n", srv_conf->hsts_max_age,
950 		    srv_conf->hsts_flags & HSTSFLAG_SUBDOMAINS ?
951 		    "; includeSubDomains" : "",
952 		    srv_conf->hsts_flags & HSTSFLAG_PRELOAD ?
953 		    "; preload" : "") == -1) {
954 			hstsheader = NULL;
955 			goto done;
956 		}
957 	}
958 
959 	if ((code >= 100 && code < 200) || code == 204)
960 		clenheader = NULL;
961 	else {
962 		if (asprintf(&clenheader,
963 		    "Content-Length: %d\r\n", bodylen) == -1) {
964 			clenheader = NULL;
965 			goto done;
966 		}
967 	}
968 
969 	/* Add basic HTTP headers */
970 	if (asprintf(&httpmsg,
971 	    "HTTP/1.0 %03d %s\r\n"
972 	    "Date: %s\r\n"
973 	    "Server: %s\r\n"
974 	    "Connection: close\r\n"
975 	    "Content-Type: text/html\r\n"
976 	    "%s"
977 	    "%s"
978 	    "%s"
979 	    "\r\n"
980 	    "%s",
981 	    code, httperr, tmbuf, HTTPD_SERVERNAME,
982 	    clenheader == NULL ? "" : clenheader,
983 	    extraheader == NULL ? "" : extraheader,
984 	    hstsheader == NULL ? "" : hstsheader,
985 	    desc->http_method == HTTP_METHOD_HEAD || clenheader == NULL ?
986 	    "" : body) == -1)
987 		goto done;
988 
989 	/* Dump the message without checking for success */
990 	server_dump(clt, httpmsg, strlen(httpmsg));
991 	free(httpmsg);
992 
993  done:
994 	free(body);
995 	free(extraheader);
996 	free(hstsheader);
997 	free(clenheader);
998 	if (msg == NULL)
999 		msg = "\"\"";
1000 	if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1) {
1001 		server_close(clt, msg);
1002 	} else {
1003 		server_close(clt, httpmsg);
1004 		free(httpmsg);
1005 	}
1006 }
1007 
1008 void
1009 server_close_http(struct client *clt)
1010 {
1011 	struct http_descriptor *desc;
1012 
1013 	desc = clt->clt_descreq;
1014 	server_httpdesc_free(desc);
1015 	free(desc);
1016 	clt->clt_descreq = NULL;
1017 
1018 	desc = clt->clt_descresp;
1019 	server_httpdesc_free(desc);
1020 	free(desc);
1021 	clt->clt_descresp = NULL;
1022 	free(clt->clt_remote_user);
1023 	clt->clt_remote_user = NULL;
1024 
1025 	str_match_free(&clt->clt_srv_match);
1026 }
1027 
1028 char *
1029 server_expand_http(struct client *clt, const char *val, char *buf,
1030     size_t len)
1031 {
1032 	struct http_descriptor	*desc = clt->clt_descreq;
1033 	struct server_config	*srv_conf = clt->clt_srv_conf;
1034 	char			 ibuf[128], *str, *path, *query;
1035 	const char		*errstr = NULL, *p;
1036 	size_t			 size;
1037 	int			 n, ret;
1038 
1039 	if (strlcpy(buf, val, len) >= len)
1040 		return (NULL);
1041 
1042 	/* Find previously matched substrings by index */
1043 	for (p = val; clt->clt_srv_match.sm_nmatch &&
1044 	    (p = strstr(p, "%")) != NULL; p++) {
1045 		if (!isdigit((unsigned char)*(p + 1)))
1046 			continue;
1047 
1048 		/* Copy number, leading '%' char and add trailing \0 */
1049 		size = strspn(p + 1, "0123456789") + 2;
1050 		if (size  >= sizeof(ibuf))
1051 			return (NULL);
1052 		(void)strlcpy(ibuf, p, size);
1053 		n = strtonum(ibuf + 1, 0,
1054 		    clt->clt_srv_match.sm_nmatch - 1, &errstr);
1055 		if (errstr != NULL)
1056 			return (NULL);
1057 
1058 		/* Expand variable with matched value */
1059 		if ((str = url_encode(clt->clt_srv_match.sm_match[n])) == NULL)
1060 			return (NULL);
1061 		ret = expand_string(buf, len, ibuf, str);
1062 		free(str);
1063 		if (ret != 0)
1064 			return (NULL);
1065 	}
1066 	if (strstr(val, "$DOCUMENT_URI") != NULL) {
1067 		if ((path = url_encode(desc->http_path)) == NULL)
1068 			return (NULL);
1069 		ret = expand_string(buf, len, "$DOCUMENT_URI", path);
1070 		free(path);
1071 		if (ret != 0)
1072 			return (NULL);
1073 	}
1074 	if (strstr(val, "$QUERY_STRING_ENC") != NULL) {
1075 		if (desc->http_query == NULL) {
1076 			ret = expand_string(buf, len, "$QUERY_STRING_ENC", "");
1077 		} else {
1078 			if ((query = url_encode(desc->http_query)) == NULL)
1079 				return (NULL);
1080 			ret = expand_string(buf, len, "$QUERY_STRING_ENC", query);
1081 			free(query);
1082 		}
1083 		if (ret != 0)
1084 			return (NULL);
1085 	}
1086 	if (strstr(val, "$QUERY_STRING") != NULL) {
1087 		if (desc->http_query == NULL) {
1088 			ret = expand_string(buf, len, "$QUERY_STRING", "");
1089 		} else {
1090 			ret = expand_string(buf, len, "$QUERY_STRING",
1091 			    desc->http_query);
1092 		}
1093 		if (ret != 0)
1094 			return (NULL);
1095 	}
1096 	if (strstr(val, "$HTTP_HOST") != NULL) {
1097 		if (desc->http_host == NULL)
1098 			return (NULL);
1099 		if ((str = url_encode(desc->http_host)) == NULL)
1100 			return (NULL);
1101 		expand_string(buf, len, "$HTTP_HOST", str);
1102 		free(str);
1103 	}
1104 	if (strstr(val, "$REMOTE_") != NULL) {
1105 		if (strstr(val, "$REMOTE_ADDR") != NULL) {
1106 			if (print_host(&clt->clt_ss,
1107 			    ibuf, sizeof(ibuf)) == NULL)
1108 				return (NULL);
1109 			if (expand_string(buf, len,
1110 			    "$REMOTE_ADDR", ibuf) != 0)
1111 				return (NULL);
1112 		}
1113 		if (strstr(val, "$REMOTE_PORT") != NULL) {
1114 			snprintf(ibuf, sizeof(ibuf),
1115 			    "%u", ntohs(clt->clt_port));
1116 			if (expand_string(buf, len,
1117 			    "$REMOTE_PORT", ibuf) != 0)
1118 				return (NULL);
1119 		}
1120 		if (strstr(val, "$REMOTE_USER") != NULL) {
1121 			if ((srv_conf->flags & SRVFLAG_AUTH) &&
1122 			    clt->clt_remote_user != NULL) {
1123 				if ((str = url_encode(clt->clt_remote_user))
1124 				    == NULL)
1125 					return (NULL);
1126 			} else
1127 				str = strdup("");
1128 			ret = expand_string(buf, len, "$REMOTE_USER", str);
1129 			free(str);
1130 			if (ret != 0)
1131 				return (NULL);
1132 		}
1133 	}
1134 	if (strstr(val, "$REQUEST_URI") != NULL) {
1135 		if ((path = url_encode(desc->http_path)) == NULL)
1136 			return (NULL);
1137 		if (desc->http_query == NULL) {
1138 			str = path;
1139 		} else {
1140 			ret = asprintf(&str, "%s?%s", path, desc->http_query);
1141 			free(path);
1142 			if (ret == -1)
1143 				return (NULL);
1144 		}
1145 
1146 		ret = expand_string(buf, len, "$REQUEST_URI", str);
1147 		free(str);
1148 		if (ret != 0)
1149 			return (NULL);
1150 	}
1151 	if (strstr(val, "$REQUEST_SCHEME") != NULL) {
1152 		if (srv_conf->flags & SRVFLAG_TLS) {
1153 			ret = expand_string(buf, len, "$REQUEST_SCHEME", "https");
1154 		} else {
1155 			ret = expand_string(buf, len, "$REQUEST_SCHEME", "http");
1156 		}
1157 		if (ret != 0)
1158 			return (NULL);
1159 	}
1160 	if (strstr(val, "$SERVER_") != NULL) {
1161 		if (strstr(val, "$SERVER_ADDR") != NULL) {
1162 			if (print_host(&srv_conf->ss,
1163 			    ibuf, sizeof(ibuf)) == NULL)
1164 				return (NULL);
1165 			if (expand_string(buf, len,
1166 			    "$SERVER_ADDR", ibuf) != 0)
1167 				return (NULL);
1168 		}
1169 		if (strstr(val, "$SERVER_PORT") != NULL) {
1170 			snprintf(ibuf, sizeof(ibuf), "%u",
1171 			    ntohs(srv_conf->port));
1172 			if (expand_string(buf, len,
1173 			    "$SERVER_PORT", ibuf) != 0)
1174 				return (NULL);
1175 		}
1176 		if (strstr(val, "$SERVER_NAME") != NULL) {
1177 			if ((str = url_encode(srv_conf->name))
1178 			     == NULL)
1179 				return (NULL);
1180 			ret = expand_string(buf, len, "$SERVER_NAME", str);
1181 			free(str);
1182 			if (ret != 0)
1183 				return (NULL);
1184 		}
1185 	}
1186 
1187 	return (buf);
1188 }
1189 
1190 int
1191 server_response(struct httpd *httpd, struct client *clt)
1192 {
1193 	char			 path[PATH_MAX];
1194 	char			 hostname[HOST_NAME_MAX+1];
1195 	struct http_descriptor	*desc = clt->clt_descreq;
1196 	struct http_descriptor	*resp = clt->clt_descresp;
1197 	struct server		*srv = clt->clt_srv;
1198 	struct server_config	*srv_conf = &srv->srv_conf;
1199 	struct kv		*kv, key, *host;
1200 	struct str_find		 sm;
1201 	int			 portval = -1, ret;
1202 	char			*hostval, *query;
1203 	const char		*errstr = NULL;
1204 
1205 	/* Decode the URL */
1206 	if (desc->http_path == NULL ||
1207 	    url_decode(desc->http_path) == NULL)
1208 		goto fail;
1209 
1210 	/* Canonicalize the request path */
1211 	if (canonicalize_path(desc->http_path, path, sizeof(path)) == NULL)
1212 		goto fail;
1213 	free(desc->http_path);
1214 	if ((desc->http_path = strdup(path)) == NULL)
1215 		goto fail;
1216 
1217 	key.kv_key = "Host";
1218 	if ((host = kv_find(&desc->http_headers, &key)) != NULL &&
1219 	    host->kv_value == NULL)
1220 		host = NULL;
1221 
1222 	if (strcmp(desc->http_version, "HTTP/1.1") == 0) {
1223 		/* Host header is mandatory */
1224 		if (host == NULL)
1225 			goto fail;
1226 
1227 		/* Is the connection persistent? */
1228 		key.kv_key = "Connection";
1229 		if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
1230 		    strcasecmp("close", kv->kv_value) == 0)
1231 			clt->clt_persist = 0;
1232 		else
1233 			clt->clt_persist++;
1234 	} else {
1235 		/* Is the connection persistent? */
1236 		key.kv_key = "Connection";
1237 		if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
1238 		    strcasecmp("keep-alive", kv->kv_value) == 0)
1239 			clt->clt_persist++;
1240 		else
1241 			clt->clt_persist = 0;
1242 	}
1243 
1244 	/*
1245 	 * Do we have a Host header and matching configuration?
1246 	 * XXX the Host can also appear in the URL path.
1247 	 */
1248 	if (host != NULL) {
1249 		if ((hostval = server_http_parsehost(host->kv_value,
1250 		    hostname, sizeof(hostname), &portval)) == NULL)
1251 			goto fail;
1252 
1253 		TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
1254 #ifdef DEBUG
1255 			if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
1256 				DPRINTF("%s: virtual host \"%s:%u\""
1257 				    " host \"%s\" (\"%s\")",
1258 				    __func__, srv_conf->name,
1259 				    ntohs(srv_conf->port), host->kv_value,
1260 				    hostname);
1261 			}
1262 #endif
1263 			if (srv_conf->flags & SRVFLAG_LOCATION)
1264 				continue;
1265 			else if (srv_conf->flags & SRVFLAG_SERVER_MATCH) {
1266 				str_find(hostname, srv_conf->name,
1267 				    &sm, 1, &errstr);
1268 				ret = errstr == NULL ? 0 : -1;
1269 			} else {
1270 				ret = fnmatch(srv_conf->name,
1271 				    hostname, FNM_CASEFOLD);
1272 			}
1273 			if (ret == 0 &&
1274 			    (portval == -1 ||
1275 			    (portval != -1 && portval == srv_conf->port))) {
1276 				/* Replace host configuration */
1277 				clt->clt_srv_conf = srv_conf;
1278 				srv_conf = NULL;
1279 				break;
1280 			}
1281 		}
1282 	}
1283 
1284 	if (srv_conf != NULL) {
1285 		/* Use the actual server IP address */
1286 		if (server_http_host(&clt->clt_srv_ss, hostname,
1287 		    sizeof(hostname)) == NULL)
1288 			goto fail;
1289 	} else {
1290 		/* Host header was valid and found */
1291 		if (strlcpy(hostname, host->kv_value, sizeof(hostname)) >=
1292 		    sizeof(hostname))
1293 			goto fail;
1294 		srv_conf = clt->clt_srv_conf;
1295 	}
1296 
1297 	if (clt->clt_persist >= srv_conf->maxrequests)
1298 		clt->clt_persist = 0;
1299 
1300 	/* pipelining should end after the first "idempotent" method */
1301 	if (clt->clt_pipelining && clt->clt_toread > 0)
1302 		clt->clt_persist = 0;
1303 
1304 	if ((desc->http_host = strdup(hostname)) == NULL)
1305 		goto fail;
1306 
1307 	/* Now fill in the mandatory parts of the response descriptor */
1308 	resp->http_method = desc->http_method;
1309 	if ((resp->http_version = strdup(desc->http_version)) == NULL)
1310 		goto fail;
1311 
1312 	/* Now search for the location */
1313 	srv_conf = server_getlocation(clt, desc->http_path);
1314 
1315 	/* Optional rewrite */
1316 	if (srv_conf->flags & SRVFLAG_PATH_REWRITE) {
1317 		/* Expand macros */
1318 		if (server_expand_http(clt, srv_conf->path,
1319 		    path, sizeof(path)) == NULL)
1320 			goto fail;
1321 
1322 		/*
1323 		 * Reset and update the query.  The updated query must already
1324 		 * be URL encoded - either specified by the user or by using the
1325 		 * original $QUERY_STRING.
1326 		 */
1327 		free(desc->http_query_alias);
1328 		desc->http_query_alias = NULL;
1329 		if ((query = strchr(path, '?')) != NULL) {
1330 			*query++ = '\0';
1331 			if ((desc->http_query_alias = strdup(query)) == NULL)
1332 				goto fail;
1333 		}
1334 
1335 		/* Canonicalize the updated request path */
1336 		if (canonicalize_path(path,
1337 		    path, sizeof(path)) == NULL)
1338 			goto fail;
1339 
1340 		log_debug("%s: rewrote %s?%s -> %s?%s", __func__,
1341 		    desc->http_path, desc->http_query ? desc->http_query : "",
1342 		    path, query ? query : "");
1343 
1344 		free(desc->http_path_alias);
1345 		if ((desc->http_path_alias = strdup(path)) == NULL)
1346 			goto fail;
1347 
1348 		/* Now search for the updated location */
1349 		srv_conf = server_getlocation(clt, desc->http_path_alias);
1350 	}
1351 
1352 	if (clt->clt_toread > 0 && (size_t)clt->clt_toread >
1353 	    srv_conf->maxrequestbody) {
1354 		server_abort_http(clt, 413, NULL);
1355 		return (-1);
1356 	}
1357 
1358 	if (srv_conf->flags & SRVFLAG_BLOCK) {
1359 		server_abort_http(clt, srv_conf->return_code,
1360 		    srv_conf->return_uri);
1361 		return (-1);
1362 	} else if (srv_conf->flags & SRVFLAG_AUTH &&
1363 	    server_http_authenticate(srv_conf, clt) == -1) {
1364 		server_abort_http(clt, 401, srv_conf->auth_realm);
1365 		return (-1);
1366 	} else
1367 		return (server_file(httpd, clt));
1368  fail:
1369 	server_abort_http(clt, 400, "bad request");
1370 	return (-1);
1371 }
1372 
1373 const char *
1374 server_root_strip(const char *path, int n)
1375 {
1376 	const char *p;
1377 
1378 	/* Strip strip leading directories. Leading '/' is ignored. */
1379 	for (; n > 0 && *path != '\0'; n--)
1380 		if ((p = strchr(++path, '/')) == NULL)
1381 			path = strchr(path, '\0');
1382 		else
1383 			path = p;
1384 
1385 	return (path);
1386 }
1387 
1388 struct server_config *
1389 server_getlocation(struct client *clt, const char *path)
1390 {
1391 	struct server		*srv = clt->clt_srv;
1392 	struct server_config	*srv_conf = clt->clt_srv_conf, *location;
1393 	const char		*errstr = NULL;
1394 	int			 ret;
1395 
1396 	/* Now search for the location */
1397 	TAILQ_FOREACH(location, &srv->srv_hosts, entry) {
1398 #ifdef DEBUG
1399 		if (location->flags & SRVFLAG_LOCATION) {
1400 			DPRINTF("%s: location \"%s\" path \"%s\"",
1401 			    __func__, location->location, path);
1402 		}
1403 #endif
1404 		if ((location->flags & SRVFLAG_LOCATION) &&
1405 		    location->parent_id == srv_conf->parent_id) {
1406 			errstr = NULL;
1407 			if (location->flags & SRVFLAG_LOCATION_MATCH) {
1408 				ret = str_match(path, location->location,
1409 				    &clt->clt_srv_match, &errstr);
1410 			} else {
1411 				ret = fnmatch(location->location,
1412 				    path, FNM_CASEFOLD);
1413 			}
1414 			if (ret == 0 && errstr == NULL) {
1415 				/* Replace host configuration */
1416 				clt->clt_srv_conf = srv_conf = location;
1417 				break;
1418 			}
1419 		}
1420 	}
1421 
1422 	return (srv_conf);
1423 }
1424 
1425 int
1426 server_response_http(struct client *clt, unsigned int code,
1427     struct media_type *media, off_t size, time_t mtime)
1428 {
1429 	struct server_config	*srv_conf = clt->clt_srv_conf;
1430 	struct http_descriptor	*desc = clt->clt_descreq;
1431 	struct http_descriptor	*resp = clt->clt_descresp;
1432 	const char		*error;
1433 	struct kv		*ct, *cl;
1434 	char			 tmbuf[32];
1435 
1436 	if (desc == NULL || media == NULL ||
1437 	    (error = server_httperror_byid(code)) == NULL)
1438 		return (-1);
1439 
1440 	if (server_log_http(clt, code, size >= 0 ? size : 0) == -1)
1441 		return (-1);
1442 
1443 	/* Add error codes */
1444 	if (kv_setkey(&resp->http_pathquery, "%u", code) == -1 ||
1445 	    kv_set(&resp->http_pathquery, "%s", error) == -1)
1446 		return (-1);
1447 
1448 	/* Add headers */
1449 	if (kv_add(&resp->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
1450 		return (-1);
1451 
1452 	/* Is it a persistent connection? */
1453 	if (clt->clt_persist) {
1454 		if (kv_add(&resp->http_headers,
1455 		    "Connection", "keep-alive") == NULL)
1456 			return (-1);
1457 	} else if (kv_add(&resp->http_headers, "Connection", "close") == NULL)
1458 		return (-1);
1459 
1460 	/* Set media type */
1461 	if ((ct = kv_add(&resp->http_headers, "Content-Type", NULL)) == NULL ||
1462 	    kv_set(ct, "%s/%s", media->media_type, media->media_subtype) == -1)
1463 		return (-1);
1464 
1465 	/* Set content length, if specified */
1466 	if (size >= 0 && ((cl =
1467 	    kv_add(&resp->http_headers, "Content-Length", NULL)) == NULL ||
1468 	    kv_set(cl, "%lld", (long long)size) == -1))
1469 		return (-1);
1470 
1471 	/* Set last modification time */
1472 	if (server_http_time(mtime, tmbuf, sizeof(tmbuf)) <= 0 ||
1473 	    kv_add(&resp->http_headers, "Last-Modified", tmbuf) == NULL)
1474 		return (-1);
1475 
1476 	/* HSTS header */
1477 	if (srv_conf->flags & SRVFLAG_SERVER_HSTS &&
1478 	    srv_conf->flags & SRVFLAG_TLS) {
1479 		if ((cl =
1480 		    kv_add(&resp->http_headers, "Strict-Transport-Security",
1481 		    NULL)) == NULL ||
1482 		    kv_set(cl, "max-age=%d%s%s", srv_conf->hsts_max_age,
1483 		    srv_conf->hsts_flags & HSTSFLAG_SUBDOMAINS ?
1484 		    "; includeSubDomains" : "",
1485 		    srv_conf->hsts_flags & HSTSFLAG_PRELOAD ?
1486 		    "; preload" : "") == -1)
1487 			return (-1);
1488 	}
1489 
1490 	/* Date header is mandatory and should be added as late as possible */
1491 	if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 ||
1492 	    kv_add(&resp->http_headers, "Date", tmbuf) == NULL)
1493 		return (-1);
1494 
1495 	/* Write completed header */
1496 	if (server_writeresponse_http(clt) == -1 ||
1497 	    server_bufferevent_print(clt, "\r\n") == -1 ||
1498 	    server_headers(clt, resp, server_writeheader_http, NULL) == -1 ||
1499 	    server_bufferevent_print(clt, "\r\n") == -1)
1500 		return (-1);
1501 
1502 	if (size <= 0 || resp->http_method == HTTP_METHOD_HEAD) {
1503 		bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
1504 		if (clt->clt_persist)
1505 			clt->clt_toread = TOREAD_HTTP_HEADER;
1506 		else
1507 			clt->clt_toread = TOREAD_HTTP_NONE;
1508 		clt->clt_done = 0;
1509 		return (0);
1510 	}
1511 
1512 	return (1);
1513 }
1514 
1515 int
1516 server_writeresponse_http(struct client *clt)
1517 {
1518 	struct http_descriptor	*desc = clt->clt_descresp;
1519 
1520 	DPRINTF("version: %s rescode: %s resmsg: %s", desc->http_version,
1521 	    desc->http_rescode, desc->http_resmesg);
1522 
1523 	if (server_bufferevent_print(clt, desc->http_version) == -1 ||
1524 	    server_bufferevent_print(clt, " ") == -1 ||
1525 	    server_bufferevent_print(clt, desc->http_rescode) == -1 ||
1526 	    server_bufferevent_print(clt, " ") == -1 ||
1527 	    server_bufferevent_print(clt, desc->http_resmesg) == -1)
1528 		return (-1);
1529 
1530 	return (0);
1531 }
1532 
1533 int
1534 server_writeheader_http(struct client *clt, struct kv *hdr, void *arg)
1535 {
1536 	char			*ptr;
1537 	const char		*key;
1538 
1539 	if (hdr->kv_flags & KV_FLAG_INVALID)
1540 		return (0);
1541 
1542 	/* The key might have been updated in the parent */
1543 	if (hdr->kv_parent != NULL && hdr->kv_parent->kv_key != NULL)
1544 		key = hdr->kv_parent->kv_key;
1545 	else
1546 		key = hdr->kv_key;
1547 
1548 	ptr = hdr->kv_value;
1549 	if (server_bufferevent_print(clt, key) == -1 ||
1550 	    (ptr != NULL &&
1551 	    (server_bufferevent_print(clt, ": ") == -1 ||
1552 	    server_bufferevent_print(clt, ptr) == -1 ||
1553 	    server_bufferevent_print(clt, "\r\n") == -1)))
1554 		return (-1);
1555 	DPRINTF("%s: %s: %s", __func__, key,
1556 	    hdr->kv_value == NULL ? "" : hdr->kv_value);
1557 
1558 	return (0);
1559 }
1560 
1561 int
1562 server_headers(struct client *clt, void *descp,
1563     int (*hdr_cb)(struct client *, struct kv *, void *), void *arg)
1564 {
1565 	struct kv		*hdr, *kv;
1566 	struct http_descriptor	*desc = descp;
1567 
1568 	RB_FOREACH(hdr, kvtree, &desc->http_headers) {
1569 		if ((hdr_cb)(clt, hdr, arg) == -1)
1570 			return (-1);
1571 		TAILQ_FOREACH(kv, &hdr->kv_children, kv_entry) {
1572 			if ((hdr_cb)(clt, kv, arg) == -1)
1573 				return (-1);
1574 		}
1575 	}
1576 
1577 	return (0);
1578 }
1579 
1580 enum httpmethod
1581 server_httpmethod_byname(const char *name)
1582 {
1583 	enum httpmethod		 id = HTTP_METHOD_NONE;
1584 	struct http_method	 method, *res = NULL;
1585 
1586 	/* Set up key */
1587 	method.method_name = name;
1588 
1589 	if ((res = bsearch(&method, http_methods,
1590 	    sizeof(http_methods) / sizeof(http_methods[0]) - 1,
1591 	    sizeof(http_methods[0]), server_httpmethod_cmp)) != NULL)
1592 		id = res->method_id;
1593 
1594 	return (id);
1595 }
1596 
1597 const char *
1598 server_httpmethod_byid(unsigned int id)
1599 {
1600 	const char	*name = "<UNKNOWN>";
1601 	int		 i;
1602 
1603 	for (i = 0; http_methods[i].method_name != NULL; i++) {
1604 		if (http_methods[i].method_id == id) {
1605 			name = http_methods[i].method_name;
1606 			break;
1607 		}
1608 	}
1609 
1610 	return (name);
1611 }
1612 
1613 static int
1614 server_httpmethod_cmp(const void *a, const void *b)
1615 {
1616 	const struct http_method *ma = a;
1617 	const struct http_method *mb = b;
1618 
1619 	/*
1620 	 * RFC 2616 section 5.1.1 says that the method is case
1621 	 * sensitive so we don't do a strcasecmp here.
1622 	 */
1623 	return (strcmp(ma->method_name, mb->method_name));
1624 }
1625 
1626 const char *
1627 server_httperror_byid(unsigned int id)
1628 {
1629 	struct http_error	 error, *res;
1630 
1631 	/* Set up key */
1632 	error.error_code = (int)id;
1633 
1634 	if ((res = bsearch(&error, http_errors,
1635 	    sizeof(http_errors) / sizeof(http_errors[0]) - 1,
1636 	    sizeof(http_errors[0]), server_httperror_cmp)) != NULL)
1637 		return (res->error_name);
1638 
1639 	return (NULL);
1640 }
1641 
1642 static int
1643 server_httperror_cmp(const void *a, const void *b)
1644 {
1645 	const struct http_error *ea = a;
1646 	const struct http_error *eb = b;
1647 	return (ea->error_code - eb->error_code);
1648 }
1649 
1650 int
1651 server_log_http(struct client *clt, unsigned int code, size_t len)
1652 {
1653 	static char		 tstamp[64];
1654 	static char		 ip[INET6_ADDRSTRLEN];
1655 	time_t			 t;
1656 	struct kv		 key, *agent, *referrer, *xff, *xfp;
1657 	struct tm		*tm;
1658 	struct server_config	*srv_conf;
1659 	struct http_descriptor	*desc;
1660 	int			 ret = -1;
1661 	char			*user = NULL;
1662 	char			*path = NULL;
1663 	char			*version = NULL;
1664 	char			*referrer_v = NULL;
1665 	char			*agent_v = NULL;
1666 	char			*xff_v = NULL;
1667 	char			*xfp_v = NULL;
1668 
1669 	if ((srv_conf = clt->clt_srv_conf) == NULL)
1670 		return (-1);
1671 	if ((srv_conf->flags & SRVFLAG_LOG) == 0)
1672 		return (0);
1673 	if ((desc = clt->clt_descreq) == NULL)
1674 		return (-1);
1675 
1676 	if ((t = time(NULL)) == -1)
1677 		return (-1);
1678 	if ((tm = localtime(&t)) == NULL)
1679 		return (-1);
1680 	if (strftime(tstamp, sizeof(tstamp), "%d/%b/%Y:%H:%M:%S %z", tm) == 0)
1681 		return (-1);
1682 
1683 	if (print_host(&clt->clt_ss, ip, sizeof(ip)) == NULL)
1684 		return (-1);
1685 
1686 	/*
1687 	 * For details on common log format, see:
1688 	 * https://httpd.apache.org/docs/current/mod/mod_log_config.html
1689 	 *
1690 	 * httpd's format is similar to these Apache LogFormats:
1691 	 * "%v %h %l %u %t \"%r\" %>s %B"
1692 	 * "%v %h %l %u %t \"%r\" %>s %B \"%{Referer}i\" \"%{User-agent}i\""
1693 	 */
1694 	switch (srv_conf->logformat) {
1695 	case LOG_FORMAT_COMMON:
1696 		/* Use vis to encode input values from the header */
1697 		if (clt->clt_remote_user &&
1698 		    stravis(&user, clt->clt_remote_user, HTTPD_LOGVIS) == -1)
1699 			goto done;
1700 		if (desc->http_version &&
1701 		    stravis(&version, desc->http_version, HTTPD_LOGVIS) == -1)
1702 			goto done;
1703 
1704 		/* The following should be URL-encoded */
1705 		if (desc->http_path &&
1706 		    (path = url_encode(desc->http_path)) == NULL)
1707 			goto done;
1708 
1709 		ret = evbuffer_add_printf(clt->clt_log,
1710 		    "%s %s - %s [%s] \"%s %s%s%s%s%s\" %03d %zu\n",
1711 		    srv_conf->name, ip, clt->clt_remote_user == NULL ? "-" :
1712 		    user, tstamp,
1713 		    server_httpmethod_byid(desc->http_method),
1714 		    desc->http_path == NULL ? "" : path,
1715 		    desc->http_query == NULL ? "" : "?",
1716 		    desc->http_query == NULL ? "" : desc->http_query,
1717 		    desc->http_version == NULL ? "" : " ",
1718 		    desc->http_version == NULL ? "" : version,
1719 		    code, len);
1720 
1721 		break;
1722 
1723 	case LOG_FORMAT_COMBINED:
1724 	case LOG_FORMAT_FORWARDED:
1725 		key.kv_key = "Referer"; /* sic */
1726 		if ((referrer = kv_find(&desc->http_headers, &key)) != NULL &&
1727 		    referrer->kv_value == NULL)
1728 			referrer = NULL;
1729 
1730 		key.kv_key = "User-Agent";
1731 		if ((agent = kv_find(&desc->http_headers, &key)) != NULL &&
1732 		    agent->kv_value == NULL)
1733 			agent = NULL;
1734 
1735 		/* Use vis to encode input values from the header */
1736 		if (clt->clt_remote_user &&
1737 		    stravis(&user, clt->clt_remote_user, HTTPD_LOGVIS) == -1)
1738 			goto done;
1739 		if (clt->clt_remote_user == NULL &&
1740 		    clt->clt_tls_ctx != NULL &&
1741 		    (srv_conf->tls_flags & TLSFLAG_CA) &&
1742 		    tls_peer_cert_subject(clt->clt_tls_ctx) != NULL &&
1743 		    stravis(&user, tls_peer_cert_subject(clt->clt_tls_ctx),
1744 		    HTTPD_LOGVIS) == -1)
1745 			goto done;
1746 		if (desc->http_version &&
1747 		    stravis(&version, desc->http_version, HTTPD_LOGVIS) == -1)
1748 			goto done;
1749 		if (agent &&
1750 		    stravis(&agent_v, agent->kv_value, HTTPD_LOGVIS) == -1)
1751 			goto done;
1752 
1753 		/* The following should be URL-encoded */
1754 		if (desc->http_path &&
1755 		    (path = url_encode(desc->http_path)) == NULL)
1756 			goto done;
1757 		if (referrer &&
1758 		    (referrer_v = url_encode(referrer->kv_value)) == NULL)
1759 			goto done;
1760 
1761 		if ((ret = evbuffer_add_printf(clt->clt_log,
1762 		    "%s %s - %s [%s] \"%s %s%s%s%s%s\""
1763 		    " %03d %zu \"%s\" \"%s\"",
1764 		    srv_conf->name, ip, user == NULL ? "-" :
1765 		    user, tstamp,
1766 		    server_httpmethod_byid(desc->http_method),
1767 		    desc->http_path == NULL ? "" : path,
1768 		    desc->http_query == NULL ? "" : "?",
1769 		    desc->http_query == NULL ? "" : desc->http_query,
1770 		    desc->http_version == NULL ? "" : " ",
1771 		    desc->http_version == NULL ? "" : version,
1772 		    code, len,
1773 		    referrer == NULL ? "" : referrer_v,
1774 		    agent == NULL ? "" : agent_v)) == -1)
1775 			break;
1776 
1777 		if (srv_conf->logformat == LOG_FORMAT_COMBINED)
1778 			goto finish;
1779 
1780 		xff = xfp = NULL;
1781 
1782 		key.kv_key = "X-Forwarded-For";
1783 		if ((xff = kv_find(&desc->http_headers, &key)) != NULL
1784 		    && xff->kv_value == NULL)
1785 			xff = NULL;
1786 
1787 		if (xff &&
1788 		    stravis(&xff_v, xff->kv_value, HTTPD_LOGVIS) == -1)
1789 			goto finish;
1790 
1791 		key.kv_key = "X-Forwarded-Port";
1792 		if ((xfp = kv_find(&desc->http_headers, &key)) != NULL &&
1793 		    (xfp->kv_value == NULL))
1794 			xfp = NULL;
1795 
1796 		if (xfp &&
1797 		    stravis(&xfp_v, xfp->kv_value, HTTPD_LOGVIS) == -1)
1798 			goto finish;
1799 
1800 		if ((ret = evbuffer_add_printf(clt->clt_log, " %s %s",
1801 		    xff == NULL ? "-" : xff_v,
1802 		    xfp == NULL ? "-" : xfp_v)) == -1)
1803 			break;
1804 finish:
1805 		ret = evbuffer_add_printf(clt->clt_log, "\n");
1806 
1807 		break;
1808 
1809 	case LOG_FORMAT_CONNECTION:
1810 		/* URL-encode the path */
1811 		if (desc->http_path &&
1812 		    (path = url_encode(desc->http_path)) == NULL)
1813 			goto done;
1814 
1815 		ret = evbuffer_add_printf(clt->clt_log, " [%s]",
1816 		    desc->http_path == NULL ? "" : path);
1817 
1818 		break;
1819 	}
1820 
1821 done:
1822 	free(user);
1823 	free(path);
1824 	free(version);
1825 	free(referrer_v);
1826 	free(agent_v);
1827 	free(xff_v);
1828 	free(xfp_v);
1829 
1830 	return (ret);
1831 }
1832