GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/httpd/httpd.c Lines: 142 631 22.5 %
Date: 2017-11-13 Branches: 147 804 18.3 %

Line Branch Exec Source
1
/*	$OpenBSD: httpd.c,v 1.67 2017/05/28 10:37:26 benno Exp $	*/
2
3
/*
4
 * Copyright (c) 2014 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/stat.h>
23
#include <sys/resource.h>
24
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <stdarg.h>
31
#include <string.h>
32
#include <signal.h>
33
#include <getopt.h>
34
#include <netdb.h>
35
#include <fnmatch.h>
36
#include <err.h>
37
#include <errno.h>
38
#include <event.h>
39
#include <syslog.h>
40
#include <unistd.h>
41
#include <ctype.h>
42
#include <pwd.h>
43
44
#include "httpd.h"
45
46
#define MAXIMUM(a, b)	(((a) > (b)) ? (a) : (b))
47
48
__dead void	 usage(void);
49
50
int		 parent_configure(struct httpd *);
51
void		 parent_configure_done(struct httpd *);
52
void		 parent_reload(struct httpd *, unsigned int, const char *);
53
void		 parent_reopen(struct httpd *);
54
void		 parent_sig_handler(int, short, void *);
55
void		 parent_shutdown(struct httpd *);
56
int		 parent_dispatch_server(int, struct privsep_proc *,
57
		    struct imsg *);
58
int		 parent_dispatch_logger(int, struct privsep_proc *,
59
		    struct imsg *);
60
void		 parent_tls_ticket_rekey_start(struct server *);
61
void		 parent_tls_ticket_rekey(int, short, void *);
62
63
struct httpd			*httpd_env;
64
65
static struct privsep_proc procs[] = {
66
	{ "server",	PROC_SERVER, parent_dispatch_server, server },
67
	{ "logger",	PROC_LOGGER, parent_dispatch_logger, logger }
68
};
69
70
void
71
parent_sig_handler(int sig, short event, void *arg)
72
{
73
96
	struct privsep	*ps = arg;
74
75

48
	switch (sig) {
76
	case SIGTERM:
77
	case SIGINT:
78
48
		parent_shutdown(ps->ps_env);
79
48
		break;
80
	case SIGHUP:
81
		log_info("%s: reload requested with SIGHUP", __func__);
82
83
		/*
84
		 * This is safe because libevent uses async signal handlers
85
		 * that run in the event loop and not in signal context.
86
		 */
87
		parent_reload(ps->ps_env, CONFIG_RELOAD, NULL);
88
		break;
89
	case SIGPIPE:
90
		/* ignore */
91
		break;
92
	case SIGUSR1:
93
		log_info("%s: reopen requested with SIGUSR1", __func__);
94
95
		parent_reopen(ps->ps_env);
96
		break;
97
	default:
98
		fatalx("unexpected signal");
99
	}
100
}
101
102
__dead void
103
usage(void)
104
{
105
	extern char	*__progname;
106
107
	fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
108
	    __progname);
109
	exit(1);
110
}
111
112
int
113
main(int argc, char *argv[])
114
{
115
	int			 c;
116
	unsigned int		 proc;
117
	int			 debug = 0, verbose = 0;
118
	uint32_t		 opts = 0;
119
	struct httpd		*env;
120
	struct privsep		*ps;
121
	const char		*conffile = CONF_FILE;
122
	enum privsep_procid	 proc_id = PROC_PARENT;
123
	int			 proc_instance = 0;
124
96
	const char		*errp, *title = NULL;
125
	int			 argc0 = argc;
126
127
480
	while ((c = getopt(argc, argv, "dD:nf:I:P:v")) != -1) {
128


192
		switch (c) {
129
		case 'd':
130
			debug = 2;
131
48
			break;
132
		case 'D':
133
			if (cmdline_symset(optarg) < 0)
134
				log_warnx("could not parse macro definition %s",
135
				    optarg);
136
			break;
137
		case 'n':
138
			debug = 2;
139
			opts |= HTTPD_OPT_NOACTION;
140
			break;
141
		case 'f':
142
48
			conffile = optarg;
143
48
			break;
144
		case 'v':
145
96
			verbose++;
146
96
			opts |= HTTPD_OPT_VERBOSE;
147
96
			break;
148
		case 'P':
149
			title = optarg;
150
			proc_id = proc_getid(procs, nitems(procs), title);
151
			if (proc_id == PROC_MAX)
152
				fatalx("invalid process name");
153
			break;
154
		case 'I':
155
			proc_instance = strtonum(optarg, 0,
156
			    PROC_MAX_INSTANCES, &errp);
157
			if (errp)
158
				fatalx("invalid process instance");
159
			break;
160
		default:
161
			usage();
162
		}
163
	}
164
165
	/* log to stderr until daemonized */
166
48
	log_init(debug ? debug : 1, LOG_DAEMON);
167
168
48
	argc -= optind;
169
48
	if (argc > 0)
170
		usage();
171
172

96
	if ((env = calloc(1, sizeof(*env))) == NULL ||
173
48
	    (ps = calloc(1, sizeof(*ps))) == NULL)
174
		exit(1);
175
176
48
	httpd_env = env;
177
48
	env->sc_ps = ps;
178
48
	ps->ps_env = env;
179
48
	TAILQ_INIT(&ps->ps_rcsocks);
180
48
	env->sc_conffile = conffile;
181
48
	env->sc_opts = opts;
182
183
48
	if (parse_config(env->sc_conffile, env) == -1)
184
		exit(1);
185
186
48
	if (geteuid())
187
		errx(1, "need root privileges");
188
189
48
	if ((ps->ps_pw =  getpwnam(HTTPD_USER)) == NULL)
190
		errx(1, "unknown user %s", HTTPD_USER);
191
192
	/* Configure the control socket */
193
48
	ps->ps_csock.cs_name = NULL;
194
195
48
	log_init(debug, LOG_DAEMON);
196
48
	log_setverbose(verbose);
197
198
48
	if (env->sc_opts & HTTPD_OPT_NOACTION)
199
		ps->ps_noaction = 1;
200
201
48
	ps->ps_instances[PROC_SERVER] = env->sc_prefork_server;
202
48
	ps->ps_instance = proc_instance;
203
48
	if (title != NULL)
204
		ps->ps_title[proc_id] = title;
205
206
48
	if (env->sc_chroot == NULL)
207
		env->sc_chroot = ps->ps_pw->pw_dir;
208
288
	for (proc = 0; proc < nitems(procs); proc++)
209
96
		procs[proc].p_chroot = env->sc_chroot;
210
211
48
	if (env->sc_logdir == NULL) {
212
		if (asprintf(&env->sc_logdir, "%s%s", env->sc_chroot,
213
			HTTPD_LOGROOT) == -1)
214
			errx(1, "malloc failed");
215
	}
216
217
	/* only the parent returns */
218
48
	proc_init(ps, procs, nitems(procs), argc0, argv, proc_id);
219
220
48
	log_procinit("parent");
221

48
	if (!debug && daemon(1, 0) == -1)
222
		err(1, "failed to daemonize");
223
224
48
	if (ps->ps_noaction == 0)
225
48
		log_info("startup");
226
227
48
	if (pledge("stdio rpath wpath cpath inet dns sendfd flock", NULL) == -1)
228
		fatal("pledge");
229
230
48
	event_init();
231
232
48
	signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
233
48
	signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
234
48
	signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
235
48
	signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps);
236
48
	signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps);
237
238
48
	signal_add(&ps->ps_evsigint, NULL);
239
48
	signal_add(&ps->ps_evsigterm, NULL);
240
48
	signal_add(&ps->ps_evsighup, NULL);
241
48
	signal_add(&ps->ps_evsigpipe, NULL);
242
48
	signal_add(&ps->ps_evsigusr1, NULL);
243
244
48
	proc_connect(ps);
245
246
48
	if (load_config(env->sc_conffile, env) == -1) {
247
		proc_kill(env->sc_ps);
248
		exit(1);
249
	}
250
251
48
	if (env->sc_opts & HTTPD_OPT_NOACTION) {
252
		fprintf(stderr, "configuration OK\n");
253
		proc_kill(env->sc_ps);
254
		exit(0);
255
	}
256
257
	/* initialize the TLS session id to a random key for all procs */
258
48
	arc4random_buf(env->sc_tls_sid, sizeof(env->sc_tls_sid));
259
260
48
	if (parent_configure(env) == -1)
261
		fatalx("configuration failed");
262
263
48
	event_dispatch();
264
265
48
	parent_shutdown(env);
266
	/* NOTREACHED */
267
268
48
	return (0);
269
48
}
270
271
int
272
parent_configure(struct httpd *env)
273
{
274
	int			 id;
275
96
	struct ctl_flags	 cf;
276
	int			 ret = -1;
277
	struct server		*srv;
278
	struct media_type	*media;
279
	struct auth		*auth;
280
281
960
	RB_FOREACH(media, mediatypes, env->sc_mediatypes) {
282
432
		if (config_setmedia(env, media) == -1)
283
			fatal("send media");
284
	}
285
286
96
	TAILQ_FOREACH(auth, env->sc_auth, auth_entry) {
287
		if (config_setauth(env, auth) == -1)
288
			fatal("send auth");
289
	}
290
291
	/* First send the servers... */
292
192
	TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
293
48
		if (srv->srv_conf.flags & SRVFLAG_LOCATION)
294
			continue;
295
		/* start the rekey of the tls ticket keys */
296

64
		if (srv->srv_conf.flags & SRVFLAG_TLS &&
297
16
		    srv->srv_conf.tls_ticket_lifetime)
298
			parent_tls_ticket_rekey_start(srv);
299
48
		if (config_setserver(env, srv) == -1)
300
			fatal("send server");
301
	}
302
	/* ...and now send the locations */
303
192
	TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
304
48
		if ((srv->srv_conf.flags & SRVFLAG_LOCATION) == 0)
305
			continue;
306
		if (config_setserver(env, srv) == -1)
307
			fatal("send location");
308
	}
309
310
	/* The servers need to reload their config. */
311
48
	env->sc_reload = env->sc_prefork_server + 1;
312
313
384
	for (id = 0; id < PROC_MAX; id++) {
314
144
		if (id == privsep_process)
315
			continue;
316
96
		cf.cf_opts = env->sc_opts;
317
96
		cf.cf_flags = env->sc_flags;
318
96
		memcpy(cf.cf_tls_sid, env->sc_tls_sid, sizeof(cf.cf_tls_sid));
319
320
96
		proc_compose(env->sc_ps, id, IMSG_CFG_DONE, &cf, sizeof(cf));
321
96
	}
322
323
	ret = 0;
324
325
48
	config_purge(env, CONFIG_ALL & ~CONFIG_SERVERS);
326
48
	return (ret);
327
48
}
328
329
void
330
parent_reload(struct httpd *env, unsigned int reset, const char *filename)
331
{
332
	if (env->sc_reload) {
333
		log_debug("%s: already in progress: %d pending",
334
		    __func__, env->sc_reload);
335
		return;
336
	}
337
338
	/* Switch back to the default config file */
339
	if (filename == NULL || *filename == '\0')
340
		filename = env->sc_conffile;
341
342
	log_debug("%s: level %d config file %s", __func__, reset, filename);
343
344
	config_purge(env, CONFIG_ALL);
345
346
	if (reset == CONFIG_RELOAD) {
347
		if (load_config(filename, env) == -1) {
348
			log_debug("%s: failed to load config file %s",
349
			    __func__, filename);
350
		}
351
352
		config_setreset(env, CONFIG_ALL);
353
354
		if (parent_configure(env) == -1) {
355
			log_debug("%s: failed to commit config from %s",
356
			    __func__, filename);
357
		}
358
	} else
359
		config_setreset(env, reset);
360
}
361
362
void
363
parent_reopen(struct httpd *env)
364
{
365
	proc_compose(env->sc_ps, PROC_LOGGER, IMSG_CTL_REOPEN, NULL, 0);
366
}
367
368
void
369
parent_configure_done(struct httpd *env)
370
{
371
	int	 id;
372
373
192
	if (env->sc_reload == 0) {
374
		log_warnx("%s: configuration already finished", __func__);
375
		return;
376
	}
377
378
96
	env->sc_reload--;
379
96
	if (env->sc_reload == 0) {
380
384
		for (id = 0; id < PROC_MAX; id++) {
381
144
			if (id == privsep_process)
382
				continue;
383
384
96
			proc_compose(env->sc_ps, id, IMSG_CTL_START, NULL, 0);
385
96
		}
386
	}
387
192
}
388
389
void
390
parent_shutdown(struct httpd *env)
391
{
392
96
	config_purge(env, CONFIG_ALL);
393
394
48
	proc_kill(env->sc_ps);
395
48
	control_cleanup(&env->sc_ps->ps_csock);
396
48
	if (env->sc_ps->ps_csock.cs_name != NULL)
397
		(void)unlink(env->sc_ps->ps_csock.cs_name);
398
399
	free(env->sc_ps);
400
	free(env);
401
402
	log_info("parent terminating, pid %d", getpid());
403
404
	exit(0);
405
}
406
407
int
408
parent_dispatch_server(int fd, struct privsep_proc *p, struct imsg *imsg)
409
{
410
96
	struct privsep		*ps = p->p_ps;
411
48
	struct httpd		*env = ps->ps_env;
412
413
48
	switch (imsg->hdr.type) {
414
	case IMSG_CFG_DONE:
415
48
		parent_configure_done(env);
416
		break;
417
	default:
418
		return (-1);
419
	}
420
421
48
	return (0);
422
48
}
423
424
int
425
parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg)
426
{
427
288
	struct privsep		*ps = p->p_ps;
428
144
	struct httpd		*env = ps->ps_env;
429
	unsigned int		 v;
430
	char			*str = NULL;
431
432

144
	switch (imsg->hdr.type) {
433
	case IMSG_CTL_RESET:
434
		IMSG_SIZE_CHECK(imsg, &v);
435
		memcpy(&v, imsg->data, sizeof(v));
436
		parent_reload(env, v, NULL);
437
		break;
438
	case IMSG_CTL_RELOAD:
439
		if (IMSG_DATA_SIZE(imsg) > 0)
440
			str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
441
		parent_reload(env, CONFIG_RELOAD, str);
442
		free(str);
443
		break;
444
	case IMSG_CTL_SHUTDOWN:
445
		parent_shutdown(env);
446
		break;
447
	case IMSG_CTL_REOPEN:
448
		parent_reopen(env);
449
		break;
450
	case IMSG_CFG_DONE:
451
48
		parent_configure_done(env);
452
48
		break;
453
	case IMSG_LOG_OPEN:
454
96
		if (logger_open_priv(imsg) == -1)
455
			fatalx("failed to open log file");
456
		break;
457
	default:
458
		return (-1);
459
	}
460
461
144
	return (0);
462
144
}
463
464
void
465
parent_tls_ticket_rekey_start(struct server *srv)
466
{
467
	struct timeval		 tv;
468
469
	server_generate_ticket_key(&srv->srv_conf);
470
471
	evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv);
472
	timerclear(&tv);
473
	tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4;
474
	evtimer_add(&srv->srv_evt, &tv);
475
}
476
477
void
478
parent_tls_ticket_rekey(int fd, short events, void *arg)
479
{
480
	struct server		*srv = arg;
481
	struct timeval		 tv;
482
483
	server_generate_ticket_key(&srv->srv_conf);
484
	proc_compose_imsg(httpd_env->sc_ps, PROC_SERVER, -1,
485
	    IMSG_TLSTICKET_REKEY, -1, -1, &srv->srv_conf.tls_ticket_key,
486
	    sizeof(srv->srv_conf.tls_ticket_key));
487
	explicit_bzero(&srv->srv_conf.tls_ticket_key,
488
	    sizeof(srv->srv_conf.tls_ticket_key));
489
490
	evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv);
491
	timerclear(&tv);
492
	tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4;
493
	evtimer_add(&srv->srv_evt, &tv);
494
}
495
496
/*
497
 * Utility functions
498
 */
499
500
void
501
event_again(struct event *ev, int fd, short event,
502
    void (*fn)(int, short, void *),
503
    struct timeval *start, struct timeval *end, void *arg)
504
{
505
	struct timeval tv_next, tv_now, tv;
506
507
	getmonotime(&tv_now);
508
	memcpy(&tv_next, end, sizeof(tv_next));
509
	timersub(&tv_now, start, &tv_now);
510
	timersub(&tv_next, &tv_now, &tv_next);
511
512
	memset(&tv, 0, sizeof(tv));
513
	if (timercmp(&tv_next, &tv, >))
514
		memcpy(&tv, &tv_next, sizeof(tv));
515
516
	event_del(ev);
517
	event_set(ev, fd, event, fn, arg);
518
	event_add(ev, &tv);
519
}
520
521
int
522
expand_string(char *label, size_t len, const char *srch, const char *repl)
523
{
524
	char *tmp;
525
	char *p, *q;
526
527
	if ((tmp = calloc(1, len)) == NULL) {
528
		log_debug("%s: calloc", __func__);
529
		return (-1);
530
	}
531
	p = q = label;
532
	while ((q = strstr(p, srch)) != NULL) {
533
		*q = '\0';
534
		if ((strlcat(tmp, p, len) >= len) ||
535
		    (strlcat(tmp, repl, len) >= len)) {
536
			log_debug("%s: string too long", __func__);
537
			free(tmp);
538
			return (-1);
539
		}
540
		q += strlen(srch);
541
		p = q;
542
	}
543
	if (strlcat(tmp, p, len) >= len) {
544
		log_debug("%s: string too long", __func__);
545
		free(tmp);
546
		return (-1);
547
	}
548
	(void)strlcpy(label, tmp, len);	/* always fits */
549
	free(tmp);
550
551
	return (0);
552
}
553
554
const char *
555
canonicalize_host(const char *host, char *name, size_t len)
556
{
557
	struct sockaddr_in	 sin4;
558
	struct sockaddr_in6	 sin6;
559
	size_t			 i, j;
560
	size_t			 plen;
561
	char			 c;
562
563
	if (len < 2)
564
		goto fail;
565
566
	/*
567
	 * Canonicalize an IPv4/6 address
568
	 */
569
	if (inet_pton(AF_INET, host, &sin4) == 1)
570
		return (inet_ntop(AF_INET, &sin4, name, len));
571
	if (inet_pton(AF_INET6, host, &sin6) == 1)
572
		return (inet_ntop(AF_INET6, &sin6, name, len));
573
574
	/*
575
	 * Canonicalize a hostname
576
	 */
577
578
	/* 1. remove repeated dots and convert upper case to lower case */
579
	plen = strlen(host);
580
	memset(name, 0, len);
581
	for (i = j = 0; i < plen; i++) {
582
		if (j >= (len - 1))
583
			goto fail;
584
		c = tolower((unsigned char)host[i]);
585
		if ((c == '.') && (j == 0 || name[j - 1] == '.'))
586
			continue;
587
		name[j++] = c;
588
	}
589
590
	/* 2. remove trailing dots */
591
	for (i = j; i > 0; i--) {
592
		if (name[i - 1] != '.')
593
			break;
594
		name[i - 1] = '\0';
595
		j--;
596
	}
597
	if (j <= 0)
598
		goto fail;
599
600
	return (name);
601
602
 fail:
603
	errno = EINVAL;
604
	return (NULL);
605
}
606
607
const char *
608
url_decode(char *url)
609
{
610
	char		*p, *q;
611
	char		 hex[3];
612
	unsigned long	 x;
613
614
	hex[2] = '\0';
615
	p = q = url;
616
617
	while (*p != '\0') {
618
		switch (*p) {
619
		case '%':
620
			/* Encoding character is followed by two hex chars */
621
			if (!(isxdigit((unsigned char)p[1]) &&
622
			    isxdigit((unsigned char)p[2])))
623
				return (NULL);
624
625
			hex[0] = p[1];
626
			hex[1] = p[2];
627
628
			/*
629
			 * We don't have to validate "hex" because it is
630
			 * guaranteed to include two hex chars followed by nul.
631
			 */
632
			x = strtoul(hex, NULL, 16);
633
			*q = (char)x;
634
			p += 2;
635
			break;
636
		default:
637
			*q = *p;
638
			break;
639
		}
640
		p++;
641
		q++;
642
	}
643
	*q = '\0';
644
645
	return (url);
646
}
647
648
const char *
649
canonicalize_path(const char *input, char *path, size_t len)
650
{
651
	const char	*i;
652
	char		*p, *start, *end;
653
654
	/* assuming input starts with '/' and is nul-terminated */
655
	i = input;
656
	p = path;
657
658
192
	if (*input != '/' || len < 3)
659
		return (NULL);
660
661
	start = p;
662
96
	end = p + (len - 1);
663
664
2208
	while (*i != '\0') {
665
		/* Detect truncation */
666
1008
		if (p >= end)
667
			return (NULL);
668
669
		/* 1. check for special path elements */
670
1008
		if (i[0] == '/') {
671
96
			if (i[1] == '/') {
672
				/* a) skip repeating '//' slashes */
673
				while (i[1] == '/')
674
					i++;
675
				continue;
676

96
			} else if (i[1] == '.' && i[2] == '.' &&
677
			    (i[3] == '/' || i[3] == '\0')) {
678
				/* b) revert '..' to previous directory */
679
				i += 3;
680
				while (p > start && *p != '/')
681
					p--;
682
				*p = '\0';
683
				continue;
684

96
			} else if (i[1] == '.' &&
685
			    (i[2] == '/' || i[2] == '\0')) {
686
				/* c) skip unnecessary '.' current dir */
687
				i += 2;
688
				continue;
689
			}
690
		}
691
692
		/* 2. copy any other characters */
693
1008
		*p++ = *i;
694
1008
		i++;
695
	}
696
96
	if (p == start)
697
		*p++ = '/';
698
96
	*p++ = '\0';
699
700
96
	return (path);
701
96
}
702
703
size_t
704
path_info(char *path)
705
{
706
	char		*p, *start, *end, ch;
707
	struct stat	 st;
708
	int		 ret;
709
710
	start = path;
711
	end = start + strlen(path);
712
713
	for (p = end; p > start; p--) {
714
		/* Scan every path component from the end and at each '/' */
715
		if (p < end && *p != '/')
716
			continue;
717
718
		/* Temporarily cut the path component out */
719
		ch = *p;
720
		*p = '\0';
721
		ret = stat(path, &st);
722
		*p = ch;
723
724
		/* Break if the initial path component was found */
725
		if (ret == 0)
726
			break;
727
	}
728
729
	return (p - start);
730
}
731
732
char *
733
url_encode(const char *src)
734
{
735
	static char	 hex[] = "0123456789ABCDEF";
736
	char		*dp, *dst;
737
	unsigned char	 c;
738
739
	/* We need 3 times the memory if every letter is encoded. */
740
	if ((dst = calloc(3, strlen(src) + 1)) == NULL)
741
		return (NULL);
742
743
	for (dp = dst; *src != 0; src++) {
744
		c = (unsigned char) *src;
745
		if (c == ' ' || c == '#' || c == '%' || c == '?' || c == '"' ||
746
		    c == '&' || c == '<' || c <= 0x1f || c >= 0x7f) {
747
			*dp++ = '%';
748
			*dp++ = hex[c >> 4];
749
			*dp++ = hex[c & 0x0f];
750
		} else
751
			*dp++ = *src;
752
	}
753
	return (dst);
754
}
755
756
char*
757
escape_html(const char* src)
758
{
759
	char		*dp, *dst;
760
761
	/* We need 5 times the memory if every letter is "&" */
762
	if ((dst = calloc(5, strlen(src) + 1)) == NULL)
763
		return NULL;
764
765
	for (dp = dst; *src != 0; src++) {
766
		if (*src == '<') {
767
			*dp++ = '&';
768
			*dp++ = 'l';
769
			*dp++ = 't';
770
			*dp++ = ';';
771
		} else if (*src == '>') {
772
			*dp++ = '&';
773
			*dp++ = 'g';
774
			*dp++ = 't';
775
			*dp++ = ';';
776
		} else if (*src == '&') {
777
			*dp++ = '&';
778
			*dp++ = 'a';
779
			*dp++ = 'm';
780
			*dp++ = 'p';
781
			*dp++ = ';';
782
		} else
783
			*dp++ = *src;
784
	}
785
	return (dst);
786
}
787
788
void
789
socket_rlimit(int maxfd)
790
{
791
	struct rlimit	 rl;
792
793
	if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
794
		fatal("%s: failed to get resource limit", __func__);
795
	log_debug("%s: max open files %llu", __func__, rl.rlim_max);
796
797
	/*
798
	 * Allow the maximum number of open file descriptors for this
799
	 * login class (which should be the class "daemon" by default).
800
	 */
801
	if (maxfd == -1)
802
		rl.rlim_cur = rl.rlim_max;
803
	else
804
		rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd);
805
	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
806
		fatal("%s: failed to set resource limit", __func__);
807
}
808
809
char *
810
evbuffer_getline(struct evbuffer *evb)
811
{
812
	uint8_t		*ptr = EVBUFFER_DATA(evb);
813
	size_t		 len = EVBUFFER_LENGTH(evb);
814
	char		*str;
815
	size_t		 i;
816
817
	/* Safe version of evbuffer_readline() */
818
	if ((str = get_string(ptr, len)) == NULL)
819
		return (NULL);
820
821
	for (i = 0; str[i] != '\0'; i++) {
822
		if (str[i] == '\r' || str[i] == '\n')
823
			break;
824
	}
825
826
	if (i == len) {
827
		free(str);
828
		return (NULL);
829
	}
830
831
	str[i] = '\0';
832
833
	if ((i + 1) < len) {
834
		if (ptr[i] == '\r' && ptr[i + 1] == '\n')
835
			i++;
836
	}
837
838
	evbuffer_drain(evb, ++i);
839
840
	return (str);
841
}
842
843
char *
844
get_string(uint8_t *ptr, size_t len)
845
{
846
	size_t	 i;
847
848
	for (i = 0; i < len; i++)
849
		if (!(isprint((unsigned char)ptr[i]) ||
850
		    isspace((unsigned char)ptr[i])))
851
			break;
852
853
	return strndup(ptr, i);
854
}
855
856
void *
857
get_data(uint8_t *ptr, size_t len)
858
{
859
	uint8_t		*data;
860
861
	if ((data = malloc(len)) == NULL)
862
		return (NULL);
863
	memcpy(data, ptr, len);
864
865
	return (data);
866
}
867
868
int
869
sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
870
{
871
	struct sockaddr_in	*a4, *b4;
872
	struct sockaddr_in6	*a6, *b6;
873
	uint32_t		 av[4], bv[4], mv[4];
874
875
	if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
876
		return (0);
877
	else if (a->sa_family > b->sa_family)
878
		return (1);
879
	else if (a->sa_family < b->sa_family)
880
		return (-1);
881
882
	if (prefixlen == -1)
883
		memset(&mv, 0xff, sizeof(mv));
884
885
	switch (a->sa_family) {
886
	case AF_INET:
887
		a4 = (struct sockaddr_in *)a;
888
		b4 = (struct sockaddr_in *)b;
889
890
		av[0] = a4->sin_addr.s_addr;
891
		bv[0] = b4->sin_addr.s_addr;
892
		if (prefixlen != -1)
893
			mv[0] = prefixlen2mask(prefixlen);
894
895
		if ((av[0] & mv[0]) > (bv[0] & mv[0]))
896
			return (1);
897
		if ((av[0] & mv[0]) < (bv[0] & mv[0]))
898
			return (-1);
899
		break;
900
	case AF_INET6:
901
		a6 = (struct sockaddr_in6 *)a;
902
		b6 = (struct sockaddr_in6 *)b;
903
904
		memcpy(&av, &a6->sin6_addr.s6_addr, 16);
905
		memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
906
		if (prefixlen != -1)
907
			prefixlen2mask6(prefixlen, mv);
908
909
		if ((av[3] & mv[3]) > (bv[3] & mv[3]))
910
			return (1);
911
		if ((av[3] & mv[3]) < (bv[3] & mv[3]))
912
			return (-1);
913
		if ((av[2] & mv[2]) > (bv[2] & mv[2]))
914
			return (1);
915
		if ((av[2] & mv[2]) < (bv[2] & mv[2]))
916
			return (-1);
917
		if ((av[1] & mv[1]) > (bv[1] & mv[1]))
918
			return (1);
919
		if ((av[1] & mv[1]) < (bv[1] & mv[1]))
920
			return (-1);
921
		if ((av[0] & mv[0]) > (bv[0] & mv[0]))
922
			return (1);
923
		if ((av[0] & mv[0]) < (bv[0] & mv[0]))
924
			return (-1);
925
		break;
926
	}
927
928
	return (0);
929
}
930
931
uint32_t
932
prefixlen2mask(uint8_t prefixlen)
933
{
934
	if (prefixlen == 0)
935
		return (0);
936
937
	if (prefixlen > 32)
938
		prefixlen = 32;
939
940
	return (htonl(0xffffffff << (32 - prefixlen)));
941
}
942
943
struct in6_addr *
944
prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
945
{
946
	static struct in6_addr  s6;
947
	int			i;
948
949
	if (prefixlen > 128)
950
		prefixlen = 128;
951
952
	memset(&s6, 0, sizeof(s6));
953
	for (i = 0; i < prefixlen / 8; i++)
954
		s6.s6_addr[i] = 0xff;
955
	i = prefixlen % 8;
956
	if (i)
957
		s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
958
959
	memcpy(mask, &s6, sizeof(s6));
960
961
	return (&s6);
962
}
963
964
int
965
accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
966
    int reserve, volatile int *counter)
967
{
968
	int ret;
969
	if (getdtablecount() + reserve +
970
	    *counter >= getdtablesize()) {
971
		errno = EMFILE;
972
		return (-1);
973
	}
974
975
	if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK)) > -1) {
976
		(*counter)++;
977
		DPRINTF("%s: inflight incremented, now %d",__func__, *counter);
978
	}
979
	return (ret);
980
}
981
982
struct kv *
983
kv_add(struct kvtree *keys, char *key, char *value)
984
{
985
	struct kv	*kv, *oldkv;
986
987
	if (key == NULL)
988
		return (NULL);
989
	if ((kv = calloc(1, sizeof(*kv))) == NULL)
990
		return (NULL);
991
	if ((kv->kv_key = strdup(key)) == NULL) {
992
		free(kv);
993
		return (NULL);
994
	}
995
	if (value != NULL &&
996
	    (kv->kv_value = strdup(value)) == NULL) {
997
		free(kv->kv_key);
998
		free(kv);
999
		return (NULL);
1000
	}
1001
	TAILQ_INIT(&kv->kv_children);
1002
1003
	if ((oldkv = RB_INSERT(kvtree, keys, kv)) != NULL) {
1004
		TAILQ_INSERT_TAIL(&oldkv->kv_children, kv, kv_entry);
1005
		kv->kv_parent = oldkv;
1006
	}
1007
1008
	return (kv);
1009
}
1010
1011
int
1012
kv_set(struct kv *kv, char *fmt, ...)
1013
{
1014
	va_list		  ap;
1015
	char		*value = NULL;
1016
	struct kv	*ckv;
1017
	int		ret;
1018
1019
	va_start(ap, fmt);
1020
	ret = vasprintf(&value, fmt, ap);
1021
	va_end(ap);
1022
	if (ret == -1)
1023
		return (-1);
1024
1025
	/* Remove all children */
1026
	while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) {
1027
		TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry);
1028
		kv_free(ckv);
1029
		free(ckv);
1030
	}
1031
1032
	/* Set the new value */
1033
	free(kv->kv_value);
1034
	kv->kv_value = value;
1035
1036
	return (0);
1037
}
1038
1039
int
1040
kv_setkey(struct kv *kv, char *fmt, ...)
1041
{
1042
	va_list  ap;
1043
	char	*key = NULL;
1044
	int	ret;
1045
1046
	va_start(ap, fmt);
1047
	ret = vasprintf(&key, fmt, ap);
1048
	va_end(ap);
1049
	if (ret == -1)
1050
		return (-1);
1051
1052
	free(kv->kv_key);
1053
	kv->kv_key = key;
1054
1055
	return (0);
1056
}
1057
1058
void
1059
kv_delete(struct kvtree *keys, struct kv *kv)
1060
{
1061
	struct kv	*ckv;
1062
1063
	RB_REMOVE(kvtree, keys, kv);
1064
1065
	/* Remove all children */
1066
	while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) {
1067
		TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry);
1068
		kv_free(ckv);
1069
		free(ckv);
1070
	}
1071
1072
	kv_free(kv);
1073
	free(kv);
1074
}
1075
1076
struct kv *
1077
kv_extend(struct kvtree *keys, struct kv *kv, char *value)
1078
{
1079
	char		*newvalue;
1080
1081
	if (kv == NULL) {
1082
		return (NULL);
1083
	} else if (kv->kv_value != NULL) {
1084
		if (asprintf(&newvalue, "%s%s", kv->kv_value, value) == -1)
1085
			return (NULL);
1086
1087
		free(kv->kv_value);
1088
		kv->kv_value = newvalue;
1089
	} else if ((kv->kv_value = strdup(value)) == NULL)
1090
		return (NULL);
1091
1092
	return (kv);
1093
}
1094
1095
void
1096
kv_purge(struct kvtree *keys)
1097
{
1098
	struct kv	*kv;
1099
1100
	while ((kv = RB_MIN(kvtree, keys)) != NULL)
1101
		kv_delete(keys, kv);
1102
}
1103
1104
void
1105
kv_free(struct kv *kv)
1106
{
1107
	free(kv->kv_key);
1108
	kv->kv_key = NULL;
1109
	free(kv->kv_value);
1110
	kv->kv_value = NULL;
1111
	memset(kv, 0, sizeof(*kv));
1112
}
1113
1114
struct kv *
1115
kv_inherit(struct kv *dst, struct kv *src)
1116
{
1117
	memset(dst, 0, sizeof(*dst));
1118
	memcpy(dst, src, sizeof(*dst));
1119
	TAILQ_INIT(&dst->kv_children);
1120
1121
	if (src->kv_key != NULL) {
1122
		if ((dst->kv_key = strdup(src->kv_key)) == NULL) {
1123
			kv_free(dst);
1124
			return (NULL);
1125
		}
1126
	}
1127
	if (src->kv_value != NULL) {
1128
		if ((dst->kv_value = strdup(src->kv_value)) == NULL) {
1129
			kv_free(dst);
1130
			return (NULL);
1131
		}
1132
	}
1133
1134
	return (dst);
1135
}
1136
1137
int
1138
kv_log(struct evbuffer *log, struct kv *kv)
1139
{
1140
	char	*msg;
1141
1142
	if (log == NULL)
1143
		return (0);
1144
	if (asprintf(&msg, " [%s%s%s]",
1145
	    kv->kv_key == NULL ? "(unknown)" : kv->kv_key,
1146
	    kv->kv_value == NULL ? "" : ": ",
1147
	    kv->kv_value == NULL ? "" : kv->kv_value) == -1)
1148
		return (-1);
1149
	if (evbuffer_add(log, msg, strlen(msg)) == -1) {
1150
		free(msg);
1151
		return (-1);
1152
	}
1153
	free(msg);
1154
1155
	return (0);
1156
}
1157
1158
struct kv *
1159
kv_find(struct kvtree *keys, struct kv *kv)
1160
{
1161
	struct kv	*match;
1162
	const char	*key;
1163
1164
	if (kv->kv_flags & KV_FLAG_GLOBBING) {
1165
		/* Test header key using shell globbing rules */
1166
		key = kv->kv_key == NULL ? "" : kv->kv_key;
1167
		RB_FOREACH(match, kvtree, keys) {
1168
			if (fnmatch(key, match->kv_key, FNM_CASEFOLD) == 0)
1169
				break;
1170
		}
1171
	} else {
1172
		/* Fast tree-based lookup only works without globbing */
1173
		match = RB_FIND(kvtree, keys, kv);
1174
	}
1175
1176
	return (match);
1177
}
1178
1179
int
1180
kv_cmp(struct kv *a, struct kv *b)
1181
{
1182
	return (strcasecmp(a->kv_key, b->kv_key));
1183
}
1184
1185
RB_GENERATE(kvtree, kv, kv_node, kv_cmp);
1186
1187
struct media_type *
1188
media_add(struct mediatypes *types, struct media_type *media)
1189
{
1190
	struct media_type	*entry;
1191
1192
864
	if ((entry = RB_FIND(mediatypes, types, media)) != NULL) {
1193
		log_debug("%s: duplicated entry for \"%s\"", __func__,
1194
		    media->media_name);
1195
		return (NULL);
1196
	}
1197
1198
432
	if ((entry = malloc(sizeof(*media))) == NULL)
1199
		return (NULL);
1200
1201
432
	memcpy(entry, media, sizeof(*entry));
1202

432
	if (media->media_encoding != NULL &&
1203
	    (entry->media_encoding = strdup(media->media_encoding)) == NULL) {
1204
		free(entry);
1205
		return (NULL);
1206
	}
1207
432
	RB_INSERT(mediatypes, types, entry);
1208
1209
432
	return (entry);
1210
432
}
1211
1212
void
1213
media_delete(struct mediatypes *types, struct media_type *media)
1214
{
1215
864
	RB_REMOVE(mediatypes, types, media);
1216
1217
432
	free(media->media_encoding);
1218
432
	free(media);
1219
432
}
1220
1221
void
1222
media_purge(struct mediatypes *types)
1223
{
1224
	struct media_type	*media;
1225
1226
1152
	while ((media = RB_MIN(mediatypes, types)) != NULL)
1227
432
		media_delete(types, media);
1228
96
}
1229
1230
struct media_type *
1231
media_find(struct mediatypes *types, const char *file)
1232
{
1233
	struct media_type	*match, media;
1234
	char			*p;
1235
1236
	/* Last component of the file name */
1237
	p = strchr(file, '\0');
1238
	while (p > file && p[-1] != '.' && p[-1] != '/')
1239
		p--;
1240
	if (*p == '\0')
1241
		return (NULL);
1242
1243
	if (strlcpy(media.media_name, p,
1244
	    sizeof(media.media_name)) >=
1245
	    sizeof(media.media_name)) {
1246
		return (NULL);
1247
	}
1248
1249
	/* Find media type by extension name */
1250
	match = RB_FIND(mediatypes, types, &media);
1251
1252
	return (match);
1253
}
1254
1255
struct media_type *
1256
media_find_config(struct httpd *env, struct server_config *srv_conf,
1257
    const char *file)
1258
{
1259
	struct media_type	*match;
1260
1261
	if ((match = media_find(env->sc_mediatypes, file)) != NULL)
1262
		return (match);
1263
	else if (srv_conf->flags & SRVFLAG_DEFAULT_TYPE)
1264
		return (&srv_conf->default_type);
1265
1266
	/* fallback to the global default type */
1267
	return (&env->sc_default_type);
1268
}
1269
1270
int
1271
media_cmp(struct media_type *a, struct media_type *b)
1272
{
1273
4032
	return (strcasecmp(a->media_name, b->media_name));
1274
}
1275
1276













































39600
RB_GENERATE(mediatypes, media_type, media_entry, media_cmp);
1277
1278
struct auth *
1279
auth_add(struct serverauth *serverauth, struct auth *auth)
1280
{
1281
	struct auth		*entry;
1282
1283
	TAILQ_FOREACH(entry, serverauth, auth_entry) {
1284
		if (strcmp(entry->auth_htpasswd, auth->auth_htpasswd) == 0)
1285
			return (entry);
1286
	}
1287
1288
	if ((entry = calloc(1, sizeof(*entry))) == NULL)
1289
		return (NULL);
1290
1291
	memcpy(entry, auth, sizeof(*entry));
1292
1293
	TAILQ_INSERT_TAIL(serverauth, entry, auth_entry);
1294
1295
	return (entry);
1296
}
1297
1298
struct auth *
1299
auth_byid(struct serverauth *serverauth, uint32_t id)
1300
{
1301
	struct auth	*auth;
1302
1303
	TAILQ_FOREACH(auth, serverauth, auth_entry) {
1304
		if (auth->auth_id == id)
1305
			return (auth);
1306
	}
1307
1308
	return (NULL);
1309
}
1310
1311
void
1312
auth_free(struct serverauth *serverauth, struct auth *auth)
1313
{
1314
	TAILQ_REMOVE(serverauth, auth, auth_entry);
1315
}
1316
1317
1318
const char *
1319
print_host(struct sockaddr_storage *ss, char *buf, size_t len)
1320
{
1321
	if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
1322
	    buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
1323
		buf[0] = '\0';
1324
		return (NULL);
1325
	}
1326
	return (buf);
1327
}
1328
1329
const char *
1330
print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
1331
{
1332
	struct timeval		tv;
1333
	unsigned long		h, sec, min;
1334
1335
	timerclear(&tv);
1336
	timersub(a, b, &tv);
1337
	sec = tv.tv_sec % 60;
1338
	min = tv.tv_sec / 60 % 60;
1339
	h = tv.tv_sec / 60 / 60;
1340
1341
	snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
1342
	return (buf);
1343
}
1344
1345
const char *
1346
printb_flags(const uint32_t v, const char *bits)
1347
{
1348
	static char	 buf[2][BUFSIZ];
1349
	static int	 idx = 0;
1350
	int		 i, any = 0;
1351
	char		 c, *p, *r;
1352
1353
	p = r = buf[++idx % 2];
1354
	memset(p, 0, BUFSIZ);
1355
1356
	if (bits) {
1357
		bits++;
1358
		while ((i = *bits++)) {
1359
			if (v & (1 << (i - 1))) {
1360
				if (any) {
1361
					*p++ = ',';
1362
					*p++ = ' ';
1363
				}
1364
				any = 1;
1365
				for (; (c = *bits) > 32; bits++) {
1366
					if (c == '_')
1367
						*p++ = ' ';
1368
					else
1369
						*p++ =
1370
						    tolower((unsigned char)c);
1371
				}
1372
			} else
1373
				for (; *bits > 32; bits++)
1374
					;
1375
		}
1376
	}
1377
1378
	return (r);
1379
}
1380
1381
void
1382
getmonotime(struct timeval *tv)
1383
{
1384
	struct timespec	 ts;
1385
1386
	if (clock_gettime(CLOCK_MONOTONIC, &ts))
1387
		fatal("clock_gettime");
1388
1389
	TIMESPEC_TO_TIMEVAL(tv, &ts);
1390
}