1/*	$OpenBSD: parse.y,v 1.128 2022/02/27 20:30:30 bluhm Exp $	*/
2
3/*
4 * Copyright (c) 2020 Matthias Pressfreund <mpfr@fn.de>
5 * Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org>
6 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
7 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
8 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
9 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
10 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
11 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
12 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
13 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
14 *
15 * Permission to use, copy, modify, and distribute this software for any
16 * purpose with or without fee is hereby granted, provided that the above
17 * copyright notice and this permission notice appear in all copies.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
20 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
22 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
25 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 */
27
28%{
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/un.h>
32#include <sys/stat.h>
33#include <sys/queue.h>
34#include <sys/tree.h>
35#include <sys/ioctl.h>
36#include <sys/sockio.h>
37#include <sys/time.h>
38
39#include <net/if.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42
43#include <ctype.h>
44#include <unistd.h>
45#include <err.h>
46#include <errno.h>
47#include <limits.h>
48#include <stdint.h>
49#include <stdarg.h>
50#include <stdio.h>
51#include <netdb.h>
52#include <string.h>
53#include <ifaddrs.h>
54#include <syslog.h>
55
56#include "httpd.h"
57#include "http.h"
58
59TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
60static struct file {
61	TAILQ_ENTRY(file)	 entry;
62	FILE			*stream;
63	char			*name;
64	size_t			 ungetpos;
65	size_t			 ungetsize;
66	u_char			*ungetbuf;
67	int			 eof_reached;
68	int			 lineno;
69	int			 errors;
70} *file, *topfile;
71struct file	*pushfile(const char *, int);
72int		 popfile(void);
73int		 check_file_secrecy(int, const char *);
74int		 yyparse(void);
75int		 yylex(void);
76int		 yyerror(const char *, ...)
77    __attribute__((__format__ (printf, 1, 2)))
78    __attribute__((__nonnull__ (1)));
79int		 kw_cmp(const void *, const void *);
80int		 lookup(char *);
81int		 igetc(void);
82int		 lgetc(int);
83void		 lungetc(int);
84int		 findeol(void);
85
86TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
87struct sym {
88	TAILQ_ENTRY(sym)	 entry;
89	int			 used;
90	int			 persist;
91	char			*nam;
92	char			*val;
93};
94int		 symset(const char *, const char *, int);
95char		*symget(const char *);
96
97struct httpd		*conf = NULL;
98static int		 errors = 0;
99static int		 loadcfg = 0;
100uint32_t		 last_server_id = 0;
101uint32_t		 last_auth_id = 0;
102
103static struct server	*srv = NULL, *parentsrv = NULL;
104static struct server_config *srv_conf = NULL;
105struct serverlist	 servers;
106struct media_type	 media;
107
108struct address	*host_v4(const char *);
109struct address	*host_v6(const char *);
110int		 host_dns(const char *, struct addresslist *,
111		    int, struct portrange *, const char *, int);
112int		 host_if(const char *, struct addresslist *,
113		    int, struct portrange *, const char *, int);
114int		 host(const char *, struct addresslist *,
115		    int, struct portrange *, const char *, int);
116struct server	*server_inherit(struct server *, struct server_config *,
117		    struct server_config *);
118int		 listen_on(const char *, int, struct portrange *);
119int		 getservice(char *);
120int		 is_if_in_group(const char *, const char *);
121int		 get_fastcgi_dest(struct server_config *, const char *, char *);
122void		 remove_locations(struct server_config *);
123
124typedef struct {
125	union {
126		int64_t			 number;
127		char			*string;
128		struct timeval		 tv;
129		struct portrange	 port;
130		struct auth		 auth;
131	} v;
132	int lineno;
133} YYSTYPE;
134
135%}
136
137%token	ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS COMMON
138%token	COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY LIFETIME
139%token	LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT PREFORK
140%token	PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TICKET
141%token	TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST
142%token	ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE
143%token	CA CLIENT CRL OPTIONAL PARAM FORWARDED FOUND NOT
144%token	ERRDOCS GZIPSTATIC
145%token	<v.string>	STRING
146%token  <v.number>	NUMBER
147%type	<v.port>	port
148%type	<v.string>	fcgiport
149%type	<v.number>	opttls optmatch optfound
150%type	<v.tv>		timeout
151%type	<v.string>	numberstring optstring
152%type	<v.auth>	authopts
153
154%%
155
156grammar		: /* empty */
157		| grammar include '\n'
158		| grammar '\n'
159		| grammar varset '\n'
160		| grammar main '\n'
161		| grammar server '\n'
162		| grammar types '\n'
163		| grammar error '\n'		{ file->errors++; }
164		;
165
166include		: INCLUDE STRING		{
167			struct file	*nfile;
168
169			if ((nfile = pushfile($2, 0)) == NULL) {
170				yyerror("failed to include file %s", $2);
171				free($2);
172				YYERROR;
173			}
174			free($2);
175
176			file = nfile;
177			lungetc('\n');
178		}
179		;
180
181varset		: STRING '=' STRING	{
182			char *s = $1;
183			while (*s++) {
184				if (isspace((unsigned char)*s)) {
185					yyerror("macro name cannot contain "
186					    "whitespace");
187					free($1);
188					free($3);
189					YYERROR;
190				}
191			}
192			if (symset($1, $3, 0) == -1)
193				fatal("cannot store variable");
194			free($1);
195			free($3);
196		}
197		;
198
199opttls		: /*empty*/	{ $$ = 0; }
200		| TLS		{ $$ = 1; }
201		;
202
203main		: PREFORK NUMBER	{
204			if (loadcfg)
205				break;
206			if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) {
207				yyerror("invalid number of preforked "
208				    "servers: %lld", $2);
209				YYERROR;
210			}
211			conf->sc_prefork_server = $2;
212		}
213		| CHROOT STRING		{
214			conf->sc_chroot = $2;
215		}
216		| ERRDOCS STRING	{
217			if ($2 != NULL && strlcpy(conf->sc_errdocroot, $2,
218			    sizeof(conf->sc_errdocroot)) >=
219			    sizeof(conf->sc_errdocroot)) {
220				yyerror("errdoc root path too long");
221				free($2);
222				YYERROR;
223			}
224			free($2);
225			conf->sc_custom_errdocs = 1;
226		}
227		| LOGDIR STRING		{
228			conf->sc_logdir = $2;
229		}
230		| DEFAULT TYPE mediastring	{
231			memcpy(&conf->sc_default_type, &media,
232			    sizeof(struct media_type));
233		}
234		;
235
236server		: SERVER optmatch STRING	{
237			struct server		*s;
238			struct sockaddr_un	*sun;
239
240			if (!loadcfg) {
241				free($3);
242				YYACCEPT;
243			}
244
245			if ((s = calloc(1, sizeof (*s))) == NULL)
246				fatal("out of memory");
247
248			if (strlcpy(s->srv_conf.name, $3,
249			    sizeof(s->srv_conf.name)) >=
250			    sizeof(s->srv_conf.name)) {
251				yyerror("server name truncated");
252				free($3);
253				free(s);
254				YYERROR;
255			}
256			free($3);
257
258			strlcpy(s->srv_conf.root, HTTPD_DOCROOT,
259			    sizeof(s->srv_conf.root));
260			strlcpy(s->srv_conf.index, HTTPD_INDEX,
261			    sizeof(s->srv_conf.index));
262			strlcpy(s->srv_conf.accesslog, HTTPD_ACCESS_LOG,
263			    sizeof(s->srv_conf.accesslog));
264			strlcpy(s->srv_conf.errorlog, HTTPD_ERROR_LOG,
265			    sizeof(s->srv_conf.errorlog));
266			s->srv_conf.id = ++last_server_id;
267			s->srv_conf.parent_id = s->srv_conf.id;
268			s->srv_s = -1;
269			s->srv_conf.timeout.tv_sec = SERVER_TIMEOUT;
270			s->srv_conf.requesttimeout.tv_sec =
271			    SERVER_REQUESTTIMEOUT;
272			s->srv_conf.maxrequests = SERVER_MAXREQUESTS;
273			s->srv_conf.maxrequestbody = SERVER_MAXREQUESTBODY;
274			s->srv_conf.flags = SRVFLAG_LOG;
275			if ($2)
276				s->srv_conf.flags |= SRVFLAG_SERVER_MATCH;
277			s->srv_conf.logformat = LOG_FORMAT_COMMON;
278			s->srv_conf.tls_protocols = TLS_PROTOCOLS_DEFAULT;
279			if ((s->srv_conf.tls_cert_file =
280			    strdup(HTTPD_TLS_CERT)) == NULL)
281				fatal("out of memory");
282			if ((s->srv_conf.tls_key_file =
283			    strdup(HTTPD_TLS_KEY)) == NULL)
284				fatal("out of memory");
285			strlcpy(s->srv_conf.tls_ciphers,
286			    HTTPD_TLS_CIPHERS,
287			    sizeof(s->srv_conf.tls_ciphers));
288			strlcpy(s->srv_conf.tls_dhe_params,
289			    HTTPD_TLS_DHE_PARAMS,
290			    sizeof(s->srv_conf.tls_dhe_params));
291			strlcpy(s->srv_conf.tls_ecdhe_curves,
292			    HTTPD_TLS_ECDHE_CURVES,
293			    sizeof(s->srv_conf.tls_ecdhe_curves));
294
295			sun = (struct sockaddr_un *)&s->srv_conf.fastcgi_ss;
296			sun->sun_family = AF_UNIX;
297			(void)strlcpy(sun->sun_path, HTTPD_FCGI_SOCKET,
298			    sizeof(sun->sun_path));
299			sun->sun_len = sizeof(struct sockaddr_un);
300
301			s->srv_conf.hsts_max_age = SERVER_HSTS_DEFAULT_AGE;
302
303			(void)strlcpy(s->srv_conf.errdocroot,
304			    conf->sc_errdocroot,
305			    sizeof(s->srv_conf.errdocroot));
306			if (conf->sc_custom_errdocs)
307				s->srv_conf.flags |= SRVFLAG_ERRDOCS;
308
309			if (last_server_id == INT_MAX) {
310				yyerror("too many servers defined");
311				free(s);
312				YYERROR;
313			}
314			srv = s;
315			srv_conf = &srv->srv_conf;
316
317			SPLAY_INIT(&srv->srv_clients);
318			TAILQ_INIT(&srv->srv_hosts);
319			TAILQ_INIT(&srv_conf->fcgiparams);
320
321			TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry);
322		} '{' optnl serveropts_l '}'	{
323			struct server		*s, *sn;
324			struct server_config	*a, *b;
325
326			srv_conf = &srv->srv_conf;
327
328			/* Check if the new server already exists. */
329			if (server_match(srv, 1) != NULL) {
330				yyerror("server \"%s\" defined twice",
331				    srv->srv_conf.name);
332				serverconfig_free(srv_conf);
333				free(srv);
334				YYABORT;
335			}
336
337			if (srv->srv_conf.ss.ss_family == AF_UNSPEC) {
338				yyerror("listen address not specified");
339				serverconfig_free(srv_conf);
340				free(srv);
341				YYERROR;
342			}
343
344			if ((s = server_match(srv, 0)) != NULL) {
345				if ((s->srv_conf.flags & SRVFLAG_TLS) !=
346				    (srv->srv_conf.flags & SRVFLAG_TLS)) {
347					yyerror("server \"%s\": tls and "
348					    "non-tls on same address/port",
349					    srv->srv_conf.name);
350					serverconfig_free(srv_conf);
351					free(srv);
352					YYERROR;
353				}
354				if (srv->srv_conf.flags & SRVFLAG_TLS &&
355				    server_tls_cmp(s, srv) != 0) {
356					yyerror("server \"%s\": tls "
357					    "configuration mismatch on same "
358					    "address/port",
359					    srv->srv_conf.name);
360					serverconfig_free(srv_conf);
361					free(srv);
362					YYERROR;
363				}
364			}
365
366			if ((srv->srv_conf.flags & SRVFLAG_TLS) &&
367			    srv->srv_conf.tls_protocols == 0) {
368				yyerror("server \"%s\": no tls protocols",
369				    srv->srv_conf.name);
370				serverconfig_free(srv_conf);
371				free(srv);
372				YYERROR;
373			}
374
375			if (server_tls_load_keypair(srv) == -1) {
376				/* Soft fail as there may be no certificate. */
377				log_warnx("%s:%d: server \"%s\": failed to "
378				    "load public/private keys", file->name,
379				    yylval.lineno, srv->srv_conf.name);
380
381				remove_locations(srv_conf);
382				serverconfig_free(srv_conf);
383				srv_conf = NULL;
384				free(srv);
385				srv = NULL;
386				break;
387			}
388
389			if (server_tls_load_ca(srv) == -1) {
390				yyerror("server \"%s\": failed to load "
391				    "ca cert(s)", srv->srv_conf.name);
392				serverconfig_free(srv_conf);
393				free(srv);
394				YYERROR;
395			}
396
397			if (server_tls_load_crl(srv) == -1) {
398				yyerror("server \"%s\": failed to load crl(s)",
399				    srv->srv_conf.name);
400				serverconfig_free(srv_conf);
401				free(srv);
402				YYERROR;
403			}
404
405			if (server_tls_load_ocsp(srv) == -1) {
406				yyerror("server \"%s\": failed to load "
407				    "ocsp staple", srv->srv_conf.name);
408				serverconfig_free(srv_conf);
409				free(srv);
410				YYERROR;
411			}
412
413			DPRINTF("adding server \"%s[%u]\"",
414			    srv->srv_conf.name, srv->srv_conf.id);
415
416			TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
417
418			/*
419			 * Add aliases and additional listen addresses as
420			 * individual servers.
421			 */
422			TAILQ_FOREACH(a, &srv->srv_hosts, entry) {
423				/* listen address */
424				if (a->ss.ss_family == AF_UNSPEC)
425					continue;
426				TAILQ_FOREACH(b, &srv->srv_hosts, entry) {
427					/* alias name */
428					if (*b->name == '\0' ||
429					    (b == &srv->srv_conf && b == a))
430						continue;
431
432					if ((sn = server_inherit(srv,
433					    b, a)) == NULL) {
434						serverconfig_free(srv_conf);
435						free(srv);
436						YYABORT;
437					}
438
439					DPRINTF("adding server \"%s[%u]\"",
440					    sn->srv_conf.name, sn->srv_conf.id);
441
442					TAILQ_INSERT_TAIL(conf->sc_servers,
443					    sn, srv_entry);
444				}
445			}
446
447			/* Remove temporary aliases */
448			TAILQ_FOREACH_SAFE(a, &srv->srv_hosts, entry, b) {
449				TAILQ_REMOVE(&srv->srv_hosts, a, entry);
450				if (a == &srv->srv_conf)
451					continue;
452				serverconfig_free(a);
453				free(a);
454			}
455
456			srv = NULL;
457			srv_conf = NULL;
458		}
459		;
460
461serveropts_l	: serveropts_l serveroptsl nl
462		| serveroptsl optnl
463		;
464
465serveroptsl	: LISTEN ON STRING opttls port	{
466			if (listen_on($3, $4, &$5) == -1) {
467				free($3);
468				YYERROR;
469			}
470			free($3);
471		}
472		| ALIAS optmatch STRING		{
473			struct server_config	*alias;
474
475			if (parentsrv != NULL) {
476				yyerror("alias inside location");
477				free($3);
478				YYERROR;
479			}
480
481			if ((alias = calloc(1, sizeof(*alias))) == NULL)
482				fatal("out of memory");
483
484			if (strlcpy(alias->name, $3, sizeof(alias->name)) >=
485			    sizeof(alias->name)) {
486				yyerror("server alias truncated");
487				free($3);
488				free(alias);
489				YYERROR;
490			}
491			free($3);
492
493			if ($2)
494				alias->flags |= SRVFLAG_SERVER_MATCH;
495
496			TAILQ_INSERT_TAIL(&srv->srv_hosts, alias, entry);
497		}
498		| ERRDOCS STRING	{
499			if (parentsrv != NULL) {
500				yyerror("errdocs inside location");
501				YYERROR;
502			}
503			if ($2 != NULL && strlcpy(srv->srv_conf.errdocroot, $2,
504			    sizeof(srv->srv_conf.errdocroot)) >=
505			    sizeof(srv->srv_conf.errdocroot)) {
506				yyerror("errdoc root path too long");
507				free($2);
508				YYERROR;
509			}
510			free($2);
511			srv->srv_conf.flags |= SRVFLAG_ERRDOCS;
512		}
513		| NO ERRDOCS		{
514			if (parentsrv != NULL) {
515				yyerror("errdocs inside location");
516				YYERROR;
517			}
518			srv->srv_conf.flags &= ~SRVFLAG_ERRDOCS;
519		}
520		| tcpip			{
521			if (parentsrv != NULL) {
522				yyerror("tcp flags inside location");
523				YYERROR;
524			}
525		}
526		| connection		{
527			if (parentsrv != NULL) {
528				yyerror("connection options inside location");
529				YYERROR;
530			}
531		}
532		| tls			{
533			struct server_config	*sc;
534			int			 tls_flag = 0;
535
536			if (parentsrv != NULL) {
537				yyerror("tls configuration inside location");
538				YYERROR;
539			}
540
541			/* Ensure that at least one server has TLS enabled. */
542			TAILQ_FOREACH(sc, &srv->srv_hosts, entry) {
543				tls_flag |= (sc->flags & SRVFLAG_TLS);
544			}
545			if (tls_flag == 0) {
546				yyerror("tls options without tls listener");
547				YYERROR;
548			}
549		}
550		| request
551		| root
552		| directory
553		| logformat
554		| fastcgi
555		| authenticate
556		| gzip_static
557		| filter
558		| LOCATION optfound optmatch STRING	{
559			struct server		*s;
560			struct sockaddr_un	*sun;
561
562			if (srv->srv_conf.ss.ss_family == AF_UNSPEC) {
563				yyerror("listen address not specified");
564				free($4);
565				YYERROR;
566			}
567
568			if (parentsrv != NULL) {
569				yyerror("location %s inside location", $4);
570				free($4);
571				YYERROR;
572			}
573
574			if (!loadcfg) {
575				free($4);
576				YYACCEPT;
577			}
578
579			if ((s = calloc(1, sizeof (*s))) == NULL)
580				fatal("out of memory");
581
582			if (strlcpy(s->srv_conf.location, $4,
583			    sizeof(s->srv_conf.location)) >=
584			    sizeof(s->srv_conf.location)) {
585				yyerror("server location truncated");
586				free($4);
587				free(s);
588				YYERROR;
589			}
590			free($4);
591
592			if (strlcpy(s->srv_conf.name, srv->srv_conf.name,
593			    sizeof(s->srv_conf.name)) >=
594			    sizeof(s->srv_conf.name)) {
595				yyerror("server name truncated");
596				free(s);
597				YYERROR;
598			}
599
600			sun = (struct sockaddr_un *)&s->srv_conf.fastcgi_ss;
601			sun->sun_family = AF_UNIX;
602			(void)strlcpy(sun->sun_path, HTTPD_FCGI_SOCKET,
603			    sizeof(sun->sun_path));
604			sun->sun_len = sizeof(struct sockaddr_un);
605
606			s->srv_conf.id = ++last_server_id;
607			/* A location entry uses the parent id */
608			s->srv_conf.parent_id = srv->srv_conf.id;
609			s->srv_conf.flags = SRVFLAG_LOCATION;
610			if ($2 == 1) {
611				s->srv_conf.flags &=
612				    ~SRVFLAG_LOCATION_NOT_FOUND;
613				s->srv_conf.flags |=
614				    SRVFLAG_LOCATION_FOUND;
615			} else if ($2 == -1) {
616				s->srv_conf.flags &=
617				    ~SRVFLAG_LOCATION_FOUND;
618				s->srv_conf.flags |=
619				    SRVFLAG_LOCATION_NOT_FOUND;
620			}
621			if ($3)
622				s->srv_conf.flags |= SRVFLAG_LOCATION_MATCH;
623			s->srv_s = -1;
624			memcpy(&s->srv_conf.ss, &srv->srv_conf.ss,
625			    sizeof(s->srv_conf.ss));
626			s->srv_conf.port = srv->srv_conf.port;
627			s->srv_conf.prefixlen = srv->srv_conf.prefixlen;
628			s->srv_conf.tls_flags = srv->srv_conf.tls_flags;
629
630			if (last_server_id == INT_MAX) {
631				yyerror("too many servers/locations defined");
632				free(s);
633				YYERROR;
634			}
635			parentsrv = srv;
636			srv = s;
637			srv_conf = &srv->srv_conf;
638			SPLAY_INIT(&srv->srv_clients);
639		} '{' optnl serveropts_l '}'	{
640			struct server	*s = NULL;
641			uint32_t	 f;
642
643			f = SRVFLAG_LOCATION_FOUND |
644			    SRVFLAG_LOCATION_NOT_FOUND;
645
646			TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
647				/* Compare locations of same parent server */
648				if ((s->srv_conf.flags & SRVFLAG_LOCATION) &&
649				    s->srv_conf.parent_id ==
650				    srv_conf->parent_id &&
651				    (s->srv_conf.flags & f) ==
652				    (srv_conf->flags & f) &&
653				    strcmp(s->srv_conf.location,
654				    srv_conf->location) == 0)
655					break;
656			}
657			if (s != NULL) {
658				yyerror("location \"%s\" defined twice",
659				    srv->srv_conf.location);
660				serverconfig_free(srv_conf);
661				free(srv);
662				YYABORT;
663			}
664
665			DPRINTF("adding location \"%s\" for \"%s[%u]\"",
666			    srv->srv_conf.location,
667			    srv->srv_conf.name, srv->srv_conf.id);
668
669			TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
670
671			srv = parentsrv;
672			srv_conf = &parentsrv->srv_conf;
673			parentsrv = NULL;
674		}
675		| DEFAULT TYPE mediastring	{
676			srv_conf->flags |= SRVFLAG_DEFAULT_TYPE;
677			memcpy(&srv_conf->default_type, &media,
678			    sizeof(struct media_type));
679		}
680		| include
681		| hsts				{
682			if (parentsrv != NULL) {
683				yyerror("hsts inside location");
684				YYERROR;
685			}
686			srv->srv_conf.flags |= SRVFLAG_SERVER_HSTS;
687		}
688		;
689
690optfound	: /* empty */	{ $$ = 0; }
691		| FOUND		{ $$ = 1; }
692		| NOT FOUND	{ $$ = -1; }
693		;
694
695hsts		: HSTS '{' optnl hstsflags_l '}'
696		| HSTS hstsflags
697		| HSTS
698		;
699
700hstsflags_l	: hstsflags optcommanl hstsflags_l
701		| hstsflags optnl
702		;
703
704hstsflags	: MAXAGE NUMBER		{
705			if ($2 < 0 || $2 > INT_MAX) {
706				yyerror("invalid number of seconds: %lld", $2);
707				YYERROR;
708			}
709			srv_conf->hsts_max_age = $2;
710		}
711		| SUBDOMAINS		{
712			srv->srv_conf.hsts_flags |= HSTSFLAG_SUBDOMAINS;
713		}
714		| PRELOAD		{
715			srv->srv_conf.hsts_flags |= HSTSFLAG_PRELOAD;
716		}
717		;
718
719fastcgi		: NO FCGI		{
720			srv_conf->flags &= ~SRVFLAG_FCGI;
721			srv_conf->flags |= SRVFLAG_NO_FCGI;
722		}
723		| FCGI			{
724			srv_conf->flags &= ~SRVFLAG_NO_FCGI;
725			srv_conf->flags |= SRVFLAG_FCGI;
726		}
727		| FCGI			{
728			srv_conf->flags &= ~SRVFLAG_NO_FCGI;
729			srv_conf->flags |= SRVFLAG_FCGI;
730		} '{' optnl fcgiflags_l '}'
731		| FCGI			{
732			srv_conf->flags &= ~SRVFLAG_NO_FCGI;
733			srv_conf->flags |= SRVFLAG_FCGI;
734		} fcgiflags
735		;
736
737fcgiflags_l	: fcgiflags optcommanl fcgiflags_l
738		| fcgiflags optnl
739		;
740
741fcgiflags	: SOCKET STRING {
742			struct sockaddr_un *sun;
743			sun = (struct sockaddr_un *)&srv_conf->fastcgi_ss;
744			memset(sun, 0, sizeof(*sun));
745			sun->sun_family = AF_UNIX;
746			if (strlcpy(sun->sun_path, $2, sizeof(sun->sun_path))
747			    >= sizeof(sun->sun_path)) {
748				yyerror("socket path too long");
749				free($2);
750				YYERROR;
751			}
752			srv_conf->fastcgi_ss.ss_len =
753			    sizeof(struct sockaddr_un);
754			free($2);
755		}
756		| SOCKET TCP STRING {
757			if (get_fastcgi_dest(srv_conf, $3, FCGI_DEFAULT_PORT)
758			    == -1) {
759				free($3);
760				YYERROR;
761			}
762			free($3);
763		}
764		| SOCKET TCP STRING fcgiport {
765			if (get_fastcgi_dest(srv_conf, $3, $4) == -1) {
766				free($3);
767				free($4);
768				YYERROR;
769			}
770			free($3);
771			free($4);
772		}
773		| PARAM STRING STRING	{
774			struct fastcgi_param	*param;
775
776			if ((param = calloc(1, sizeof(*param))) == NULL)
777				fatal("out of memory");
778
779			if (strlcpy(param->name, $2, sizeof(param->name)) >=
780			    sizeof(param->name)) {
781				yyerror("fastcgi_param name truncated");
782				free($2);
783				free($3);
784				free(param);
785				YYERROR;
786			}
787			if (strlcpy(param->value, $3, sizeof(param->value)) >=
788			    sizeof(param->value)) {
789				yyerror("fastcgi_param value truncated");
790				free($2);
791				free($3);
792				free(param);
793				YYERROR;
794			}
795			free($2);
796			free($3);
797
798			DPRINTF("[%s,%s,%d]: adding param \"%s\" value \"%s\"",
799			    srv_conf->location, srv_conf->name, srv_conf->id,
800			    param->name, param->value);
801			TAILQ_INSERT_HEAD(&srv_conf->fcgiparams, param, entry);
802		}
803		| STRIP NUMBER			{
804			if ($2 < 0 || $2 > INT_MAX) {
805				yyerror("invalid fastcgi strip number");
806				YYERROR;
807			}
808			srv_conf->fcgistrip = $2;
809		}
810		;
811
812connection	: CONNECTION '{' optnl conflags_l '}'
813		| CONNECTION conflags
814		;
815
816conflags_l	: conflags optcommanl conflags_l
817		| conflags optnl
818		;
819
820conflags	: TIMEOUT timeout		{
821			memcpy(&srv_conf->timeout, &$2,
822			    sizeof(struct timeval));
823		}
824		| REQUEST TIMEOUT timeout	{
825			memcpy(&srv_conf->requesttimeout, &$3,
826			    sizeof(struct timeval));
827		}
828		| MAXIMUM REQUESTS NUMBER	{
829			srv_conf->maxrequests = $3;
830		}
831		| MAXIMUM REQUEST BODY NUMBER	{
832			srv_conf->maxrequestbody = $4;
833		}
834		;
835
836tls		: TLS '{' optnl tlsopts_l '}'
837		| TLS tlsopts
838		;
839
840tlsopts_l	: tlsopts optcommanl tlsopts_l
841		| tlsopts optnl
842		;
843
844tlsopts		: CERTIFICATE STRING		{
845			free(srv_conf->tls_cert_file);
846			if ((srv_conf->tls_cert_file = strdup($2)) == NULL)
847				fatal("out of memory");
848			free($2);
849		}
850		| KEY STRING			{
851			free(srv_conf->tls_key_file);
852			if ((srv_conf->tls_key_file = strdup($2)) == NULL)
853				fatal("out of memory");
854			free($2);
855		}
856		| OCSP STRING			{
857			free(srv_conf->tls_ocsp_staple_file);
858			if ((srv_conf->tls_ocsp_staple_file = strdup($2))
859			    == NULL)
860				fatal("out of memory");
861			free($2);
862		}
863		| CIPHERS STRING		{
864			if (strlcpy(srv_conf->tls_ciphers, $2,
865			    sizeof(srv_conf->tls_ciphers)) >=
866			    sizeof(srv_conf->tls_ciphers)) {
867				yyerror("ciphers too long");
868				free($2);
869				YYERROR;
870			}
871			free($2);
872		}
873		| CLIENT CA STRING tlsclientopt {
874			srv_conf->tls_flags |= TLSFLAG_CA;
875			free(srv_conf->tls_ca_file);
876			if ((srv_conf->tls_ca_file = strdup($3)) == NULL)
877				fatal("out of memory");
878			free($3);
879		}
880		| DHE STRING			{
881			if (strlcpy(srv_conf->tls_dhe_params, $2,
882			    sizeof(srv_conf->tls_dhe_params)) >=
883			    sizeof(srv_conf->tls_dhe_params)) {
884				yyerror("dhe too long");
885				free($2);
886				YYERROR;
887			}
888			free($2);
889		}
890		| ECDHE STRING			{
891			if (strlcpy(srv_conf->tls_ecdhe_curves, $2,
892			    sizeof(srv_conf->tls_ecdhe_curves)) >=
893			    sizeof(srv_conf->tls_ecdhe_curves)) {
894				yyerror("ecdhe too long");
895				free($2);
896				YYERROR;
897			}
898			free($2);
899		}
900		| PROTOCOLS STRING		{
901			if (tls_config_parse_protocols(
902			    &srv_conf->tls_protocols, $2) != 0) {
903				yyerror("invalid tls protocols");
904				free($2);
905				YYERROR;
906			}
907			free($2);
908		}
909		| TICKET LIFETIME DEFAULT	{
910			srv_conf->tls_ticket_lifetime = SERVER_DEF_TLS_LIFETIME;
911		}
912		| TICKET LIFETIME NUMBER	{
913			if ($3 != 0 && $3 < SERVER_MIN_TLS_LIFETIME) {
914				yyerror("ticket lifetime too small");
915				YYERROR;
916			}
917			if ($3 > SERVER_MAX_TLS_LIFETIME) {
918				yyerror("ticket lifetime too large");
919				YYERROR;
920			}
921			srv_conf->tls_ticket_lifetime = $3;
922		}
923		| NO TICKET			{
924			srv_conf->tls_ticket_lifetime = 0;
925		}
926		;
927
928tlsclientopt	: /* empty */
929		| tlsclientopt CRL STRING	{
930			srv_conf->tls_flags = TLSFLAG_CRL;
931			free(srv_conf->tls_crl_file);
932			if ((srv_conf->tls_crl_file = strdup($3)) == NULL)
933				fatal("out of memory");
934			free($3);
935		}
936		| tlsclientopt OPTIONAL		{
937			srv_conf->tls_flags |= TLSFLAG_OPTIONAL;
938		}
939		;
940root		: ROOT rootflags
941		| ROOT '{' optnl rootflags_l '}'
942		;
943
944rootflags_l	: rootflags optcommanl rootflags_l
945		| rootflags optnl
946		;
947
948rootflags	: STRING		{
949			if (strlcpy(srv->srv_conf.root, $1,
950			    sizeof(srv->srv_conf.root)) >=
951			    sizeof(srv->srv_conf.root)) {
952				yyerror("document root too long");
953				free($1);
954				YYERROR;
955			}
956			free($1);
957			srv->srv_conf.flags |= SRVFLAG_ROOT;
958		}
959		;
960
961request		: REQUEST requestflags
962		| REQUEST '{' optnl requestflags_l '}'
963		;
964
965requestflags_l	: requestflags optcommanl requestflags_l
966		| requestflags optnl
967		;
968
969requestflags	: REWRITE STRING		{
970			if (strlcpy(srv->srv_conf.path, $2,
971			    sizeof(srv->srv_conf.path)) >=
972			    sizeof(srv->srv_conf.path)) {
973				yyerror("request path too long");
974				free($2);
975				YYERROR;
976			}
977			free($2);
978			srv->srv_conf.flags |= SRVFLAG_PATH_REWRITE;
979			srv->srv_conf.flags &= ~SRVFLAG_NO_PATH_REWRITE;
980		}
981		| NO REWRITE			{
982			srv->srv_conf.flags |= SRVFLAG_NO_PATH_REWRITE;
983			srv->srv_conf.flags &= ~SRVFLAG_PATH_REWRITE;
984		}
985		| STRIP NUMBER			{
986			if ($2 < 0 || $2 > INT_MAX) {
987				yyerror("invalid strip number");
988				YYERROR;
989			}
990			srv->srv_conf.strip = $2;
991		}
992		;
993
994authenticate	: NO AUTHENTICATE		{
995			srv->srv_conf.flags |= SRVFLAG_NO_AUTH;
996		}
997		| AUTHENTICATE authopts		{
998			struct auth	*auth;
999
1000			if ((auth = auth_add(conf->sc_auth, &$2)) == NULL) {
1001				yyerror("failed to add auth");
1002				YYERROR;
1003			}
1004
1005			if (auth->auth_id == 0) {
1006				/* New htpasswd, get new Id */
1007				auth->auth_id = ++last_auth_id;
1008				if (last_auth_id == INT_MAX) {
1009					yyerror("too many auth ids defined");
1010					auth_free(conf->sc_auth, auth);
1011					YYERROR;
1012				}
1013			}
1014
1015			srv->srv_conf.auth_id = auth->auth_id;
1016			srv->srv_conf.flags |= SRVFLAG_AUTH;
1017		}
1018		;
1019
1020authopts	: STRING WITH STRING	{
1021			if (strlcpy(srv->srv_conf.auth_realm, $1,
1022			    sizeof(srv->srv_conf.auth_realm)) >=
1023			    sizeof(srv->srv_conf.auth_realm)) {
1024				yyerror("basic auth realm name too long");
1025				free($1);
1026				YYERROR;
1027			}
1028			free($1);
1029			if (strlcpy($$.auth_htpasswd, $3,
1030			    sizeof($$.auth_htpasswd)) >=
1031			    sizeof($$.auth_htpasswd)) {
1032				yyerror("password file name too long");
1033				free($3);
1034				YYERROR;
1035			}
1036			free($3);
1037
1038		}
1039		| WITH STRING		{
1040			if (strlcpy($$.auth_htpasswd, $2,
1041			    sizeof($$.auth_htpasswd)) >=
1042			    sizeof($$.auth_htpasswd)) {
1043				yyerror("password file name too long");
1044				free($2);
1045				YYERROR;
1046			}
1047			free($2);
1048		};
1049
1050directory	: DIRECTORY dirflags
1051		| DIRECTORY '{' optnl dirflags_l '}'
1052		;
1053
1054dirflags_l	: dirflags optcommanl dirflags_l
1055		| dirflags optnl
1056		;
1057
1058dirflags	: INDEX STRING		{
1059			if (strlcpy(srv_conf->index, $2,
1060			    sizeof(srv_conf->index)) >=
1061			    sizeof(srv_conf->index)) {
1062				yyerror("index file too long");
1063				free($2);
1064				YYERROR;
1065			}
1066			srv_conf->flags &= ~SRVFLAG_NO_INDEX;
1067			srv_conf->flags |= SRVFLAG_INDEX;
1068			free($2);
1069		}
1070		| NO INDEX		{
1071			srv_conf->flags &= ~SRVFLAG_INDEX;
1072			srv_conf->flags |= SRVFLAG_NO_INDEX;
1073		}
1074		| AUTO INDEX		{
1075			srv_conf->flags &= ~SRVFLAG_NO_AUTO_INDEX;
1076			srv_conf->flags |= SRVFLAG_AUTO_INDEX;
1077		}
1078		| NO AUTO INDEX		{
1079			srv_conf->flags &= ~SRVFLAG_AUTO_INDEX;
1080			srv_conf->flags |= SRVFLAG_NO_AUTO_INDEX;
1081		}
1082		;
1083
1084
1085logformat	: LOG logflags
1086		| LOG '{' optnl logflags_l '}'
1087		| NO LOG		{
1088			srv_conf->flags &= ~SRVFLAG_LOG;
1089			srv_conf->flags |= SRVFLAG_NO_LOG;
1090		}
1091		;
1092
1093logflags_l	: logflags optcommanl logflags_l
1094		| logflags optnl
1095		;
1096
1097logflags	: STYLE logstyle
1098		| SYSLOG		{
1099			srv_conf->flags &= ~SRVFLAG_NO_SYSLOG;
1100			srv_conf->flags |= SRVFLAG_SYSLOG;
1101		}
1102		| NO SYSLOG		{
1103			srv_conf->flags &= ~SRVFLAG_SYSLOG;
1104			srv_conf->flags |= SRVFLAG_NO_SYSLOG;
1105		}
1106		| ACCESS STRING		{
1107			if (strlcpy(srv_conf->accesslog, $2,
1108			    sizeof(srv_conf->accesslog)) >=
1109			    sizeof(srv_conf->accesslog)) {
1110				yyerror("access log name too long");
1111				free($2);
1112				YYERROR;
1113			}
1114			free($2);
1115			srv_conf->flags |= SRVFLAG_ACCESS_LOG;
1116		}
1117		| ERR STRING		{
1118			if (strlcpy(srv_conf->errorlog, $2,
1119			    sizeof(srv_conf->errorlog)) >=
1120			    sizeof(srv_conf->errorlog)) {
1121				yyerror("error log name too long");
1122				free($2);
1123				YYERROR;
1124			}
1125			free($2);
1126			srv_conf->flags |= SRVFLAG_ERROR_LOG;
1127		}
1128		;
1129
1130logstyle	: COMMON		{
1131			srv_conf->flags &= ~SRVFLAG_NO_LOG;
1132			srv_conf->flags |= SRVFLAG_LOG;
1133			srv_conf->logformat = LOG_FORMAT_COMMON;
1134		}
1135		| COMBINED		{
1136			srv_conf->flags &= ~SRVFLAG_NO_LOG;
1137			srv_conf->flags |= SRVFLAG_LOG;
1138			srv_conf->logformat = LOG_FORMAT_COMBINED;
1139		}
1140		| CONNECTION		{
1141			srv_conf->flags &= ~SRVFLAG_NO_LOG;
1142			srv_conf->flags |= SRVFLAG_LOG;
1143			srv_conf->logformat = LOG_FORMAT_CONNECTION;
1144		}
1145		| FORWARDED		{
1146			srv_conf->flags &= ~SRVFLAG_NO_LOG;
1147			srv_conf->flags |= SRVFLAG_LOG;
1148			srv_conf->logformat = LOG_FORMAT_FORWARDED;
1149		}
1150		;
1151
1152filter		: block RETURN NUMBER optstring	{
1153			if ($3 <= 0 || server_httperror_byid($3) == NULL) {
1154				yyerror("invalid return code: %lld", $3);
1155				free($4);
1156				YYERROR;
1157			}
1158			srv_conf->return_code = $3;
1159
1160			if ($4 != NULL) {
1161				/* Only for 3xx redirection headers */
1162				if ($3 < 300 || $3 > 399) {
1163					yyerror("invalid return code for "
1164					    "location URI");
1165					free($4);
1166					YYERROR;
1167				}
1168				srv_conf->return_uri = $4;
1169				srv_conf->return_uri_len = strlen($4) + 1;
1170			}
1171		}
1172		| block DROP			{
1173			/* No return code, silently drop the connection */
1174			srv_conf->return_code = 0;
1175		}
1176		| block				{
1177			/* Forbidden */
1178			srv_conf->return_code = 403;
1179		}
1180		| PASS				{
1181			srv_conf->flags &= ~SRVFLAG_BLOCK;
1182			srv_conf->flags |= SRVFLAG_NO_BLOCK;
1183		}
1184		;
1185
1186block		: BLOCK				{
1187			srv_conf->flags &= ~SRVFLAG_NO_BLOCK;
1188			srv_conf->flags |= SRVFLAG_BLOCK;
1189		}
1190		;
1191
1192optmatch	: /* empty */		{ $$ = 0; }
1193		| MATCH			{ $$ = 1; }
1194		;
1195
1196optstring	: /* empty */		{ $$ = NULL; }
1197		| STRING		{ $$ = $1; }
1198		;
1199
1200fcgiport	: NUMBER		{
1201			if ($1 <= 0 || $1 > (int)USHRT_MAX) {
1202				yyerror("invalid port: %lld", $1);
1203				YYERROR;
1204			}
1205			if (asprintf(&$$, "%lld", $1) == -1) {
1206				yyerror("out of memory");
1207				YYERROR;
1208			}
1209		}
1210		| STRING		{
1211			if (getservice($1) <= 0) {
1212				yyerror("invalid port: %s", $1);
1213				free($1);
1214				YYERROR;
1215			}
1216
1217			$$ = $1;
1218		}
1219		;
1220
1221gzip_static	: NO GZIPSTATIC		{
1222			srv->srv_conf.flags &= ~SRVFLAG_GZIP_STATIC;
1223		}
1224		| GZIPSTATIC		{
1225			srv->srv_conf.flags |= SRVFLAG_GZIP_STATIC;
1226		}
1227		;
1228
1229tcpip		: TCP '{' optnl tcpflags_l '}'
1230		| TCP tcpflags
1231		;
1232
1233tcpflags_l	: tcpflags optcommanl tcpflags_l
1234		| tcpflags optnl
1235		;
1236
1237tcpflags	: SACK			{ srv_conf->tcpflags |= TCPFLAG_SACK; }
1238		| NO SACK		{ srv_conf->tcpflags |= TCPFLAG_NSACK; }
1239		| NODELAY		{
1240			srv_conf->tcpflags |= TCPFLAG_NODELAY;
1241		}
1242		| NO NODELAY		{
1243			srv_conf->tcpflags |= TCPFLAG_NNODELAY;
1244		}
1245		| BACKLOG NUMBER	{
1246			if ($2 < 0 || $2 > SERVER_MAX_CLIENTS) {
1247				yyerror("invalid backlog: %lld", $2);
1248				YYERROR;
1249			}
1250			srv_conf->tcpbacklog = $2;
1251		}
1252		| SOCKET BUFFER NUMBER	{
1253			srv_conf->tcpflags |= TCPFLAG_BUFSIZ;
1254			if ((srv_conf->tcpbufsiz = $3) < 0) {
1255				yyerror("invalid socket buffer size: %lld", $3);
1256				YYERROR;
1257			}
1258		}
1259		| IP STRING NUMBER	{
1260			if ($3 < 0) {
1261				yyerror("invalid ttl: %lld", $3);
1262				free($2);
1263				YYERROR;
1264			}
1265			if (strcasecmp("ttl", $2) == 0) {
1266				srv_conf->tcpflags |= TCPFLAG_IPTTL;
1267				srv_conf->tcpipttl = $3;
1268			} else if (strcasecmp("minttl", $2) == 0) {
1269				srv_conf->tcpflags |= TCPFLAG_IPMINTTL;
1270				srv_conf->tcpipminttl = $3;
1271			} else {
1272				yyerror("invalid TCP/IP flag: %s", $2);
1273				free($2);
1274				YYERROR;
1275			}
1276			free($2);
1277		}
1278		;
1279
1280types		: TYPES	'{' optnl mediaopts_l '}'
1281		;
1282
1283mediaopts_l	: mediaopts_l mediaoptsl nl
1284		| mediaoptsl nl
1285		;
1286
1287mediaoptsl	: mediastring medianames_l optsemicolon
1288		| include
1289		;
1290
1291mediastring	: STRING '/' STRING	{
1292			if (strlcpy(media.media_type, $1,
1293			    sizeof(media.media_type)) >=
1294			    sizeof(media.media_type) ||
1295			    strlcpy(media.media_subtype, $3,
1296			    sizeof(media.media_subtype)) >=
1297			    sizeof(media.media_subtype)) {
1298				yyerror("media type too long");
1299				free($1);
1300				free($3);
1301				YYERROR;
1302			}
1303			free($1);
1304			free($3);
1305		}
1306		;
1307
1308medianames_l	: medianames_l medianamesl
1309		| medianamesl
1310		;
1311
1312medianamesl	: numberstring				{
1313			if (strlcpy(media.media_name, $1,
1314			    sizeof(media.media_name)) >=
1315			    sizeof(media.media_name)) {
1316				yyerror("media name too long");
1317				free($1);
1318				YYERROR;
1319			}
1320			free($1);
1321
1322			if (!loadcfg)
1323				break;
1324
1325			if (media_add(conf->sc_mediatypes, &media) == NULL) {
1326				yyerror("failed to add media type");
1327				YYERROR;
1328			}
1329		}
1330		;
1331
1332port		: PORT NUMBER {
1333			if ($2 <= 0 || $2 > (int)USHRT_MAX) {
1334				yyerror("invalid port: %lld", $2);
1335				YYERROR;
1336			}
1337			$$.val[0] = htons($2);
1338			$$.op = 1;
1339		}
1340		| PORT STRING {
1341			int	 val;
1342
1343			if ((val = getservice($2)) == -1) {
1344				yyerror("invalid port: %s", $2);
1345				free($2);
1346				YYERROR;
1347			}
1348			free($2);
1349
1350			$$.val[0] = val;
1351			$$.op = 1;
1352		}
1353		;
1354
1355timeout		: NUMBER
1356		{
1357			if ($1 < 0) {
1358				yyerror("invalid timeout: %lld", $1);
1359				YYERROR;
1360			}
1361			$$.tv_sec = $1;
1362			$$.tv_usec = 0;
1363		}
1364		;
1365
1366numberstring	: NUMBER		{
1367			char *s;
1368			if (asprintf(&s, "%lld", $1) == -1) {
1369				yyerror("asprintf: number");
1370				YYERROR;
1371			}
1372			$$ = s;
1373		}
1374		| STRING
1375		;
1376
1377optsemicolon	: ';'
1378		|
1379		;
1380
1381optnl		: '\n' optnl
1382		|
1383		;
1384
1385optcommanl	: ',' optnl
1386		| nl
1387		;
1388
1389nl		: '\n' optnl
1390		;
1391
1392%%
1393
1394struct keywords {
1395	const char	*k_name;
1396	int		 k_val;
1397};
1398
1399int
1400yyerror(const char *fmt, ...)
1401{
1402	va_list		 ap;
1403	char		*msg;
1404
1405	file->errors++;
1406	va_start(ap, fmt);
1407	if (vasprintf(&msg, fmt, ap) == -1)
1408		fatalx("yyerror vasprintf");
1409	va_end(ap);
1410	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
1411	free(msg);
1412	return (0);
1413}
1414
1415int
1416kw_cmp(const void *k, const void *e)
1417{
1418	return (strcmp(k, ((const struct keywords *)e)->k_name));
1419}
1420
1421int
1422lookup(char *s)
1423{
1424	/* this has to be sorted always */
1425	static const struct keywords keywords[] = {
1426		{ "access",		ACCESS },
1427		{ "alias",		ALIAS },
1428		{ "authenticate",	AUTHENTICATE},
1429		{ "auto",		AUTO },
1430		{ "backlog",		BACKLOG },
1431		{ "block",		BLOCK },
1432		{ "body",		BODY },
1433		{ "buffer",		BUFFER },
1434		{ "ca",			CA },
1435		{ "certificate",	CERTIFICATE },
1436		{ "chroot",		CHROOT },
1437		{ "ciphers",		CIPHERS },
1438		{ "client",		CLIENT },
1439		{ "combined",		COMBINED },
1440		{ "common",		COMMON },
1441		{ "connection",		CONNECTION },
1442		{ "crl",		CRL },
1443		{ "default",		DEFAULT },
1444		{ "dhe",		DHE },
1445		{ "directory",		DIRECTORY },
1446		{ "drop",		DROP },
1447		{ "ecdhe",		ECDHE },
1448		{ "errdocs",		ERRDOCS },
1449		{ "error",		ERR },
1450		{ "fastcgi",		FCGI },
1451		{ "forwarded",		FORWARDED },
1452		{ "found",		FOUND },
1453		{ "gzip-static",	GZIPSTATIC },
1454		{ "hsts",		HSTS },
1455		{ "include",		INCLUDE },
1456		{ "index",		INDEX },
1457		{ "ip",			IP },
1458		{ "key",		KEY },
1459		{ "lifetime",		LIFETIME },
1460		{ "listen",		LISTEN },
1461		{ "location",		LOCATION },
1462		{ "log",		LOG },
1463		{ "logdir",		LOGDIR },
1464		{ "match",		MATCH },
1465		{ "max",		MAXIMUM },
1466		{ "max-age",		MAXAGE },
1467		{ "no",			NO },
1468		{ "nodelay",		NODELAY },
1469		{ "not",		NOT },
1470		{ "ocsp",		OCSP },
1471		{ "on",			ON },
1472		{ "optional",		OPTIONAL },
1473		{ "param",		PARAM },
1474		{ "pass",		PASS },
1475		{ "port",		PORT },
1476		{ "prefork",		PREFORK },
1477		{ "preload",		PRELOAD },
1478		{ "protocols",		PROTOCOLS },
1479		{ "request",		REQUEST },
1480		{ "requests",		REQUESTS },
1481		{ "return",		RETURN },
1482		{ "rewrite",		REWRITE },
1483		{ "root",		ROOT },
1484		{ "sack",		SACK },
1485		{ "server",		SERVER },
1486		{ "socket",		SOCKET },
1487		{ "strip",		STRIP },
1488		{ "style",		STYLE },
1489		{ "subdomains",		SUBDOMAINS },
1490		{ "syslog",		SYSLOG },
1491		{ "tcp",		TCP },
1492		{ "ticket",		TICKET },
1493		{ "timeout",		TIMEOUT },
1494		{ "tls",		TLS },
1495		{ "type",		TYPE },
1496		{ "types",		TYPES },
1497		{ "with",		WITH }
1498	};
1499	const struct keywords	*p;
1500
1501	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
1502	    sizeof(keywords[0]), kw_cmp);
1503
1504	if (p)
1505		return (p->k_val);
1506	else
1507		return (STRING);
1508}
1509
1510#define START_EXPAND	1
1511#define DONE_EXPAND	2
1512
1513static int	expanding;
1514
1515int
1516igetc(void)
1517{
1518	int	c;
1519
1520	while (1) {
1521		if (file->ungetpos > 0)
1522			c = file->ungetbuf[--file->ungetpos];
1523		else
1524			c = getc(file->stream);
1525
1526		if (c == START_EXPAND)
1527			expanding = 1;
1528		else if (c == DONE_EXPAND)
1529			expanding = 0;
1530		else
1531			break;
1532	}
1533	return (c);
1534}
1535
1536int
1537lgetc(int quotec)
1538{
1539	int		c, next;
1540
1541	if (quotec) {
1542		if ((c = igetc()) == EOF) {
1543			yyerror("reached end of file while parsing "
1544			    "quoted string");
1545			if (file == topfile || popfile() == EOF)
1546				return (EOF);
1547			return (quotec);
1548		}
1549		return (c);
1550	}
1551
1552	while ((c = igetc()) == '\\') {
1553		next = igetc();
1554		if (next != '\n') {
1555			c = next;
1556			break;
1557		}
1558		yylval.lineno = file->lineno;
1559		file->lineno++;
1560	}
1561
1562	if (c == EOF) {
1563		/*
1564		 * Fake EOL when hit EOF for the first time. This gets line
1565		 * count right if last line in included file is syntactically
1566		 * invalid and has no newline.
1567		 */
1568		if (file->eof_reached == 0) {
1569			file->eof_reached = 1;
1570			return ('\n');
1571		}
1572		while (c == EOF) {
1573			if (file == topfile || popfile() == EOF)
1574				return (EOF);
1575			c = igetc();
1576		}
1577	}
1578	return (c);
1579}
1580
1581void
1582lungetc(int c)
1583{
1584	if (c == EOF)
1585		return;
1586
1587	if (file->ungetpos >= file->ungetsize) {
1588		void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
1589		if (p == NULL)
1590			err(1, "%s", __func__);
1591		file->ungetbuf = p;
1592		file->ungetsize *= 2;
1593	}
1594	file->ungetbuf[file->ungetpos++] = c;
1595}
1596
1597int
1598findeol(void)
1599{
1600	int	c;
1601
1602	/* skip to either EOF or the first real EOL */
1603	while (1) {
1604		c = lgetc(0);
1605		if (c == '\n') {
1606			file->lineno++;
1607			break;
1608		}
1609		if (c == EOF)
1610			break;
1611	}
1612	return (ERROR);
1613}
1614
1615int
1616yylex(void)
1617{
1618	char	 buf[8096];
1619	char	*p, *val;
1620	int	 quotec, next, c;
1621	int	 token;
1622
1623top:
1624	p = buf;
1625	while ((c = lgetc(0)) == ' ' || c == '\t')
1626		; /* nothing */
1627
1628	yylval.lineno = file->lineno;
1629	if (c == '#')
1630		while ((c = lgetc(0)) != '\n' && c != EOF)
1631			; /* nothing */
1632	if (c == '$' && !expanding) {
1633		while (1) {
1634			if ((c = lgetc(0)) == EOF)
1635				return (0);
1636
1637			if (p + 1 >= buf + sizeof(buf) - 1) {
1638				yyerror("string too long");
1639				return (findeol());
1640			}
1641			if (isalnum(c) || c == '_') {
1642				*p++ = c;
1643				continue;
1644			}
1645			*p = '\0';
1646			lungetc(c);
1647			break;
1648		}
1649		val = symget(buf);
1650		if (val == NULL) {
1651			yyerror("macro '%s' not defined", buf);
1652			return (findeol());
1653		}
1654		p = val + strlen(val) - 1;
1655		lungetc(DONE_EXPAND);
1656		while (p >= val) {
1657			lungetc((unsigned char)*p);
1658			p--;
1659		}
1660		lungetc(START_EXPAND);
1661		goto top;
1662	}
1663
1664	switch (c) {
1665	case '\'':
1666	case '"':
1667		quotec = c;
1668		while (1) {
1669			if ((c = lgetc(quotec)) == EOF)
1670				return (0);
1671			if (c == '\n') {
1672				file->lineno++;
1673				continue;
1674			} else if (c == '\\') {
1675				if ((next = lgetc(quotec)) == EOF)
1676					return (0);
1677				if (next == quotec || next == ' ' ||
1678				    next == '\t')
1679					c = next;
1680				else if (next == '\n') {
1681					file->lineno++;
1682					continue;
1683				} else
1684					lungetc(next);
1685			} else if (c == quotec) {
1686				*p = '\0';
1687				break;
1688			} else if (c == '\0') {
1689				yyerror("syntax error");
1690				return (findeol());
1691			}
1692			if (p + 1 >= buf + sizeof(buf) - 1) {
1693				yyerror("string too long");
1694				return (findeol());
1695			}
1696			*p++ = c;
1697		}
1698		yylval.v.string = strdup(buf);
1699		if (yylval.v.string == NULL)
1700			err(1, "%s", __func__);
1701		return (STRING);
1702	}
1703
1704#define allowed_to_end_number(x) \
1705	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1706
1707	if (c == '-' || isdigit(c)) {
1708		do {
1709			*p++ = c;
1710			if ((size_t)(p-buf) >= sizeof(buf)) {
1711				yyerror("string too long");
1712				return (findeol());
1713			}
1714		} while ((c = lgetc(0)) != EOF && isdigit(c));
1715		lungetc(c);
1716		if (p == buf + 1 && buf[0] == '-')
1717			goto nodigits;
1718		if (c == EOF || allowed_to_end_number(c)) {
1719			const char *errstr = NULL;
1720
1721			*p = '\0';
1722			yylval.v.number = strtonum(buf, LLONG_MIN,
1723			    LLONG_MAX, &errstr);
1724			if (errstr) {
1725				yyerror("\"%s\" invalid number: %s",
1726				    buf, errstr);
1727				return (findeol());
1728			}
1729			return (NUMBER);
1730		} else {
1731nodigits:
1732			while (p > buf + 1)
1733				lungetc((unsigned char)*--p);
1734			c = (unsigned char)*--p;
1735			if (c == '-')
1736				return (c);
1737		}
1738	}
1739
1740#define allowed_in_string(x) \
1741	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1742	x != '{' && x != '}' && x != '<' && x != '>' && \
1743	x != '!' && x != '=' && x != '#' && \
1744	x != ',' && x != ';' && x != '/'))
1745
1746	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
1747		do {
1748			*p++ = c;
1749			if ((size_t)(p-buf) >= sizeof(buf)) {
1750				yyerror("string too long");
1751				return (findeol());
1752			}
1753		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
1754		lungetc(c);
1755		*p = '\0';
1756		if ((token = lookup(buf)) == STRING)
1757			if ((yylval.v.string = strdup(buf)) == NULL)
1758				err(1, "%s", __func__);
1759		return (token);
1760	}
1761	if (c == '\n') {
1762		yylval.lineno = file->lineno;
1763		file->lineno++;
1764	}
1765	if (c == EOF)
1766		return (0);
1767	return (c);
1768}
1769
1770int
1771check_file_secrecy(int fd, const char *fname)
1772{
1773	struct stat	st;
1774
1775	if (fstat(fd, &st)) {
1776		log_warn("cannot stat %s", fname);
1777		return (-1);
1778	}
1779	if (st.st_uid != 0 && st.st_uid != getuid()) {
1780		log_warnx("%s: owner not root or current user", fname);
1781		return (-1);
1782	}
1783	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
1784		log_warnx("%s: group writable or world read/writable", fname);
1785		return (-1);
1786	}
1787	return (0);
1788}
1789
1790struct file *
1791pushfile(const char *name, int secret)
1792{
1793	struct file	*nfile;
1794
1795	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
1796		log_warn("%s", __func__);
1797		return (NULL);
1798	}
1799	if ((nfile->name = strdup(name)) == NULL) {
1800		log_warn("%s", __func__);
1801		free(nfile);
1802		return (NULL);
1803	}
1804	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
1805		log_warn("%s: %s", __func__, nfile->name);
1806		free(nfile->name);
1807		free(nfile);
1808		return (NULL);
1809	} else if (secret &&
1810	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
1811		fclose(nfile->stream);
1812		free(nfile->name);
1813		free(nfile);
1814		return (NULL);
1815	}
1816	nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
1817	nfile->ungetsize = 16;
1818	nfile->ungetbuf = malloc(nfile->ungetsize);
1819	if (nfile->ungetbuf == NULL) {
1820		log_warn("%s", __func__);
1821		fclose(nfile->stream);
1822		free(nfile->name);
1823		free(nfile);
1824		return (NULL);
1825	}
1826	TAILQ_INSERT_TAIL(&files, nfile, entry);
1827	return (nfile);
1828}
1829
1830int
1831popfile(void)
1832{
1833	struct file	*prev;
1834
1835	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
1836		prev->errors += file->errors;
1837
1838	TAILQ_REMOVE(&files, file, entry);
1839	fclose(file->stream);
1840	free(file->name);
1841	free(file->ungetbuf);
1842	free(file);
1843	file = prev;
1844	return (file ? 0 : EOF);
1845}
1846
1847int
1848parse_config(const char *filename, struct httpd *x_conf)
1849{
1850	struct sym		*sym, *next;
1851	struct media_type	 dflt = HTTPD_DEFAULT_TYPE;
1852
1853	conf = x_conf;
1854	if (config_init(conf) == -1) {
1855		log_warn("%s: cannot initialize configuration", __func__);
1856		return (-1);
1857	}
1858
1859	/* Set default media type */
1860	memcpy(&conf->sc_default_type, &dflt, sizeof(struct media_type));
1861
1862	errors = 0;
1863
1864	if ((file = pushfile(filename, 0)) == NULL)
1865		return (-1);
1866
1867	topfile = file;
1868	setservent(1);
1869
1870	yyparse();
1871	errors = file->errors;
1872	while (popfile() != EOF)
1873		;
1874
1875	endservent();
1876	endprotoent();
1877
1878	/* Free macros */
1879	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
1880		if (!sym->persist) {
1881			free(sym->nam);
1882			free(sym->val);
1883			TAILQ_REMOVE(&symhead, sym, entry);
1884			free(sym);
1885		}
1886	}
1887
1888	return (errors ? -1 : 0);
1889}
1890
1891int
1892load_config(const char *filename, struct httpd *x_conf)
1893{
1894	struct sym		*sym, *next;
1895	struct http_mediatype	 mediatypes[] = MEDIA_TYPES;
1896	struct media_type	 m;
1897	int			 i;
1898
1899	conf = x_conf;
1900	conf->sc_flags = 0;
1901
1902	loadcfg = 1;
1903	errors = 0;
1904	last_server_id = 0;
1905	last_auth_id = 0;
1906
1907	srv = NULL;
1908
1909	if ((file = pushfile(filename, 0)) == NULL)
1910		return (-1);
1911
1912	topfile = file;
1913	setservent(1);
1914
1915	yyparse();
1916	errors = file->errors;
1917	popfile();
1918
1919	endservent();
1920	endprotoent();
1921
1922	/* Free macros and check which have not been used. */
1923	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
1924		next = TAILQ_NEXT(sym, entry);
1925		if ((conf->sc_opts & HTTPD_OPT_VERBOSE) && !sym->used)
1926			fprintf(stderr, "warning: macro '%s' not "
1927			    "used\n", sym->nam);
1928		if (!sym->persist) {
1929			free(sym->nam);
1930			free(sym->val);
1931			TAILQ_REMOVE(&symhead, sym, entry);
1932			free(sym);
1933		}
1934	}
1935
1936	if (TAILQ_EMPTY(conf->sc_servers)) {
1937		log_warnx("no actions, nothing to do");
1938		errors++;
1939	}
1940
1941	if (RB_EMPTY(conf->sc_mediatypes)) {
1942		/* Add default media types */
1943		for (i = 0; mediatypes[i].media_name != NULL; i++) {
1944			(void)strlcpy(m.media_name, mediatypes[i].media_name,
1945			    sizeof(m.media_name));
1946			(void)strlcpy(m.media_type, mediatypes[i].media_type,
1947			    sizeof(m.media_type));
1948			(void)strlcpy(m.media_subtype,
1949			    mediatypes[i].media_subtype,
1950			    sizeof(m.media_subtype));
1951			m.media_encoding = NULL;
1952
1953			if (media_add(conf->sc_mediatypes, &m) == NULL) {
1954				log_warnx("failed to add default media \"%s\"",
1955				    m.media_name);
1956				errors++;
1957			}
1958		}
1959	}
1960
1961	return (errors ? -1 : 0);
1962}
1963
1964int
1965symset(const char *nam, const char *val, int persist)
1966{
1967	struct sym	*sym;
1968
1969	TAILQ_FOREACH(sym, &symhead, entry) {
1970		if (strcmp(nam, sym->nam) == 0)
1971			break;
1972	}
1973
1974	if (sym != NULL) {
1975		if (sym->persist == 1)
1976			return (0);
1977		else {
1978			free(sym->nam);
1979			free(sym->val);
1980			TAILQ_REMOVE(&symhead, sym, entry);
1981			free(sym);
1982		}
1983	}
1984	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1985		return (-1);
1986
1987	sym->nam = strdup(nam);
1988	if (sym->nam == NULL) {
1989		free(sym);
1990		return (-1);
1991	}
1992	sym->val = strdup(val);
1993	if (sym->val == NULL) {
1994		free(sym->nam);
1995		free(sym);
1996		return (-1);
1997	}
1998	sym->used = 0;
1999	sym->persist = persist;
2000	TAILQ_INSERT_TAIL(&symhead, sym, entry);
2001	return (0);
2002}
2003
2004int
2005cmdline_symset(char *s)
2006{
2007	char	*sym, *val;
2008	int	ret;
2009
2010	if ((val = strrchr(s, '=')) == NULL)
2011		return (-1);
2012	sym = strndup(s, val - s);
2013	if (sym == NULL)
2014		errx(1, "%s: strndup", __func__);
2015	ret = symset(sym, val + 1, 1);
2016	free(sym);
2017
2018	return (ret);
2019}
2020
2021char *
2022symget(const char *nam)
2023{
2024	struct sym	*sym;
2025
2026	TAILQ_FOREACH(sym, &symhead, entry) {
2027		if (strcmp(nam, sym->nam) == 0) {
2028			sym->used = 1;
2029			return (sym->val);
2030		}
2031	}
2032	return (NULL);
2033}
2034
2035struct address *
2036host_v4(const char *s)
2037{
2038	struct in_addr		 ina;
2039	struct sockaddr_in	*sain;
2040	struct address		*h;
2041
2042	memset(&ina, 0, sizeof(ina));
2043	if (inet_pton(AF_INET, s, &ina) != 1)
2044		return (NULL);
2045
2046	if ((h = calloc(1, sizeof(*h))) == NULL)
2047		fatal(__func__);
2048	sain = (struct sockaddr_in *)&h->ss;
2049	sain->sin_len = sizeof(struct sockaddr_in);
2050	sain->sin_family = AF_INET;
2051	sain->sin_addr.s_addr = ina.s_addr;
2052	if (sain->sin_addr.s_addr == INADDR_ANY)
2053		h->prefixlen = 0; /* 0.0.0.0 address */
2054	else
2055		h->prefixlen = -1; /* host address */
2056	return (h);
2057}
2058
2059struct address *
2060host_v6(const char *s)
2061{
2062	struct addrinfo		 hints, *res;
2063	struct sockaddr_in6	*sa_in6;
2064	struct address		*h = NULL;
2065
2066	memset(&hints, 0, sizeof(hints));
2067	hints.ai_family = AF_INET6;
2068	hints.ai_socktype = SOCK_DGRAM; /* dummy */
2069	hints.ai_flags = AI_NUMERICHOST;
2070	if (getaddrinfo(s, "0", &hints, &res) == 0) {
2071		if ((h = calloc(1, sizeof(*h))) == NULL)
2072			fatal(__func__);
2073		sa_in6 = (struct sockaddr_in6 *)&h->ss;
2074		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
2075		sa_in6->sin6_family = AF_INET6;
2076		memcpy(&sa_in6->sin6_addr,
2077		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
2078		    sizeof(sa_in6->sin6_addr));
2079		sa_in6->sin6_scope_id =
2080		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
2081		if (memcmp(&sa_in6->sin6_addr, &in6addr_any,
2082		    sizeof(sa_in6->sin6_addr)) == 0)
2083			h->prefixlen = 0; /* any address */
2084		else
2085			h->prefixlen = -1; /* host address */
2086		freeaddrinfo(res);
2087	}
2088
2089	return (h);
2090}
2091
2092int
2093host_dns(const char *s, struct addresslist *al, int max,
2094    struct portrange *port, const char *ifname, int ipproto)
2095{
2096	struct addrinfo		 hints, *res0, *res;
2097	int			 error, cnt = 0;
2098	struct sockaddr_in	*sain;
2099	struct sockaddr_in6	*sin6;
2100	struct address		*h;
2101
2102	if ((cnt = host_if(s, al, max, port, ifname, ipproto)) != 0)
2103		return (cnt);
2104
2105	memset(&hints, 0, sizeof(hints));
2106	hints.ai_family = PF_UNSPEC;
2107	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
2108	hints.ai_flags = AI_ADDRCONFIG;
2109	error = getaddrinfo(s, NULL, &hints, &res0);
2110	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
2111		return (0);
2112	if (error) {
2113		log_warnx("%s: could not parse \"%s\": %s", __func__, s,
2114		    gai_strerror(error));
2115		return (-1);
2116	}
2117
2118	for (res = res0; res && cnt < max; res = res->ai_next) {
2119		if (res->ai_family != AF_INET &&
2120		    res->ai_family != AF_INET6)
2121			continue;
2122		if ((h = calloc(1, sizeof(*h))) == NULL)
2123			fatal(__func__);
2124
2125		if (port != NULL)
2126			memcpy(&h->port, port, sizeof(h->port));
2127		if (ifname != NULL) {
2128			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
2129			    sizeof(h->ifname))
2130				log_warnx("%s: interface name truncated",
2131				    __func__);
2132			freeaddrinfo(res0);
2133			free(h);
2134			return (-1);
2135		}
2136		if (ipproto != -1)
2137			h->ipproto = ipproto;
2138		h->ss.ss_family = res->ai_family;
2139		h->prefixlen = -1; /* host address */
2140
2141		if (res->ai_family == AF_INET) {
2142			sain = (struct sockaddr_in *)&h->ss;
2143			sain->sin_len = sizeof(struct sockaddr_in);
2144			sain->sin_addr.s_addr = ((struct sockaddr_in *)
2145			    res->ai_addr)->sin_addr.s_addr;
2146		} else {
2147			sin6 = (struct sockaddr_in6 *)&h->ss;
2148			sin6->sin6_len = sizeof(struct sockaddr_in6);
2149			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
2150			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
2151		}
2152
2153		TAILQ_INSERT_HEAD(al, h, entry);
2154		cnt++;
2155	}
2156	if (cnt == max && res) {
2157		log_warnx("%s: %s resolves to more than %d hosts", __func__,
2158		    s, max);
2159	}
2160	freeaddrinfo(res0);
2161	return (cnt);
2162}
2163
2164int
2165host_if(const char *s, struct addresslist *al, int max,
2166    struct portrange *port, const char *ifname, int ipproto)
2167{
2168	struct ifaddrs		*ifap, *p;
2169	struct sockaddr_in	*sain;
2170	struct sockaddr_in6	*sin6;
2171	struct address		*h;
2172	int			 cnt = 0, af;
2173
2174	if (getifaddrs(&ifap) == -1)
2175		fatal("getifaddrs");
2176
2177	/* First search for IPv4 addresses */
2178	af = AF_INET;
2179
2180 nextaf:
2181	for (p = ifap; p != NULL && cnt < max; p = p->ifa_next) {
2182		if (p->ifa_addr == NULL ||
2183		    p->ifa_addr->sa_family != af ||
2184		    (strcmp(s, p->ifa_name) != 0 &&
2185		    !is_if_in_group(p->ifa_name, s)))
2186			continue;
2187		if ((h = calloc(1, sizeof(*h))) == NULL)
2188			fatal("calloc");
2189
2190		if (port != NULL)
2191			memcpy(&h->port, port, sizeof(h->port));
2192		if (ifname != NULL) {
2193			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
2194			    sizeof(h->ifname))
2195				log_warnx("%s: interface name truncated",
2196				    __func__);
2197			freeifaddrs(ifap);
2198			free(h);
2199			return (-1);
2200		}
2201		if (ipproto != -1)
2202			h->ipproto = ipproto;
2203		h->ss.ss_family = af;
2204		h->prefixlen = -1; /* host address */
2205
2206		if (af == AF_INET) {
2207			sain = (struct sockaddr_in *)&h->ss;
2208			sain->sin_len = sizeof(struct sockaddr_in);
2209			sain->sin_addr.s_addr = ((struct sockaddr_in *)
2210			    p->ifa_addr)->sin_addr.s_addr;
2211		} else {
2212			sin6 = (struct sockaddr_in6 *)&h->ss;
2213			sin6->sin6_len = sizeof(struct sockaddr_in6);
2214			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
2215			    p->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
2216			sin6->sin6_scope_id = ((struct sockaddr_in6 *)
2217			    p->ifa_addr)->sin6_scope_id;
2218		}
2219
2220		TAILQ_INSERT_HEAD(al, h, entry);
2221		cnt++;
2222	}
2223	if (af == AF_INET) {
2224		/* Next search for IPv6 addresses */
2225		af = AF_INET6;
2226		goto nextaf;
2227	}
2228
2229	if (cnt > max) {
2230		log_warnx("%s: %s resolves to more than %d hosts", __func__,
2231		    s, max);
2232	}
2233	freeifaddrs(ifap);
2234	return (cnt);
2235}
2236
2237int
2238host(const char *s, struct addresslist *al, int max,
2239    struct portrange *port, const char *ifname, int ipproto)
2240{
2241	struct address *h;
2242
2243	h = host_v4(s);
2244
2245	/* IPv6 address? */
2246	if (h == NULL)
2247		h = host_v6(s);
2248
2249	if (h != NULL) {
2250		if (port != NULL)
2251			memcpy(&h->port, port, sizeof(h->port));
2252		if (ifname != NULL) {
2253			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
2254			    sizeof(h->ifname)) {
2255				log_warnx("%s: interface name truncated",
2256				    __func__);
2257				free(h);
2258				return (-1);
2259			}
2260		}
2261		if (ipproto != -1)
2262			h->ipproto = ipproto;
2263
2264		TAILQ_INSERT_HEAD(al, h, entry);
2265		return (1);
2266	}
2267
2268	return (host_dns(s, al, max, port, ifname, ipproto));
2269}
2270
2271struct server *
2272server_inherit(struct server *src, struct server_config *alias,
2273    struct server_config *addr)
2274{
2275	struct server	*dst, *s, *dstl;
2276
2277	if ((dst = calloc(1, sizeof(*dst))) == NULL)
2278		fatal("out of memory");
2279
2280	/* Copy the source server and assign a new Id */
2281	memcpy(&dst->srv_conf, &src->srv_conf, sizeof(dst->srv_conf));
2282	if ((dst->srv_conf.tls_cert_file =
2283	    strdup(src->srv_conf.tls_cert_file)) == NULL)
2284		fatal("out of memory");
2285	if ((dst->srv_conf.tls_key_file =
2286	    strdup(src->srv_conf.tls_key_file)) == NULL)
2287		fatal("out of memory");
2288	if (src->srv_conf.tls_ocsp_staple_file != NULL) {
2289		if ((dst->srv_conf.tls_ocsp_staple_file =
2290		    strdup(src->srv_conf.tls_ocsp_staple_file)) == NULL)
2291			fatal("out of memory");
2292	}
2293
2294	if (src->srv_conf.return_uri != NULL &&
2295	    (dst->srv_conf.return_uri =
2296	    strdup(src->srv_conf.return_uri)) == NULL)
2297		fatal("out of memory");
2298
2299	dst->srv_conf.id = ++last_server_id;
2300	dst->srv_conf.parent_id = dst->srv_conf.id;
2301	dst->srv_s = -1;
2302
2303	if (last_server_id == INT_MAX) {
2304		yyerror("too many servers defined");
2305		serverconfig_free(&dst->srv_conf);
2306		free(dst);
2307		return (NULL);
2308	}
2309
2310	/* Now set alias and listen address */
2311	strlcpy(dst->srv_conf.name, alias->name, sizeof(dst->srv_conf.name));
2312	memcpy(&dst->srv_conf.ss, &addr->ss, sizeof(dst->srv_conf.ss));
2313	dst->srv_conf.port = addr->port;
2314	dst->srv_conf.prefixlen = addr->prefixlen;
2315	if (addr->flags & SRVFLAG_TLS)
2316		dst->srv_conf.flags |= SRVFLAG_TLS;
2317	else
2318		dst->srv_conf.flags &= ~SRVFLAG_TLS;
2319
2320	/* Don't inherit the "match" option, use it from the alias */
2321	dst->srv_conf.flags &= ~SRVFLAG_SERVER_MATCH;
2322	dst->srv_conf.flags |= (alias->flags & SRVFLAG_SERVER_MATCH);
2323
2324	if (server_tls_load_keypair(dst) == -1)
2325		log_warnx("%s:%d: server \"%s\": failed to "
2326		    "load public/private keys", file->name,
2327		    yylval.lineno, dst->srv_conf.name);
2328
2329	if (server_tls_load_ca(dst) == -1) {
2330		yyerror("failed to load ca cert(s) for server %s",
2331		    dst->srv_conf.name);
2332		serverconfig_free(&dst->srv_conf);
2333		return NULL;
2334	}
2335
2336	if (server_tls_load_crl(dst) == -1) {
2337		yyerror("failed to load crl(s) for server %s",
2338		    dst->srv_conf.name);
2339		serverconfig_free(&dst->srv_conf);
2340		free(dst);
2341		return NULL;
2342	}
2343
2344	if (server_tls_load_ocsp(dst) == -1) {
2345		yyerror("failed to load ocsp staple "
2346		    "for server %s", dst->srv_conf.name);
2347		serverconfig_free(&dst->srv_conf);
2348		free(dst);
2349		return (NULL);
2350	}
2351
2352	/* Check if the new server already exists */
2353	if (server_match(dst, 1) != NULL) {
2354		yyerror("server \"%s\" defined twice",
2355		    dst->srv_conf.name);
2356		serverconfig_free(&dst->srv_conf);
2357		free(dst);
2358		return (NULL);
2359	}
2360
2361	/* Copy all the locations of the source server */
2362	TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
2363		if (!(s->srv_conf.flags & SRVFLAG_LOCATION &&
2364		    s->srv_conf.parent_id == src->srv_conf.parent_id))
2365			continue;
2366
2367		if ((dstl = calloc(1, sizeof(*dstl))) == NULL)
2368			fatal("out of memory");
2369
2370		memcpy(&dstl->srv_conf, &s->srv_conf, sizeof(dstl->srv_conf));
2371		strlcpy(dstl->srv_conf.name, alias->name,
2372		    sizeof(dstl->srv_conf.name));
2373
2374		/* Copy the new Id and listen address */
2375		dstl->srv_conf.id = ++last_server_id;
2376		dstl->srv_conf.parent_id = dst->srv_conf.id;
2377		memcpy(&dstl->srv_conf.ss, &addr->ss,
2378		    sizeof(dstl->srv_conf.ss));
2379		dstl->srv_conf.port = addr->port;
2380		dstl->srv_conf.prefixlen = addr->prefixlen;
2381		dstl->srv_s = -1;
2382
2383		DPRINTF("adding location \"%s\" for \"%s[%u]\"",
2384		    dstl->srv_conf.location,
2385		    dstl->srv_conf.name, dstl->srv_conf.id);
2386
2387		TAILQ_INSERT_TAIL(conf->sc_servers, dstl, srv_entry);
2388	}
2389
2390	return (dst);
2391}
2392
2393int
2394listen_on(const char *addr, int tls, struct portrange *port)
2395{
2396	struct addresslist	 al;
2397	struct address		*h;
2398	struct server_config	*s_conf, *alias = NULL;
2399
2400	if (parentsrv != NULL) {
2401		yyerror("listen %s inside location", addr);
2402		return (-1);
2403	}
2404
2405	TAILQ_INIT(&al);
2406	if (strcmp("*", addr) == 0) {
2407		if (host("0.0.0.0", &al, 1, port, NULL, -1) <= 0) {
2408			yyerror("invalid listen ip: %s",
2409			    "0.0.0.0");
2410			return (-1);
2411		}
2412		if (host("::", &al, 1, port, NULL, -1) <= 0) {
2413			yyerror("invalid listen ip: %s", "::");
2414			return (-1);
2415		}
2416	} else {
2417		if (host(addr, &al, HTTPD_MAX_ALIAS_IP, port, NULL,
2418		    -1) <= 0) {
2419			yyerror("invalid listen ip: %s", addr);
2420			return (-1);
2421		}
2422	}
2423
2424	while ((h = TAILQ_FIRST(&al)) != NULL) {
2425		if (srv->srv_conf.ss.ss_family != AF_UNSPEC) {
2426			if ((alias = calloc(1,
2427			    sizeof(*alias))) == NULL)
2428				fatal("out of memory");
2429				/* Add as an IP-based alias. */
2430			s_conf = alias;
2431		} else
2432			s_conf = &srv->srv_conf;
2433		memcpy(&s_conf->ss, &h->ss, sizeof(s_conf->ss));
2434		s_conf->prefixlen = h->prefixlen;
2435		/* Set the default port to 80 or 443 */
2436		if (!h->port.op)
2437			s_conf->port = htons(tls ?
2438			    HTTPS_PORT : HTTP_PORT);
2439		else
2440			s_conf->port = h->port.val[0];
2441
2442		if (tls)
2443			s_conf->flags |= SRVFLAG_TLS;
2444
2445		if (alias != NULL) {
2446			/*
2447			 * IP-based; use name match flags from
2448			 * parent
2449			 */
2450			alias->flags &= ~SRVFLAG_SERVER_MATCH;
2451			alias->flags |= srv->srv_conf.flags &
2452			    SRVFLAG_SERVER_MATCH;
2453			TAILQ_INSERT_TAIL(&srv->srv_hosts,
2454			    alias, entry);
2455		}
2456		TAILQ_REMOVE(&al, h, entry);
2457		free(h);
2458	}
2459
2460	return (0);
2461}
2462
2463int
2464getservice(char *n)
2465{
2466	struct servent	*s;
2467	const char	*errstr;
2468	long long	 llval;
2469
2470	llval = strtonum(n, 0, UINT16_MAX, &errstr);
2471	if (errstr) {
2472		s = getservbyname(n, "tcp");
2473		if (s == NULL)
2474			s = getservbyname(n, "udp");
2475		if (s == NULL)
2476			return (-1);
2477		return (s->s_port);
2478	}
2479
2480	return (htons((unsigned short)llval));
2481}
2482
2483int
2484is_if_in_group(const char *ifname, const char *groupname)
2485{
2486	unsigned int		 len;
2487	struct ifgroupreq	 ifgr;
2488	struct ifg_req		*ifg;
2489	int			 s;
2490	int			 ret = 0;
2491
2492	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2493		err(1, "socket");
2494
2495	memset(&ifgr, 0, sizeof(ifgr));
2496	if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ)
2497		err(1, "IFNAMSIZ");
2498	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
2499		if (errno == EINVAL || errno == ENOTTY)
2500			goto end;
2501		err(1, "SIOCGIFGROUP");
2502	}
2503
2504	len = ifgr.ifgr_len;
2505	ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req),
2506	    sizeof(struct ifg_req));
2507	if (ifgr.ifgr_groups == NULL)
2508		err(1, "getifgroups");
2509	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
2510		err(1, "SIOCGIFGROUP");
2511
2512	ifg = ifgr.ifgr_groups;
2513	for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
2514		len -= sizeof(struct ifg_req);
2515		if (strcmp(ifg->ifgrq_group, groupname) == 0) {
2516			ret = 1;
2517			break;
2518		}
2519	}
2520	free(ifgr.ifgr_groups);
2521
2522end:
2523	close(s);
2524	return (ret);
2525}
2526
2527int
2528get_fastcgi_dest(struct server_config *xsrv_conf, const char *node, char *port)
2529{
2530	struct addrinfo		 hints, *res;
2531	int			 s;
2532
2533	memset(&hints, 0, sizeof(hints));
2534	hints.ai_family = AF_UNSPEC;
2535	hints.ai_socktype = SOCK_STREAM;
2536
2537	if ((s = getaddrinfo(node, port, &hints, &res)) != 0) {
2538		yyerror("getaddrinfo: %s\n", gai_strerror(s));
2539		return -1;
2540	}
2541
2542	memset(&(xsrv_conf)->fastcgi_ss, 0, sizeof(xsrv_conf->fastcgi_ss));
2543	memcpy(&(xsrv_conf)->fastcgi_ss, res->ai_addr, res->ai_addrlen);
2544
2545	freeaddrinfo(res);
2546
2547	return (0);
2548}
2549
2550void
2551remove_locations(struct server_config *xsrv_conf)
2552{
2553	struct server *s, *next;
2554
2555	TAILQ_FOREACH_SAFE(s, conf->sc_servers, srv_entry, next) {
2556		if (!(s->srv_conf.flags & SRVFLAG_LOCATION &&
2557		    s->srv_conf.parent_id == xsrv_conf->parent_id))
2558			continue;
2559		TAILQ_REMOVE(conf->sc_servers, s, srv_entry);
2560		serverconfig_free(&s->srv_conf);
2561		free(s);
2562	}
2563}
2564