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
59 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
60 static 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;
71 struct file *pushfile(const char *, int);
72 int popfile(void);
73 int check_file_secrecy(int, const char *);
74 int yyparse(void);
75 int yylex(void);
76 int yyerror(const char *, ...)
77 __attribute__((__format__ (printf, 1, 2)))
78 __attribute__((__nonnull__ (1)));
79 int kw_cmp(const void *, const void *);
80 int lookup(char *);
81 int igetc(void);
82 int lgetc(int);
83 void lungetc(int);
84 int findeol(void);
85
86 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
87 struct sym {
88 TAILQ_ENTRY(sym) entry;
89 int used;
90 int persist;
91 char *nam;
92 char *val;
93 };
94 int symset(const char *, const char *, int);
95 char *symget(const char *);
96
97 struct httpd *conf = NULL;
98 static int errors = 0;
99 static int loadcfg = 0;
100 uint32_t last_server_id = 0;
101 uint32_t last_auth_id = 0;
102
103 static struct server *srv = NULL, *parentsrv = NULL;
104 static struct server_config *srv_conf = NULL;
105 struct serverlist servers;
106 struct media_type media;
107
108 struct address *host_v4(const char *);
109 struct address *host_v6(const char *);
110 int host_dns(const char *, struct addresslist *,
111 int, struct portrange *, const char *, int);
112 int host_if(const char *, struct addresslist *,
113 int, struct portrange *, const char *, int);
114 int host(const char *, struct addresslist *,
115 int, struct portrange *, const char *, int);
116 struct server *server_inherit(struct server *, struct server_config *,
117 struct server_config *);
118 int listen_on(const char *, int, struct portrange *);
119 int getservice(char *);
120 int is_if_in_group(const char *, const char *);
121 int get_fastcgi_dest(struct server_config *, const char *, char *);
122 void remove_locations(struct server_config *);
123
124 typedef 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
156 grammar : /* 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
166 include : 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
181 varset : 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
199 opttls : /*empty*/ { $$ = 0; }
200 | TLS { $$ = 1; }
201 ;
202
203 main : 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
236 server : 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
461 serveropts_l : serveropts_l serveroptsl nl
462 | serveroptsl optnl
463 ;
464
465 serveroptsl : 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
690 optfound : /* empty */ { $$ = 0; }
691 | FOUND { $$ = 1; }
692 | NOT FOUND { $$ = -1; }
693 ;
694
695 hsts : HSTS '{' optnl hstsflags_l '}'
696 | HSTS hstsflags
697 | HSTS
698 ;
699
700 hstsflags_l : hstsflags optcommanl hstsflags_l
701 | hstsflags optnl
702 ;
703
704 hstsflags : 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
719 fastcgi : 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
737 fcgiflags_l : fcgiflags optcommanl fcgiflags_l
738 | fcgiflags optnl
739 ;
740
741 fcgiflags : 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
812 connection : CONNECTION '{' optnl conflags_l '}'
813 | CONNECTION conflags
814 ;
815
816 conflags_l : conflags optcommanl conflags_l
817 | conflags optnl
818 ;
819
820 conflags : 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
836 tls : TLS '{' optnl tlsopts_l '}'
837 | TLS tlsopts
838 ;
839
840 tlsopts_l : tlsopts optcommanl tlsopts_l
841 | tlsopts optnl
842 ;
843
844 tlsopts : 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
928 tlsclientopt : /* 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 ;
940 root : ROOT rootflags
941 | ROOT '{' optnl rootflags_l '}'
942 ;
943
944 rootflags_l : rootflags optcommanl rootflags_l
945 | rootflags optnl
946 ;
947
948 rootflags : 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
961 request : REQUEST requestflags
962 | REQUEST '{' optnl requestflags_l '}'
963 ;
964
965 requestflags_l : requestflags optcommanl requestflags_l
966 | requestflags optnl
967 ;
968
969 requestflags : 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
994 authenticate : 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
1020 authopts : 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
1050 directory : DIRECTORY dirflags
1051 | DIRECTORY '{' optnl dirflags_l '}'
1052 ;
1053
1054 dirflags_l : dirflags optcommanl dirflags_l
1055 | dirflags optnl
1056 ;
1057
1058 dirflags : 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
1085 logformat : 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
1093 logflags_l : logflags optcommanl logflags_l
1094 | logflags optnl
1095 ;
1096
1097 logflags : 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
1130 logstyle : 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
1152 filter : 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
1186 block : BLOCK {
1187 srv_conf->flags &= ~SRVFLAG_NO_BLOCK;
1188 srv_conf->flags |= SRVFLAG_BLOCK;
1189 }
1190 ;
1191
1192 optmatch : /* empty */ { $$ = 0; }
1193 | MATCH { $$ = 1; }
1194 ;
1195
1196 optstring : /* empty */ { $$ = NULL; }
1197 | STRING { $$ = $1; }
1198 ;
1199
1200 fcgiport : 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
1221 gzip_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
1229 tcpip : TCP '{' optnl tcpflags_l '}'
1230 | TCP tcpflags
1231 ;
1232
1233 tcpflags_l : tcpflags optcommanl tcpflags_l
1234 | tcpflags optnl
1235 ;
1236
1237 tcpflags : 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
1280 types : TYPES '{' optnl mediaopts_l '}'
1281 ;
1282
1283 mediaopts_l : mediaopts_l mediaoptsl nl
1284 | mediaoptsl nl
1285 ;
1286
1287 mediaoptsl : mediastring medianames_l optsemicolon
1288 | include
1289 ;
1290
1291 mediastring : 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
1308 medianames_l : medianames_l medianamesl
1309 | medianamesl
1310 ;
1311
1312 medianamesl : 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
1332 port : 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
1355 timeout : 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
1366 numberstring : 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
1377 optsemicolon : ';'
1378 |
1379 ;
1380
1381 optnl : '\n' optnl
1382 |
1383 ;
1384
1385 optcommanl : ',' optnl
1386 | nl
1387 ;
1388
1389 nl : '\n' optnl
1390 ;
1391
1392 %%
1393
1394 struct keywords {
1395 const char *k_name;
1396 int k_val;
1397 };
1398
1399 int
yyerror(const char * fmt,...)1400 yyerror(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
1415 int
kw_cmp(const void * k,const void * e)1416 kw_cmp(const void *k, const void *e)
1417 {
1418 return (strcmp(k, ((const struct keywords *)e)->k_name));
1419 }
1420
1421 int
lookup(char * s)1422 lookup(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
1513 static int expanding;
1514
1515 int
igetc(void)1516 igetc(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
1536 int
lgetc(int quotec)1537 lgetc(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
1581 void
lungetc(int c)1582 lungetc(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
1597 int
findeol(void)1598 findeol(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
1615 int
yylex(void)1616 yylex(void)
1617 {
1618 char buf[8096];
1619 char *p, *val;
1620 int quotec, next, c;
1621 int token;
1622
1623 top:
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 {
1731 nodigits:
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
1770 int
check_file_secrecy(int fd,const char * fname)1771 check_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
1790 struct file *
pushfile(const char * name,int secret)1791 pushfile(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
1830 int
popfile(void)1831 popfile(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
1847 int
parse_config(const char * filename,struct httpd * x_conf)1848 parse_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
1891 int
load_config(const char * filename,struct httpd * x_conf)1892 load_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
1964 int
symset(const char * nam,const char * val,int persist)1965 symset(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
2004 int
cmdline_symset(char * s)2005 cmdline_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
2021 char *
symget(const char * nam)2022 symget(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
2035 struct address *
host_v4(const char * s)2036 host_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
2059 struct address *
host_v6(const char * s)2060 host_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
2092 int
host_dns(const char * s,struct addresslist * al,int max,struct portrange * port,const char * ifname,int ipproto)2093 host_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
2164 int
host_if(const char * s,struct addresslist * al,int max,struct portrange * port,const char * ifname,int ipproto)2165 host_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
2237 int
host(const char * s,struct addresslist * al,int max,struct portrange * port,const char * ifname,int ipproto)2238 host(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
2271 struct server *
server_inherit(struct server * src,struct server_config * alias,struct server_config * addr)2272 server_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
2393 int
listen_on(const char * addr,int tls,struct portrange * port)2394 listen_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
2463 int
getservice(char * n)2464 getservice(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
2483 int
is_if_in_group(const char * ifname,const char * groupname)2484 is_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
2522 end:
2523 close(s);
2524 return (ret);
2525 }
2526
2527 int
get_fastcgi_dest(struct server_config * xsrv_conf,const char * node,char * port)2528 get_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
2550 void
remove_locations(struct server_config * xsrv_conf)2551 remove_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