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