xref: /openbsd-src/usr.sbin/smtpd/parse.y (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: parse.y,v 1.190 2016/09/12 07:33:00 eric Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
7  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
8  * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
9  * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
10  *
11  * Permission to use, copy, modify, and distribute this software for any
12  * purpose with or without fee is hereby granted, provided that the above
13  * copyright notice and this permission notice appear in all copies.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23 
24 %{
25 #include <sys/types.h>
26 #include <sys/queue.h>
27 #include <sys/tree.h>
28 #include <sys/socket.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 
32 #include <net/if.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 
36 #include <ctype.h>
37 #include <err.h>
38 #include <errno.h>
39 #include <event.h>
40 #include <ifaddrs.h>
41 #include <imsg.h>
42 #include <inttypes.h>
43 #include <limits.h>
44 #include <netdb.h>
45 #include <paths.h>
46 #include <pwd.h>
47 #include <resolv.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <syslog.h>
52 #include <unistd.h>
53 #include <util.h>
54 
55 #include <openssl/ssl.h>
56 
57 #include "smtpd.h"
58 #include "ssl.h"
59 #include "log.h"
60 
61 TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
62 static struct file {
63 	TAILQ_ENTRY(file)	 entry;
64 	FILE			*stream;
65 	char			*name;
66 	int			 lineno;
67 	int			 errors;
68 } *file, *topfile;
69 struct file	*pushfile(const char *, int);
70 int		 popfile(void);
71 int		 check_file_secrecy(int, const char *);
72 int		 yyparse(void);
73 int		 yylex(void);
74 int		 kw_cmp(const void *, const void *);
75 int		 lookup(char *);
76 int		 lgetc(int);
77 int		 lungetc(int);
78 int		 findeol(void);
79 int		 yyerror(const char *, ...)
80     __attribute__((__format__ (printf, 1, 2)))
81     __attribute__((__nonnull__ (1)));
82 
83 TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
84 struct sym {
85 	TAILQ_ENTRY(sym)	 entry;
86 	int			 used;
87 	int			 persist;
88 	char			*nam;
89 	char			*val;
90 };
91 int		 symset(const char *, const char *, int);
92 char		*symget(const char *);
93 
94 struct smtpd		*conf = NULL;
95 static int		 errors = 0;
96 
97 struct filter_conf	*filter = NULL;
98 struct table		*table = NULL;
99 struct rule		*rule = NULL;
100 struct mta_limits	*limits;
101 static struct pki	*pki;
102 static struct ca	*sca;
103 
104 enum listen_options {
105 	LO_FAMILY	= 0x000001,
106 	LO_PORT		= 0x000002,
107 	LO_SSL		= 0x000004,
108 	LO_FILTER      	= 0x000008,
109 	LO_PKI      	= 0x000010,
110 	LO_AUTH      	= 0x000020,
111 	LO_TAG      	= 0x000040,
112 	LO_HOSTNAME   	= 0x000080,
113 	LO_HOSTNAMES   	= 0x000100,
114 	LO_MASKSOURCE  	= 0x000200,
115 	LO_NODSN	= 0x000400,
116 	LO_SENDERS	= 0x000800,
117 	LO_RECEIVEDAUTH = 0x001000,
118 	LO_MASQUERADE	= 0x002000,
119 	LO_CA		= 0x010000
120 };
121 
122 static struct listen_opts {
123 	char	       *ifx;
124 	int		family;
125 	in_port_t	port;
126 	uint16_t	ssl;
127 	char	       *filtername;
128 	char	       *pki;
129 	char	       *ca;
130 	uint16_t       	auth;
131 	struct table   *authtable;
132 	char	       *tag;
133 	char	       *hostname;
134 	struct table   *hostnametable;
135 	struct table   *sendertable;
136 	uint16_t	flags;
137 
138 	uint32_t       	options;
139 } listen_opts;
140 
141 static void	create_sock_listener(struct listen_opts *);
142 static void	create_if_listener(struct listen_opts *);
143 static void	config_listener(struct listener *, struct listen_opts *);
144 static int	host_v4(struct listen_opts *);
145 static int	host_v6(struct listen_opts *);
146 static int	host_dns(struct listen_opts *);
147 static int	interface(struct listen_opts *);
148 
149 void		 set_local(const char *);
150 void		 set_localaddrs(struct table *);
151 int		 delaytonum(char *);
152 int		 is_if_in_group(const char *, const char *);
153 
154 static struct filter_conf *create_filter_proc(char *, char *);
155 static struct filter_conf *create_filter_chain(char *);
156 static int add_filter_arg(struct filter_conf *, char *);
157 
158 static int config_lo_filter(struct listen_opts *, char *);
159 static int config_lo_mask_source(struct listen_opts *);
160 
161 typedef struct {
162 	union {
163 		int64_t		 number;
164 		struct table	*table;
165 		char		*string;
166 		struct host	*host;
167 		struct mailaddr	*maddr;
168 	} v;
169 	int lineno;
170 } YYSTYPE;
171 
172 %}
173 
174 %token	AS QUEUE COMPRESSION ENCRYPTION MAXMESSAGESIZE MAXMTADEFERRED LISTEN ON ANY PORT EXPIRE
175 %token	TABLE SECURE SMTPS CERTIFICATE DOMAIN BOUNCEWARN LIMIT INET4 INET6 NODSN SESSION
176 %token  RELAY BACKUP VIA DELIVER TO LMTP MAILDIR MBOX RCPTTO HOSTNAME HOSTNAMES
177 %token	ACCEPT REJECT INCLUDE ERROR MDA FROM FOR SOURCE MTA PKI SCHEDULER
178 %token	ARROW AUTH TLS LOCAL VIRTUAL TAG TAGGED ALIAS FILTER KEY CA DHE
179 %token	AUTH_OPTIONAL TLS_REQUIRE USERBASE SENDER SENDERS MASK_SOURCE VERIFY FORWARDONLY RECIPIENT
180 %token	CIPHERS RECEIVEDAUTH MASQUERADE SOCKET SUBADDRESSING_DELIM AUTHENTICATED
181 %token	<v.string>	STRING
182 %token  <v.number>	NUMBER
183 %type	<v.table>	table
184 %type	<v.number>	size negation
185 %type	<v.table>	tables tablenew tableref alias virtual userbase
186 %type	<v.string>	tagged
187 %%
188 
189 grammar		: /* empty */
190 		| grammar '\n'
191 		| grammar include '\n'
192 		| grammar varset '\n'
193 		| grammar main '\n'
194 		| grammar table '\n'
195 		| grammar rule '\n'
196 		| grammar error '\n'		{ file->errors++; }
197 		;
198 
199 include		: INCLUDE STRING		{
200 			struct file	*nfile;
201 
202 			if ((nfile = pushfile($2, 0)) == NULL) {
203 				yyerror("failed to include file %s", $2);
204 				free($2);
205 				YYERROR;
206 			}
207 			free($2);
208 
209 			file = nfile;
210 			lungetc('\n');
211 		}
212 		;
213 
214 varset		: STRING '=' STRING		{
215 			char *s = $1;
216 			while (*s++) {
217 				if (isspace((unsigned char)*s)) {
218 					yyerror("macro name cannot contain "
219 					    "whitespace");
220 					YYERROR;
221 				}
222 			}
223 			if (symset($1, $3, 0) == -1)
224 				fatal("cannot store variable");
225 			free($1);
226 			free($3);
227 		}
228 		;
229 
230 comma		: ','
231 		| nl
232 		| /* empty */
233 		;
234 
235 optnl		: '\n' optnl
236 		|
237 		;
238 
239 nl		: '\n' optnl
240 		;
241 
242 size		: NUMBER		{
243 			if ($1 < 0) {
244 				yyerror("invalid size: %" PRId64, $1);
245 				YYERROR;
246 			}
247 			$$ = $1;
248 		}
249 		| STRING			{
250 			long long result;
251 
252 			if (scan_scaled($1, &result) == -1 || result < 0) {
253 				yyerror("invalid size: %s", $1);
254 				free($1);
255 				YYERROR;
256 			}
257 			free($1);
258 			$$ = result;
259 		}
260 		;
261 
262 tagged		: TAGGED negation STRING       		{
263 			if (strlcpy(rule->r_tag, $3, sizeof rule->r_tag)
264 			    >= sizeof rule->r_tag) {
265 				yyerror("tag name too long: %s", $3);
266 				free($3);
267 				YYERROR;
268 			}
269 			free($3);
270 			rule->r_nottag = $2;
271 		}
272 		;
273 
274 authenticated  	: AUTHENTICATED	{
275 			rule->r_wantauth = 1;
276 		}
277 		;
278 
279 bouncedelay	: STRING {
280 			time_t	d;
281 			int	i;
282 
283 			d = delaytonum($1);
284 			if (d < 0) {
285 				yyerror("invalid bounce delay: %s", $1);
286 				free($1);
287 				YYERROR;
288 			}
289 			free($1);
290 			for (i = 0; i < MAX_BOUNCE_WARN; i++) {
291 				if (conf->sc_bounce_warn[i] != 0)
292 					continue;
293 				conf->sc_bounce_warn[i] = d;
294 				break;
295 			}
296 		}
297 
298 bouncedelays	: bouncedelays ',' bouncedelay
299 		| bouncedelay
300 		| /* EMPTY */
301 		;
302 
303 opt_limit_mda	: STRING NUMBER {
304 			if (!strcmp($1, "max-session")) {
305 				conf->sc_mda_max_session = $2;
306 			}
307 			else if (!strcmp($1, "max-session-per-user")) {
308 				conf->sc_mda_max_user_session = $2;
309 			}
310 			else if (!strcmp($1, "task-lowat")) {
311 				conf->sc_mda_task_lowat = $2;
312 			}
313 			else if (!strcmp($1, "task-hiwat")) {
314 				conf->sc_mda_task_hiwat = $2;
315 			}
316 			else if (!strcmp($1, "task-release")) {
317 				conf->sc_mda_task_release = $2;
318 			}
319 			else {
320 				yyerror("invalid scheduler limit keyword: %s", $1);
321 				free($1);
322 				YYERROR;
323 			}
324 			free($1);
325 		}
326 		;
327 
328 limits_session	: opt_limit_session limits_session
329 		| /* empty */
330 		;
331 
332 opt_limit_session : STRING NUMBER {
333 			if (!strcmp($1, "max-rcpt")) {
334 				conf->sc_session_max_rcpt = $2;
335 			}
336 			else if (!strcmp($1, "max-mails")) {
337 				conf->sc_session_max_mails = $2;
338 			}
339 			else {
340 				yyerror("invalid session limit keyword: %s", $1);
341 				free($1);
342 				YYERROR;
343 			}
344 			free($1);
345 		}
346 		;
347 
348 limits_mda	: opt_limit_mda limits_mda
349 		| /* empty */
350 		;
351 
352 opt_limit_mta	: INET4 {
353 			limits->family = AF_INET;
354 		}
355 		| INET6 {
356 			limits->family = AF_INET6;
357 		}
358 		| STRING NUMBER {
359 			if (!limit_mta_set(limits, $1, $2)) {
360 				yyerror("invalid mta limit keyword: %s", $1);
361 				free($1);
362 				YYERROR;
363 			}
364 			free($1);
365 		}
366 		;
367 
368 limits_mta	: opt_limit_mta limits_mta
369 		| /* empty */
370 		;
371 
372 opt_limit_scheduler : STRING NUMBER {
373 			if (!strcmp($1, "max-inflight")) {
374 				conf->sc_scheduler_max_inflight = $2;
375 			}
376 			else if (!strcmp($1, "max-evp-batch-size")) {
377 				conf->sc_scheduler_max_evp_batch_size = $2;
378 			}
379 			else if (!strcmp($1, "max-msg-batch-size")) {
380 				conf->sc_scheduler_max_msg_batch_size = $2;
381 			}
382 			else if (!strcmp($1, "max-schedule")) {
383 				conf->sc_scheduler_max_schedule = $2;
384 			}
385 			else {
386 				yyerror("invalid scheduler limit keyword: %s", $1);
387 				free($1);
388 				YYERROR;
389 			}
390 			free($1);
391 		}
392 		;
393 
394 limits_scheduler: opt_limit_scheduler limits_scheduler
395 		| /* empty */
396 		;
397 
398 opt_ca		: CERTIFICATE STRING {
399 			sca->ca_cert_file = $2;
400 		}
401 		;
402 
403 ca		: opt_ca
404 		;
405 
406 opt_pki		: CERTIFICATE STRING {
407 			pki->pki_cert_file = $2;
408 		}
409 		| KEY STRING {
410 			pki->pki_key_file = $2;
411 		}
412 		| DHE STRING {
413 			if (strcasecmp($2, "none") == 0)
414 				pki->pki_dhe = 0;
415 			else if (strcasecmp($2, "auto") == 0)
416 				pki->pki_dhe = 1;
417 			else if (strcasecmp($2, "legacy") == 0)
418 				pki->pki_dhe = 2;
419 			else {
420 				yyerror("invalid DHE keyword: %s", $2);
421 				free($2);
422 				YYERROR;
423 			}
424 			free($2);
425 		}
426 		;
427 
428 pki		: opt_pki pki
429 		| /* empty */
430 		;
431 
432 opt_sock_listen : FILTER STRING {
433 			if (config_lo_filter(&listen_opts, $2)) {
434 				YYERROR;
435 			}
436 		}
437 		| MASK_SOURCE {
438 			if (config_lo_mask_source(&listen_opts)) {
439 				YYERROR;
440 			}
441 		}
442 		;
443 
444 opt_if_listen : INET4 {
445 			if (listen_opts.options & LO_FAMILY) {
446 				yyerror("address family already specified");
447 				YYERROR;
448 			}
449 			listen_opts.options |= LO_FAMILY;
450 			listen_opts.family = AF_INET;
451 		}
452 		| INET6			{
453 			if (listen_opts.options & LO_FAMILY) {
454 				yyerror("address family already specified");
455 				YYERROR;
456 			}
457 			listen_opts.options |= LO_FAMILY;
458 			listen_opts.family = AF_INET6;
459 		}
460 		| PORT STRING			{
461 			struct servent	*servent;
462 
463 			if (listen_opts.options & LO_PORT) {
464 				yyerror("port already specified");
465 				YYERROR;
466 			}
467 			listen_opts.options |= LO_PORT;
468 
469 			servent = getservbyname($2, "tcp");
470 			if (servent == NULL) {
471 				yyerror("invalid port: %s", $2);
472 				free($2);
473 				YYERROR;
474 			}
475 			free($2);
476 			listen_opts.port = ntohs(servent->s_port);
477 		}
478 		| PORT NUMBER			{
479 			if (listen_opts.options & LO_PORT) {
480 				yyerror("port already specified");
481 				YYERROR;
482 			}
483 			listen_opts.options |= LO_PORT;
484 
485 			if ($2 <= 0 || $2 >= (int)USHRT_MAX) {
486 				yyerror("invalid port: %" PRId64, $2);
487 				YYERROR;
488 			}
489 			listen_opts.port = $2;
490 		}
491 		| FILTER STRING			{
492 			if (config_lo_filter(&listen_opts, $2)) {
493 				YYERROR;
494 			}
495 		}
496 		| SMTPS				{
497 			if (listen_opts.options & LO_SSL) {
498 				yyerror("TLS mode already specified");
499 				YYERROR;
500 			}
501 			listen_opts.options |= LO_SSL;
502 			listen_opts.ssl = F_SMTPS;
503 		}
504 		| SMTPS VERIFY 			{
505 			if (listen_opts.options & LO_SSL) {
506 				yyerror("TLS mode already specified");
507 				YYERROR;
508 			}
509 			listen_opts.options |= LO_SSL;
510 			listen_opts.ssl = F_SMTPS|F_TLS_VERIFY;
511 		}
512 		| TLS				{
513 			if (listen_opts.options & LO_SSL) {
514 				yyerror("TLS mode already specified");
515 				YYERROR;
516 			}
517 			listen_opts.options |= LO_SSL;
518 			listen_opts.ssl = F_STARTTLS;
519 		}
520 		| SECURE       			{
521 			if (listen_opts.options & LO_SSL) {
522 				yyerror("TLS mode already specified");
523 				YYERROR;
524 			}
525 			listen_opts.options |= LO_SSL;
526 			listen_opts.ssl = F_SSL;
527 		}
528 		| TLS_REQUIRE			{
529 			if (listen_opts.options & LO_SSL) {
530 				yyerror("TLS mode already specified");
531 				YYERROR;
532 			}
533 			listen_opts.options |= LO_SSL;
534 			listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE;
535 		}
536 		| TLS_REQUIRE VERIFY   		{
537 			if (listen_opts.options & LO_SSL) {
538 				yyerror("TLS mode already specified");
539 				YYERROR;
540 			}
541 			listen_opts.options |= LO_SSL;
542 			listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE|F_TLS_VERIFY;
543 		}
544 		| PKI STRING			{
545 			if (listen_opts.options & LO_PKI) {
546 				yyerror("pki already specified");
547 				YYERROR;
548 			}
549 			listen_opts.options |= LO_PKI;
550 			listen_opts.pki = $2;
551 		}
552 		| CA STRING			{
553 			if (listen_opts.options & LO_CA) {
554 				yyerror("ca already specified");
555 				YYERROR;
556 			}
557 			listen_opts.options |= LO_CA;
558 			listen_opts.ca = $2;
559 		}
560 		| AUTH				{
561 			if (listen_opts.options & LO_AUTH) {
562 				yyerror("auth already specified");
563 				YYERROR;
564 			}
565 			listen_opts.options |= LO_AUTH;
566 			listen_opts.auth = F_AUTH|F_AUTH_REQUIRE;
567 		}
568 		| AUTH_OPTIONAL			{
569 			if (listen_opts.options & LO_AUTH) {
570 				yyerror("auth already specified");
571 				YYERROR;
572 			}
573 			listen_opts.options |= LO_AUTH;
574 			listen_opts.auth = F_AUTH;
575 		}
576 		| AUTH tables  			{
577 			if (listen_opts.options & LO_AUTH) {
578 				yyerror("auth already specified");
579 				YYERROR;
580 			}
581 			listen_opts.options |= LO_AUTH;
582 			listen_opts.authtable = $2;
583 			listen_opts.auth = F_AUTH|F_AUTH_REQUIRE;
584 		}
585 		| AUTH_OPTIONAL tables 		{
586 			if (listen_opts.options & LO_AUTH) {
587 				yyerror("auth already specified");
588 				YYERROR;
589 			}
590 			listen_opts.options |= LO_AUTH;
591 			listen_opts.authtable = $2;
592 			listen_opts.auth = F_AUTH;
593 		}
594 		| TAG STRING			{
595 			if (listen_opts.options & LO_TAG) {
596 				yyerror("tag already specified");
597 				YYERROR;
598 			}
599 			listen_opts.options |= LO_TAG;
600 
601 			if (strlen($2) >= SMTPD_TAG_SIZE) {
602        				yyerror("tag name too long");
603 				free($2);
604 				YYERROR;
605 			}
606 			listen_opts.tag = $2;
607 		}
608 		| HOSTNAME STRING	{
609 			if (listen_opts.options & LO_HOSTNAME) {
610 				yyerror("hostname already specified");
611 				YYERROR;
612 			}
613 			listen_opts.options |= LO_HOSTNAME;
614 
615 			listen_opts.hostname = $2;
616 		}
617 		| HOSTNAMES tables	{
618 			struct table	*t = $2;
619 
620 			if (listen_opts.options & LO_HOSTNAMES) {
621 				yyerror("hostnames already specified");
622 				YYERROR;
623 			}
624 			listen_opts.options |= LO_HOSTNAMES;
625 
626 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) {
627 				yyerror("invalid use of table \"%s\" as "
628 				    "HOSTNAMES parameter", t->t_name);
629 				YYERROR;
630 			}
631 			listen_opts.hostnametable = t;
632 		}
633 		| MASK_SOURCE	{
634 			if (config_lo_mask_source(&listen_opts)) {
635 				YYERROR;
636 			}
637 		}
638 		| RECEIVEDAUTH	{
639 			if (listen_opts.options & LO_RECEIVEDAUTH) {
640 				yyerror("received-auth already specified");
641 				YYERROR;
642 			}
643 			listen_opts.options |= LO_RECEIVEDAUTH;
644 			listen_opts.flags |= F_RECEIVEDAUTH;
645 		}
646 		| NODSN	{
647 			if (listen_opts.options & LO_NODSN) {
648 				yyerror("no-dsn already specified");
649 				YYERROR;
650 			}
651 			listen_opts.options |= LO_NODSN;
652 			listen_opts.flags &= ~F_EXT_DSN;
653 		}
654 		| SENDERS tables	{
655 			struct table	*t = $2;
656 
657 			if (listen_opts.options & LO_SENDERS) {
658 				yyerror("senders already specified");
659 				YYERROR;
660 			}
661 			listen_opts.options |= LO_SENDERS;
662 
663 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) {
664 				yyerror("invalid use of table \"%s\" as "
665 				    "SENDERS parameter", t->t_name);
666 				YYERROR;
667 			}
668 			listen_opts.sendertable = t;
669 		}
670 		| SENDERS tables MASQUERADE	{
671 			struct table	*t = $2;
672 
673 			if (listen_opts.options & LO_SENDERS) {
674 				yyerror("senders already specified");
675 				YYERROR;
676 			}
677 			listen_opts.options |= LO_SENDERS|LO_MASQUERADE;
678 
679 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) {
680 				yyerror("invalid use of table \"%s\" as "
681 				    "SENDERS parameter", t->t_name);
682 				YYERROR;
683 			}
684 			listen_opts.sendertable = t;
685 		}
686 		;
687 
688 listener_type	: socket_listener
689 		| if_listener
690 		;
691 
692 socket_listener	: SOCKET sock_listen {
693 			if (conf->sc_sock_listener) {
694 				yyerror("socket listener already configured");
695 				YYERROR;
696 			}
697 			create_sock_listener(&listen_opts);
698 		}
699 		;
700 
701 if_listener	: STRING if_listen {
702 			listen_opts.ifx = $1;
703 			create_if_listener(&listen_opts);
704 		}
705 		;
706 
707 sock_listen	: opt_sock_listen sock_listen
708 		| /* empty */
709 		;
710 
711 if_listen	: opt_if_listen if_listen
712 		| /* empty */
713 		;
714 
715 opt_relay_common: AS STRING	{
716 			struct mailaddr maddr, *maddrp;
717 
718 			if (!text_to_mailaddr(&maddr, $2)) {
719 				yyerror("invalid parameter to AS: %s", $2);
720 				free($2);
721 				YYERROR;
722 			}
723 			free($2);
724 
725 			if (maddr.user[0] == '\0' && maddr.domain[0] == '\0') {
726 				yyerror("invalid empty parameter to AS");
727 				YYERROR;
728 			}
729 			else if (maddr.domain[0] == '\0') {
730 				if (strlcpy(maddr.domain, conf->sc_hostname,
731 					sizeof (maddr.domain))
732 				    >= sizeof (maddr.domain)) {
733 					yyerror("hostname too long for AS parameter: %s",
734 					    conf->sc_hostname);
735 					YYERROR;
736 				}
737 			}
738 			rule->r_as = xmemdup(&maddr, sizeof (*maddrp), "parse relay_as: AS");
739 		}
740 		| SOURCE tables			{
741 			struct table	*t = $2;
742 			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_SOURCE)) {
743 				yyerror("invalid use of table \"%s\" as "
744 				    "SOURCE parameter", t->t_name);
745 				YYERROR;
746 			}
747 			(void)strlcpy(rule->r_value.relayhost.sourcetable, t->t_name,
748 			    sizeof rule->r_value.relayhost.sourcetable);
749 		}
750 		| HOSTNAME STRING {
751 			(void)strlcpy(rule->r_value.relayhost.heloname, $2,
752 			    sizeof rule->r_value.relayhost.heloname);
753 			free($2);
754 		}
755 		| HOSTNAMES tables		{
756 			struct table	*t = $2;
757 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) {
758 				yyerror("invalid use of table \"%s\" as "
759 				    "HOSTNAMES parameter", t->t_name);
760 				YYERROR;
761 			}
762 			(void)strlcpy(rule->r_value.relayhost.helotable, t->t_name,
763 			    sizeof rule->r_value.relayhost.helotable);
764 		}
765 		| PKI STRING {
766 			if (!lowercase(rule->r_value.relayhost.pki_name, $2,
767 				sizeof(rule->r_value.relayhost.pki_name))) {
768 				yyerror("pki name too long: %s", $2);
769 				free($2);
770 				YYERROR;
771 			}
772 			if (dict_get(conf->sc_pki_dict,
773 				rule->r_value.relayhost.pki_name) == NULL) {
774 				log_warnx("pki name not found: %s", $2);
775 				free($2);
776 				YYERROR;
777 			}
778 			free($2);
779 		}
780 		| CA STRING {
781 			if (!lowercase(rule->r_value.relayhost.ca_name, $2,
782 				sizeof(rule->r_value.relayhost.ca_name))) {
783 				yyerror("ca name too long: %s", $2);
784 				free($2);
785 				YYERROR;
786 			}
787 			if (dict_get(conf->sc_ca_dict,
788 				rule->r_value.relayhost.ca_name) == NULL) {
789 				log_warnx("ca name not found: %s", $2);
790 				free($2);
791 				YYERROR;
792 			}
793 			free($2);
794 		}
795 		;
796 
797 opt_relay	: BACKUP STRING			{
798 			rule->r_value.relayhost.flags |= F_BACKUP;
799 			if (strlcpy(rule->r_value.relayhost.hostname, $2,
800 				sizeof (rule->r_value.relayhost.hostname))
801 			    >= sizeof (rule->r_value.relayhost.hostname)) {
802 				log_warnx("hostname too long: %s", $2);
803 				free($2);
804 				YYERROR;
805 			}
806 			free($2);
807 		}
808 		| BACKUP       			{
809 			rule->r_value.relayhost.flags |= F_BACKUP;
810 			(void)strlcpy(rule->r_value.relayhost.hostname,
811 			    conf->sc_hostname,
812 			    sizeof (rule->r_value.relayhost.hostname));
813 		}
814 		| TLS       			{
815 			rule->r_value.relayhost.flags |= F_STARTTLS;
816 		}
817 		| TLS VERIFY			{
818 			rule->r_value.relayhost.flags |= F_STARTTLS|F_TLS_VERIFY;
819 		}
820 		;
821 
822 relay		: opt_relay_common relay
823 		| opt_relay relay
824 		| /* empty */
825 		;
826 
827 opt_relay_via	: AUTH tables {
828 			struct table   *t = $2;
829 
830 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_CREDENTIALS)) {
831 				yyerror("invalid use of table \"%s\" as AUTH parameter",
832 				    t->t_name);
833 				YYERROR;
834 			}
835 			(void)strlcpy(rule->r_value.relayhost.authtable, t->t_name,
836 			    sizeof(rule->r_value.relayhost.authtable));
837 		}
838 		| VERIFY {
839 			if (!(rule->r_value.relayhost.flags & F_SSL)) {
840 				yyerror("cannot \"verify\" with insecure protocol");
841 				YYERROR;
842 			}
843 			rule->r_value.relayhost.flags |= F_TLS_VERIFY;
844 		}
845 		;
846 
847 relay_via	: opt_relay_common relay_via
848 		| opt_relay_via relay_via
849 		| /* empty */
850 		;
851 
852 main		: BOUNCEWARN {
853 			memset(conf->sc_bounce_warn, 0, sizeof conf->sc_bounce_warn);
854 		} bouncedelays
855 		| SUBADDRESSING_DELIM STRING {
856 			if (strlen($2) != 1) {
857 				yyerror("subaddressing-delimiter must be one character");
858 				free($2);
859 				YYERROR;
860 			}
861 
862 			if (isspace((int)*$2) ||  !isprint((int)*$2) || *$2== '@') {
863 				yyerror("subaddressing-delimiter uses invalid character");
864 				free($2);
865 				YYERROR;
866 			}
867 
868 			conf->sc_subaddressing_delim = $2;
869 		}
870 		| QUEUE COMPRESSION {
871 			conf->sc_queue_flags |= QUEUE_COMPRESSION;
872 		}
873 		| QUEUE ENCRYPTION {
874 			conf->sc_queue_flags |= QUEUE_ENCRYPTION;
875 		}
876 		| QUEUE ENCRYPTION KEY STRING {
877 			if (strcasecmp($4, "stdin") == 0 || strcasecmp($4, "-") == 0) {
878 				conf->sc_queue_key = "stdin";
879 				free($4);
880 			}
881 			else
882 				conf->sc_queue_key = $4;
883 			conf->sc_queue_flags |= QUEUE_ENCRYPTION;
884 		}
885 		| EXPIRE STRING {
886 			conf->sc_qexpire = delaytonum($2);
887 			if (conf->sc_qexpire == -1) {
888 				yyerror("invalid expire delay: %s", $2);
889 				free($2);
890 				YYERROR;
891 			}
892 			free($2);
893 		}
894 		| MAXMESSAGESIZE size {
895 			conf->sc_maxsize = $2;
896 		}
897 		| MAXMTADEFERRED NUMBER  {
898 			conf->sc_mta_max_deferred = $2;
899 		}
900 		| LIMIT SESSION limits_session
901 		| LIMIT MDA limits_mda
902 		| LIMIT MTA FOR DOMAIN STRING {
903 			struct mta_limits	*d;
904 
905 			limits = dict_get(conf->sc_limits_dict, $5);
906 			if (limits == NULL) {
907 				limits = xcalloc(1, sizeof(*limits), "mta_limits");
908 				dict_xset(conf->sc_limits_dict, $5, limits);
909 				d = dict_xget(conf->sc_limits_dict, "default");
910 				memmove(limits, d, sizeof(*limits));
911 			}
912 			free($5);
913 		} limits_mta
914 		| LIMIT MTA {
915 			limits = dict_get(conf->sc_limits_dict, "default");
916 		} limits_mta
917 		| LIMIT SCHEDULER limits_scheduler
918 		| LISTEN {
919 			memset(&listen_opts, 0, sizeof listen_opts);
920 			listen_opts.family = AF_UNSPEC;
921 			listen_opts.flags |= F_EXT_DSN;
922 		} ON listener_type
923 		| FILTER STRING STRING {
924 			if (!strcmp($3, "chain")) {
925 				free($3);
926 				if ((filter = create_filter_chain($2)) == NULL) {
927 					free($2);
928 					YYERROR;
929 				}
930 			}
931 			else {
932 				if ((filter = create_filter_proc($2, $3)) == NULL) {
933 					free($2);
934 					free($3);
935 					YYERROR;
936 				}
937 			}
938 		} filter_args
939 		| PKI STRING	{
940 			char buf[HOST_NAME_MAX+1];
941 
942 			/* if not catchall, check that it is a valid domain */
943 			if (strcmp($2, "*") != 0) {
944 				if (!res_hnok($2)) {
945 					yyerror("not a valid domain name: %s", $2);
946 					free($2);
947 					YYERROR;
948 				}
949 			}
950 			xlowercase(buf, $2, sizeof(buf));
951 			free($2);
952 			pki = dict_get(conf->sc_pki_dict, buf);
953 			if (pki == NULL) {
954 				pki = xcalloc(1, sizeof *pki, "parse:pki");
955 				(void)strlcpy(pki->pki_name, buf, sizeof(pki->pki_name));
956 				dict_set(conf->sc_pki_dict, pki->pki_name, pki);
957 			}
958 		} pki
959 		| CA STRING	{
960 			char buf[HOST_NAME_MAX+1];
961 
962 			/* if not catchall, check that it is a valid domain */
963 			if (strcmp($2, "*") != 0) {
964 				if (!res_hnok($2)) {
965 					yyerror("not a valid domain name: %s", $2);
966 					free($2);
967 					YYERROR;
968 				}
969 			}
970 			xlowercase(buf, $2, sizeof(buf));
971 			free($2);
972 			sca = dict_get(conf->sc_ca_dict, buf);
973 			if (sca == NULL) {
974 				sca = xcalloc(1, sizeof *sca, "parse:ca");
975 				(void)strlcpy(sca->ca_name, buf, sizeof(sca->ca_name));
976 				dict_set(conf->sc_ca_dict, sca->ca_name, sca);
977 			}
978 		} ca
979 		| CIPHERS STRING {
980 			conf->sc_tls_ciphers = $2;
981 		}
982 		;
983 
984 filter_args	:
985 		| STRING {
986 			if (!add_filter_arg(filter, $1)) {
987 				free($1);
988 				YYERROR;
989 			}
990 		} filter_args
991 		;
992 
993 table		: TABLE STRING STRING	{
994 			char *p, *backend, *config;
995 
996 			p = $3;
997 			if (*p == '/') {
998 				backend = "static";
999 				config = $3;
1000 			}
1001 			else {
1002 				backend = $3;
1003 				config = NULL;
1004 				for (p = $3; *p && *p != ':'; p++)
1005 					;
1006 				if (*p == ':') {
1007 					*p = '\0';
1008 					backend = $3;
1009 					config  = p+1;
1010 				}
1011 			}
1012 			if (config != NULL && *config != '/') {
1013 				yyerror("invalid backend parameter for table: %s",
1014 				    $2);
1015 				free($2);
1016 				free($3);
1017 				YYERROR;
1018 			}
1019 			table = table_create(backend, $2, NULL, config);
1020 			if (!table_config(table)) {
1021 				yyerror("invalid configuration file %s for table %s",
1022 				    config, table->t_name);
1023 				free($2);
1024 				free($3);
1025 				YYERROR;
1026 			}
1027 			free($2);
1028 			free($3);
1029 		}
1030 		| TABLE STRING {
1031 			table = table_create("static", $2, NULL, NULL);
1032 			free($2);
1033 		} '{' tableval_list '}' {
1034 			table = NULL;
1035 		}
1036 		;
1037 
1038 assign		: '=' | ARROW;
1039 
1040 keyval		: STRING assign STRING		{
1041 			table->t_type = T_HASH;
1042 			table_add(table, $1, $3);
1043 			free($1);
1044 			free($3);
1045 		}
1046 		;
1047 
1048 keyval_list	: keyval
1049 		| keyval comma keyval_list
1050 		;
1051 
1052 stringel	: STRING			{
1053 			table->t_type = T_LIST;
1054 			table_add(table, $1, NULL);
1055 			free($1);
1056 		}
1057 		;
1058 
1059 string_list	: stringel
1060 		| stringel comma string_list
1061 		;
1062 
1063 tableval_list	: string_list			{ }
1064 		| keyval_list			{ }
1065 		;
1066 
1067 tablenew	: STRING			{
1068 			struct table	*t;
1069 
1070 			t = table_create("static", NULL, NULL, NULL);
1071 			t->t_type = T_LIST;
1072 			table_add(t, $1, NULL);
1073 			free($1);
1074 			$$ = t;
1075 		}
1076 		| '{'				{
1077 			table = table_create("static", NULL, NULL, NULL);
1078 		} tableval_list '}'		{
1079 			$$ = table;
1080 		}
1081 		;
1082 
1083 tableref       	: '<' STRING '>'       		{
1084 			struct table	*t;
1085 
1086 			if ((t = table_find($2, NULL)) == NULL) {
1087 				yyerror("no such table: %s", $2);
1088 				free($2);
1089 				YYERROR;
1090 			}
1091 			free($2);
1092 			$$ = t;
1093 		}
1094 		;
1095 
1096 tables		: tablenew			{ $$ = $1; }
1097 		| tableref			{ $$ = $1; }
1098 		;
1099 
1100 alias		: ALIAS tables			{
1101 			struct table   *t = $2;
1102 
1103 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) {
1104 				yyerror("invalid use of table \"%s\" as ALIAS parameter",
1105 				    t->t_name);
1106 				YYERROR;
1107 			}
1108 
1109 			$$ = t;
1110 		}
1111 		;
1112 
1113 virtual		: VIRTUAL tables		{
1114 			struct table   *t = $2;
1115 
1116 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) {
1117 				yyerror("invalid use of table \"%s\" as VIRTUAL parameter",
1118 				    t->t_name);
1119 				YYERROR;
1120 			}
1121 			$$ = t;
1122 		}
1123 		;
1124 
1125 usermapping	: alias		{
1126 			if (rule->r_mapping) {
1127 				yyerror("alias specified multiple times");
1128 				YYERROR;
1129 			}
1130 			rule->r_desttype = DEST_DOM;
1131 			rule->r_mapping = $1;
1132 		}
1133 		| virtual	{
1134 			if (rule->r_mapping) {
1135 				yyerror("virtual specified multiple times");
1136 				YYERROR;
1137 			}
1138 			rule->r_desttype = DEST_VDOM;
1139 			rule->r_mapping = $1;
1140 		}
1141 		;
1142 
1143 userbase	: USERBASE tables	{
1144 			struct table   *t = $2;
1145 
1146 			if (rule->r_userbase) {
1147 				yyerror("userbase specified multiple times");
1148 				YYERROR;
1149 			}
1150 			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_USERINFO)) {
1151 				yyerror("invalid use of table \"%s\" as USERBASE parameter",
1152 				    t->t_name);
1153 				YYERROR;
1154 			}
1155 			rule->r_userbase = t;
1156 		}
1157 		;
1158 
1159 deliver_as	: AS STRING	{
1160 			if (strlcpy(rule->r_delivery_user, $2,
1161 			    sizeof(rule->r_delivery_user))
1162 			    >= sizeof(rule->r_delivery_user))
1163 				fatal("username too long");
1164 			free($2);
1165 		}
1166 		| /* empty */	{}
1167 		;
1168 
1169 deliver_action	: DELIVER TO MAILDIR			{
1170 			rule->r_action = A_MAILDIR;
1171 			if (strlcpy(rule->r_value.buffer, "~/Maildir",
1172 			    sizeof(rule->r_value.buffer)) >=
1173 			    sizeof(rule->r_value.buffer))
1174 				fatal("pathname too long");
1175 		}
1176 		| DELIVER TO MAILDIR STRING		{
1177 			rule->r_action = A_MAILDIR;
1178 			if (strlcpy(rule->r_value.buffer, $4,
1179 			    sizeof(rule->r_value.buffer)) >=
1180 			    sizeof(rule->r_value.buffer))
1181 				fatal("pathname too long");
1182 			free($4);
1183 		}
1184 		| DELIVER TO MBOX			{
1185 			rule->r_action = A_MBOX;
1186 			if (strlcpy(rule->r_value.buffer, _PATH_MAILDIR "/%u",
1187 			    sizeof(rule->r_value.buffer))
1188 			    >= sizeof(rule->r_value.buffer))
1189 				fatal("pathname too long");
1190 		}
1191 		| DELIVER TO LMTP STRING deliver_as	{
1192 			rule->r_action = A_LMTP;
1193 			if (strchr($4, ':') || $4[0] == '/') {
1194 				if (strlcpy(rule->r_value.buffer, $4,
1195 					sizeof(rule->r_value.buffer))
1196 					>= sizeof(rule->r_value.buffer))
1197 					fatal("lmtp destination too long");
1198 			} else
1199 				fatal("invalid lmtp destination");
1200 			free($4);
1201 		}
1202 		| DELIVER TO LMTP STRING RCPTTO deliver_as 	{
1203 			rule->r_action = A_LMTP;
1204 			if (strchr($4, ':') || $4[0] == '/') {
1205 				if (strlcpy(rule->r_value.buffer, $4,
1206 					sizeof(rule->r_value.buffer))
1207 					>= sizeof(rule->r_value.buffer))
1208 					fatal("lmtp destination too long");
1209 				if (strlcat(rule->r_value.buffer, " rcpt-to",
1210 					sizeof(rule->r_value.buffer))
1211 					>= sizeof(rule->r_value.buffer))
1212 					fatal("lmtp recipient too long");
1213 			} else
1214 				fatal("invalid lmtp destination");
1215 			free($4);
1216 		}
1217 		| DELIVER TO MDA STRING deliver_as	{
1218 			rule->r_action = A_MDA;
1219 			if (strlcpy(rule->r_value.buffer, $4,
1220 			    sizeof(rule->r_value.buffer))
1221 			    >= sizeof(rule->r_value.buffer))
1222 				fatal("command too long");
1223 			free($4);
1224 		}
1225 		;
1226 
1227 relay_action   	: RELAY relay {
1228 			rule->r_action = A_RELAY;
1229 		}
1230 		| RELAY VIA STRING {
1231 			rule->r_action = A_RELAYVIA;
1232 			if (!text_to_relayhost(&rule->r_value.relayhost, $3)) {
1233 				yyerror("error: invalid url: %s", $3);
1234 				free($3);
1235 				YYERROR;
1236 			}
1237 			free($3);
1238 		} relay_via {
1239 			/* no worries, F_AUTH cant be set without SSL */
1240 			if (rule->r_value.relayhost.flags & F_AUTH) {
1241 				if (rule->r_value.relayhost.authtable[0] == '\0') {
1242 					yyerror("error: auth without auth table");
1243 					YYERROR;
1244 				}
1245 			}
1246 		}
1247 		;
1248 
1249 negation	: '!'		{ $$ = 1; }
1250 		| /* empty */	{ $$ = 0; }
1251 		;
1252 
1253 from		: FROM negation SOURCE tables       		{
1254 			struct table   *t = $4;
1255 
1256 			if (rule->r_sources) {
1257 				yyerror("from specified multiple times");
1258 				YYERROR;
1259 			}
1260 			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_NETADDR)) {
1261 				yyerror("invalid use of table \"%s\" as FROM parameter",
1262 				    t->t_name);
1263 				YYERROR;
1264 			}
1265 			rule->r_notsources = $2;
1266 			rule->r_sources = t;
1267 		}
1268 		| FROM negation ANY    		{
1269 			if (rule->r_sources) {
1270 				yyerror("from specified multiple times");
1271 				YYERROR;
1272 			}
1273 			rule->r_sources = table_find("<anyhost>", NULL);
1274 			rule->r_notsources = $2;
1275 		}
1276 		| FROM negation LOCAL  		{
1277 			if (rule->r_sources) {
1278 				yyerror("from specified multiple times");
1279 				YYERROR;
1280 			}
1281 			rule->r_sources = table_find("<localhost>", NULL);
1282 			rule->r_notsources = $2;
1283 		}
1284 		;
1285 
1286 for		: FOR negation DOMAIN tables {
1287 			struct table   *t = $4;
1288 
1289 			if (rule->r_destination) {
1290 				yyerror("for specified multiple times");
1291 				YYERROR;
1292 			}
1293 			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) {
1294 				yyerror("invalid use of table \"%s\" as DOMAIN parameter",
1295 				    t->t_name);
1296 				YYERROR;
1297 			}
1298 			rule->r_notdestination = $2;
1299 			rule->r_destination = t;
1300 		}
1301 		| FOR negation ANY    		{
1302 			if (rule->r_destination) {
1303 				yyerror("for specified multiple times");
1304 				YYERROR;
1305 			}
1306 			rule->r_notdestination = $2;
1307 			rule->r_destination = table_find("<anydestination>", NULL);
1308 		}
1309 		| FOR negation LOCAL  		{
1310 			if (rule->r_destination) {
1311 				yyerror("for specified multiple times");
1312 				YYERROR;
1313 			}
1314 			rule->r_notdestination = $2;
1315 			rule->r_destination = table_find("<localnames>", NULL);
1316 		}
1317 		;
1318 
1319 sender		: SENDER negation tables			{
1320 			struct table   *t = $3;
1321 
1322 			if (rule->r_senders) {
1323 				yyerror("sender specified multiple times");
1324 				YYERROR;
1325 			}
1326 
1327 			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) {
1328 				yyerror("invalid use of table \"%s\" as SENDER parameter",
1329 				    t->t_name);
1330 				YYERROR;
1331 			}
1332 			rule->r_notsenders = $2;
1333 			rule->r_senders = t;
1334 		}
1335 		;
1336 
1337 recipient      	: RECIPIENT negation tables			{
1338 			struct table   *t = $3;
1339 
1340 			if (rule->r_recipients) {
1341 				yyerror("recipient specified multiple times");
1342 				YYERROR;
1343 			}
1344 
1345 			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) {
1346 				yyerror("invalid use of table \"%s\" as RECIPIENT parameter",
1347 				    t->t_name);
1348 				YYERROR;
1349 			}
1350 			rule->r_notrecipients = $2;
1351 			rule->r_recipients = t;
1352 		}
1353 		;
1354 
1355 forwardonly	: FORWARDONLY {
1356 			if (rule->r_forwardonly) {
1357 				yyerror("forward-only specified multiple times");
1358 				YYERROR;
1359 			}
1360 			rule->r_forwardonly = 1;
1361 		}
1362 		;
1363 
1364 expire		: EXPIRE STRING {
1365 			if (rule->r_qexpire != -1) {
1366 				yyerror("expire specified multiple times");
1367 				YYERROR;
1368 			}
1369 			rule->r_qexpire = delaytonum($2);
1370 			if (rule->r_qexpire == -1) {
1371 				yyerror("invalid expire delay: %s", $2);
1372 				free($2);
1373 				YYERROR;
1374 			}
1375 			free($2);
1376 		}
1377 		;
1378 
1379 opt_decision	: sender
1380 		| recipient
1381 		| from
1382 		| for
1383 		| tagged
1384 		| authenticated
1385 		;
1386 decision	: opt_decision decision
1387 		|
1388 		;
1389 
1390 opt_lookup	: userbase
1391 		| usermapping
1392 		;
1393 lookup		: opt_lookup lookup
1394 		|
1395 		;
1396 
1397 action		: deliver_action
1398 		| relay_action
1399 		|
1400 		;
1401 
1402 opt_accept	: expire
1403 		| forwardonly
1404 		;
1405 
1406 accept_params	: opt_accept accept_params
1407 		|
1408 		;
1409 
1410 rule		: ACCEPT {
1411 			rule = xcalloc(1, sizeof(*rule), "parse rule: ACCEPT");
1412 			rule->r_action = A_NONE;
1413 			rule->r_decision = R_ACCEPT;
1414 			rule->r_desttype = DEST_DOM;
1415 			rule->r_qexpire = -1;
1416 		} decision lookup action accept_params {
1417 			if (!rule->r_sources)
1418 				rule->r_sources = table_find("<localhost>", NULL);
1419 			if (!rule->r_destination)
1420 			 	rule->r_destination = table_find("<localnames>", NULL);
1421 			if (!rule->r_userbase)
1422 				rule->r_userbase = table_find("<getpwnam>", NULL);
1423 			if (rule->r_qexpire == -1)
1424 				rule->r_qexpire = conf->sc_qexpire;
1425 			if (rule->r_action == A_RELAY || rule->r_action == A_RELAYVIA) {
1426 				if (rule->r_userbase != table_find("<getpwnam>", NULL)) {
1427 					yyerror("userbase may not be used with a relay rule");
1428 					YYERROR;
1429 				}
1430 				if (rule->r_mapping) {
1431 					yyerror("aliases/virtual may not be used with a relay rule");
1432 					YYERROR;
1433 				}
1434 			}
1435 			if (rule->r_forwardonly && rule->r_action != A_NONE) {
1436 				yyerror("forward-only may not be used with a default action");
1437 				YYERROR;
1438 			}
1439 			TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry);
1440 			rule = NULL;
1441 		}
1442 		| REJECT {
1443 			rule = xcalloc(1, sizeof(*rule), "parse rule: REJECT");
1444 			rule->r_decision = R_REJECT;
1445 			rule->r_desttype = DEST_DOM;
1446 		} decision {
1447 			if (!rule->r_sources)
1448 				rule->r_sources = table_find("<localhost>", NULL);
1449 			if (!rule->r_destination)
1450 				rule->r_destination = table_find("<localnames>", NULL);
1451 			TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry);
1452 			rule = NULL;
1453 		}
1454 		;
1455 %%
1456 
1457 struct keywords {
1458 	const char	*k_name;
1459 	int		 k_val;
1460 };
1461 
1462 int
1463 yyerror(const char *fmt, ...)
1464 {
1465 	va_list		 ap;
1466 	char		*msg;
1467 
1468 	file->errors++;
1469 	va_start(ap, fmt);
1470 	if (vasprintf(&msg, fmt, ap) == -1)
1471 		fatalx("yyerror vasprintf");
1472 	va_end(ap);
1473 	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
1474 	free(msg);
1475 	return (0);
1476 }
1477 
1478 int
1479 kw_cmp(const void *k, const void *e)
1480 {
1481 	return (strcmp(k, ((const struct keywords *)e)->k_name));
1482 }
1483 
1484 int
1485 lookup(char *s)
1486 {
1487 	/* this has to be sorted always */
1488 	static const struct keywords keywords[] = {
1489 		{ "accept",		ACCEPT },
1490 		{ "alias",		ALIAS },
1491 		{ "any",		ANY },
1492 		{ "as",			AS },
1493 		{ "auth",		AUTH },
1494 		{ "auth-optional",     	AUTH_OPTIONAL },
1495 		{ "authenticated",     	AUTHENTICATED },
1496 		{ "backup",		BACKUP },
1497 		{ "bounce-warn",	BOUNCEWARN },
1498 		{ "ca",			CA },
1499 		{ "certificate",	CERTIFICATE },
1500 		{ "ciphers",		CIPHERS },
1501 		{ "compression",	COMPRESSION },
1502 		{ "deliver",		DELIVER },
1503 		{ "dhe",		DHE },
1504 		{ "domain",		DOMAIN },
1505 		{ "encryption",		ENCRYPTION },
1506 		{ "expire",		EXPIRE },
1507 		{ "filter",		FILTER },
1508 		{ "for",		FOR },
1509 		{ "forward-only",      	FORWARDONLY },
1510 		{ "from",		FROM },
1511 		{ "hostname",		HOSTNAME },
1512 		{ "hostnames",		HOSTNAMES },
1513 		{ "include",		INCLUDE },
1514 		{ "inet4",		INET4 },
1515 		{ "inet6",		INET6 },
1516 		{ "key",		KEY },
1517 		{ "limit",		LIMIT },
1518 		{ "listen",		LISTEN },
1519 		{ "lmtp",		LMTP },
1520 		{ "local",		LOCAL },
1521 		{ "maildir",		MAILDIR },
1522 		{ "mask-source",	MASK_SOURCE },
1523 		{ "masquerade",		MASQUERADE },
1524 		{ "max-message-size",  	MAXMESSAGESIZE },
1525 		{ "max-mta-deferred",  	MAXMTADEFERRED },
1526 		{ "mbox",		MBOX },
1527 		{ "mda",		MDA },
1528 		{ "mta",		MTA },
1529 		{ "no-dsn",		NODSN },
1530 		{ "on",			ON },
1531 		{ "pki",		PKI },
1532 		{ "port",		PORT },
1533 		{ "queue",		QUEUE },
1534 		{ "rcpt-to",		RCPTTO },
1535 		{ "received-auth",     	RECEIVEDAUTH },
1536 		{ "recipient",		RECIPIENT },
1537 		{ "reject",		REJECT },
1538 		{ "relay",		RELAY },
1539 		{ "scheduler",		SCHEDULER },
1540 		{ "secure",		SECURE },
1541 		{ "sender",    		SENDER },
1542 		{ "senders",   		SENDERS },
1543 		{ "session",   		SESSION },
1544 		{ "smtps",		SMTPS },
1545 		{ "socket",		SOCKET },
1546 		{ "source",		SOURCE },
1547 		{ "subaddressing-delimiter",	SUBADDRESSING_DELIM },
1548 		{ "table",		TABLE },
1549 		{ "tag",		TAG },
1550 		{ "tagged",		TAGGED },
1551 		{ "tls",		TLS },
1552 		{ "tls-require",       	TLS_REQUIRE },
1553 		{ "to",			TO },
1554 		{ "userbase",		USERBASE },
1555 		{ "verify",		VERIFY },
1556 		{ "via",		VIA },
1557 		{ "virtual",		VIRTUAL },
1558 	};
1559 	const struct keywords	*p;
1560 
1561 	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
1562 	    sizeof(keywords[0]), kw_cmp);
1563 
1564 	if (p)
1565 		return (p->k_val);
1566 	else
1567 		return (STRING);
1568 }
1569 
1570 #define MAXPUSHBACK	128
1571 
1572 unsigned char	*parsebuf;
1573 int		 parseindex;
1574 unsigned char	 pushback_buffer[MAXPUSHBACK];
1575 int		 pushback_index = 0;
1576 
1577 int
1578 lgetc(int quotec)
1579 {
1580 	int		c, next;
1581 
1582 	if (parsebuf) {
1583 		/* Read character from the parsebuffer instead of input. */
1584 		if (parseindex >= 0) {
1585 			c = parsebuf[parseindex++];
1586 			if (c != '\0')
1587 				return (c);
1588 			parsebuf = NULL;
1589 		} else
1590 			parseindex++;
1591 	}
1592 
1593 	if (pushback_index)
1594 		return (pushback_buffer[--pushback_index]);
1595 
1596 	if (quotec) {
1597 		if ((c = getc(file->stream)) == EOF) {
1598 			yyerror("reached end of file while parsing "
1599 			    "quoted string");
1600 			if (file == topfile || popfile() == EOF)
1601 				return (EOF);
1602 			return (quotec);
1603 		}
1604 		return (c);
1605 	}
1606 
1607 	while ((c = getc(file->stream)) == '\\') {
1608 		next = getc(file->stream);
1609 		if (next != '\n') {
1610 			c = next;
1611 			break;
1612 		}
1613 		yylval.lineno = file->lineno;
1614 		file->lineno++;
1615 	}
1616 
1617 	while (c == EOF) {
1618 		if (file == topfile || popfile() == EOF)
1619 			return (EOF);
1620 		c = getc(file->stream);
1621 	}
1622 	return (c);
1623 }
1624 
1625 int
1626 lungetc(int c)
1627 {
1628 	if (c == EOF)
1629 		return (EOF);
1630 	if (parsebuf) {
1631 		parseindex--;
1632 		if (parseindex >= 0)
1633 			return (c);
1634 	}
1635 	if (pushback_index < MAXPUSHBACK-1)
1636 		return (pushback_buffer[pushback_index++] = c);
1637 	else
1638 		return (EOF);
1639 }
1640 
1641 int
1642 findeol(void)
1643 {
1644 	int	c;
1645 
1646 	parsebuf = NULL;
1647 	pushback_index = 0;
1648 
1649 	/* skip to either EOF or the first real EOL */
1650 	while (1) {
1651 		c = lgetc(0);
1652 		if (c == '\n') {
1653 			file->lineno++;
1654 			break;
1655 		}
1656 		if (c == EOF)
1657 			break;
1658 	}
1659 	return (ERROR);
1660 }
1661 
1662 int
1663 yylex(void)
1664 {
1665 	unsigned char	 buf[8096];
1666 	unsigned char	*p, *val;
1667 	int		 quotec, next, c;
1668 	int		 token;
1669 
1670 top:
1671 	p = buf;
1672 	while ((c = lgetc(0)) == ' ' || c == '\t')
1673 		; /* nothing */
1674 
1675 	yylval.lineno = file->lineno;
1676 	if (c == '#')
1677 		while ((c = lgetc(0)) != '\n' && c != EOF)
1678 			; /* nothing */
1679 	if (c == '$' && parsebuf == NULL) {
1680 		while (1) {
1681 			if ((c = lgetc(0)) == EOF)
1682 				return (0);
1683 
1684 			if (p + 1 >= buf + sizeof(buf) - 1) {
1685 				yyerror("string too long");
1686 				return (findeol());
1687 			}
1688 			if (isalnum(c) || c == '_') {
1689 				*p++ = c;
1690 				continue;
1691 			}
1692 			*p = '\0';
1693 			lungetc(c);
1694 			break;
1695 		}
1696 		val = symget(buf);
1697 		if (val == NULL) {
1698 			yyerror("macro '%s' not defined", buf);
1699 			return (findeol());
1700 		}
1701 		parsebuf = val;
1702 		parseindex = 0;
1703 		goto top;
1704 	}
1705 
1706 	switch (c) {
1707 	case '\'':
1708 	case '"':
1709 		quotec = c;
1710 		while (1) {
1711 			if ((c = lgetc(quotec)) == EOF)
1712 				return (0);
1713 			if (c == '\n') {
1714 				file->lineno++;
1715 				continue;
1716 			} else if (c == '\\') {
1717 				if ((next = lgetc(quotec)) == EOF)
1718 					return (0);
1719 				if (next == quotec || c == ' ' || c == '\t')
1720 					c = next;
1721 				else if (next == '\n') {
1722 					file->lineno++;
1723 					continue;
1724 				} else
1725 					lungetc(next);
1726 			} else if (c == quotec) {
1727 				*p = '\0';
1728 				break;
1729 			} else if (c == '\0') {
1730 				yyerror("syntax error");
1731 				return (findeol());
1732 			}
1733 			if (p + 1 >= buf + sizeof(buf) - 1) {
1734 				yyerror("string too long");
1735 				return (findeol());
1736 			}
1737 			*p++ = c;
1738 		}
1739 		yylval.v.string = strdup(buf);
1740 		if (yylval.v.string == NULL)
1741 			err(1, "yylex: strdup");
1742 		return (STRING);
1743 	}
1744 
1745 #define allowed_to_end_number(x) \
1746 	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1747 
1748 	if (c == '-' || isdigit(c)) {
1749 		do {
1750 			*p++ = c;
1751 			if ((unsigned)(p-buf) >= sizeof(buf)) {
1752 				yyerror("string too long");
1753 				return (findeol());
1754 			}
1755 		} while ((c = lgetc(0)) != EOF && isdigit(c));
1756 		lungetc(c);
1757 		if (p == buf + 1 && buf[0] == '-')
1758 			goto nodigits;
1759 		if (c == EOF || allowed_to_end_number(c)) {
1760 			const char *errstr = NULL;
1761 
1762 			*p = '\0';
1763 			yylval.v.number = strtonum(buf, LLONG_MIN,
1764 			    LLONG_MAX, &errstr);
1765 			if (errstr) {
1766 				yyerror("\"%s\" invalid number: %s",
1767 				    buf, errstr);
1768 				return (findeol());
1769 			}
1770 			return (NUMBER);
1771 		} else {
1772 nodigits:
1773 			while (p > buf + 1)
1774 				lungetc(*--p);
1775 			c = *--p;
1776 			if (c == '-')
1777 				return (c);
1778 		}
1779 	}
1780 
1781 	if (c == '=') {
1782 		if ((c = lgetc(0)) != EOF && c == '>')
1783 			return (ARROW);
1784 		lungetc(c);
1785 		c = '=';
1786 	}
1787 
1788 #define allowed_in_string(x) \
1789 	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1790 	x != '{' && x != '}' && x != '<' && x != '>' && \
1791 	x != '!' && x != '=' && x != '#' && \
1792 	x != ','))
1793 
1794 	if (isalnum(c) || c == ':' || c == '_') {
1795 		do {
1796 			*p++ = c;
1797 			if ((unsigned)(p-buf) >= sizeof(buf)) {
1798 				yyerror("string too long");
1799 				return (findeol());
1800 			}
1801 		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
1802 		lungetc(c);
1803 		*p = '\0';
1804 		if ((token = lookup(buf)) == STRING)
1805 			if ((yylval.v.string = strdup(buf)) == NULL)
1806 				err(1, "yylex: strdup");
1807 		return (token);
1808 	}
1809 	if (c == '\n') {
1810 		yylval.lineno = file->lineno;
1811 		file->lineno++;
1812 	}
1813 	if (c == EOF)
1814 		return (0);
1815 	return (c);
1816 }
1817 
1818 int
1819 check_file_secrecy(int fd, const char *fname)
1820 {
1821 	struct stat	st;
1822 
1823 	if (fstat(fd, &st)) {
1824 		log_warn("warn: cannot stat %s", fname);
1825 		return (-1);
1826 	}
1827 	if (st.st_uid != 0 && st.st_uid != getuid()) {
1828 		log_warnx("warn: %s: owner not root or current user", fname);
1829 		return (-1);
1830 	}
1831 	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
1832 		log_warnx("warn: %s: group/world readable/writeable", fname);
1833 		return (-1);
1834 	}
1835 	return (0);
1836 }
1837 
1838 struct file *
1839 pushfile(const char *name, int secret)
1840 {
1841 	struct file	*nfile;
1842 
1843 	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
1844 		log_warn("warn: malloc");
1845 		return (NULL);
1846 	}
1847 	if ((nfile->name = strdup(name)) == NULL) {
1848 		log_warn("warn: malloc");
1849 		free(nfile);
1850 		return (NULL);
1851 	}
1852 	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
1853 		log_warn("warn: %s", nfile->name);
1854 		free(nfile->name);
1855 		free(nfile);
1856 		return (NULL);
1857 	} else if (secret &&
1858 	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
1859 		fclose(nfile->stream);
1860 		free(nfile->name);
1861 		free(nfile);
1862 		return (NULL);
1863 	}
1864 	nfile->lineno = 1;
1865 	TAILQ_INSERT_TAIL(&files, nfile, entry);
1866 	return (nfile);
1867 }
1868 
1869 int
1870 popfile(void)
1871 {
1872 	struct file	*prev;
1873 
1874 	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
1875 		prev->errors += file->errors;
1876 
1877 	TAILQ_REMOVE(&files, file, entry);
1878 	fclose(file->stream);
1879 	free(file->name);
1880 	free(file);
1881 	file = prev;
1882 	return (file ? 0 : EOF);
1883 }
1884 
1885 int
1886 parse_config(struct smtpd *x_conf, const char *filename, int opts)
1887 {
1888 	struct sym     *sym, *next;
1889 	struct table   *t;
1890 	char		hostname[HOST_NAME_MAX+1];
1891 	char		hostname_copy[HOST_NAME_MAX+1];
1892 
1893 	if (getmailname(hostname, sizeof hostname) == -1)
1894 		return (-1);
1895 
1896 	conf = x_conf;
1897 	memset(conf, 0, sizeof(*conf));
1898 
1899 	(void)strlcpy(conf->sc_hostname, hostname, sizeof(conf->sc_hostname));
1900 
1901 	conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE;
1902 	conf->sc_subaddressing_delim = SUBADDRESSING_DELIMITER;
1903 
1904 	conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict));
1905 	conf->sc_rules = calloc(1, sizeof(*conf->sc_rules));
1906 	conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners));
1907 	conf->sc_ca_dict = calloc(1, sizeof(*conf->sc_ca_dict));
1908 	conf->sc_pki_dict = calloc(1, sizeof(*conf->sc_pki_dict));
1909 	conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict));
1910 	conf->sc_limits_dict = calloc(1, sizeof(*conf->sc_limits_dict));
1911 
1912 	/* Report mails delayed for more than 4 hours */
1913 	conf->sc_bounce_warn[0] = 3600 * 4;
1914 
1915 	if (conf->sc_tables_dict == NULL	||
1916 	    conf->sc_rules == NULL		||
1917 	    conf->sc_listeners == NULL		||
1918 	    conf->sc_ca_dict == NULL		||
1919 	    conf->sc_pki_dict == NULL		||
1920 	    conf->sc_ssl_dict == NULL		||
1921 	    conf->sc_limits_dict == NULL) {
1922 		log_warn("warn: cannot allocate memory");
1923 		free(conf->sc_tables_dict);
1924 		free(conf->sc_rules);
1925 		free(conf->sc_listeners);
1926 		free(conf->sc_ca_dict);
1927 		free(conf->sc_pki_dict);
1928 		free(conf->sc_ssl_dict);
1929 		free(conf->sc_limits_dict);
1930 		return (-1);
1931 	}
1932 
1933 	errors = 0;
1934 
1935 	table = NULL;
1936 	rule = NULL;
1937 
1938 	dict_init(&conf->sc_filters);
1939 
1940 	dict_init(conf->sc_ca_dict);
1941 	dict_init(conf->sc_pki_dict);
1942 	dict_init(conf->sc_ssl_dict);
1943 	dict_init(conf->sc_tables_dict);
1944 
1945 	dict_init(conf->sc_limits_dict);
1946 	limits = xcalloc(1, sizeof(*limits), "mta_limits");
1947 	limit_mta_set_defaults(limits);
1948 	dict_xset(conf->sc_limits_dict, "default", limits);
1949 
1950 	TAILQ_INIT(conf->sc_listeners);
1951 	TAILQ_INIT(conf->sc_rules);
1952 
1953 	conf->sc_qexpire = SMTPD_QUEUE_EXPIRY;
1954 	conf->sc_opts = opts;
1955 
1956 	conf->sc_mta_max_deferred = 100;
1957 	conf->sc_scheduler_max_inflight = 5000;
1958 	conf->sc_scheduler_max_schedule = 10;
1959 	conf->sc_scheduler_max_evp_batch_size = 256;
1960 	conf->sc_scheduler_max_msg_batch_size = 1024;
1961 
1962 	conf->sc_session_max_rcpt = 1000;
1963 	conf->sc_session_max_mails = 100;
1964 
1965 	conf->sc_mda_max_session = 50;
1966 	conf->sc_mda_max_user_session = 7;
1967 	conf->sc_mda_task_hiwat = 50;
1968 	conf->sc_mda_task_lowat = 30;
1969 	conf->sc_mda_task_release = 10;
1970 
1971 	if ((file = pushfile(filename, 0)) == NULL) {
1972 		purge_config(PURGE_EVERYTHING);
1973 		return (-1);
1974 	}
1975 	topfile = file;
1976 
1977 	/*
1978 	 * declare special "localhost", "anyhost" and "localnames" tables
1979 	 */
1980 	set_local(hostname);
1981 
1982 	t = table_create("static", "<anydestination>", NULL, NULL);
1983 	t->t_type = T_LIST;
1984 	table_add(t, "*", NULL);
1985 
1986 	/* can't truncate here */
1987 	(void)strlcpy(hostname_copy, hostname, sizeof hostname_copy);
1988 
1989 	hostname_copy[strcspn(hostname_copy, ".")] = '\0';
1990 	if (strcmp(hostname, hostname_copy) != 0)
1991 		table_add(t, hostname_copy, NULL);
1992 
1993 	table_create("getpwnam", "<getpwnam>", NULL, NULL);
1994 
1995 	/*
1996 	 * parse configuration
1997 	 */
1998 	setservent(1);
1999 	yyparse();
2000 	errors = file->errors;
2001 	popfile();
2002 	endservent();
2003 
2004 	/* If the socket listener was not configured, create a default one. */
2005 	if (!conf->sc_sock_listener) {
2006 		memset(&listen_opts, 0, sizeof listen_opts);
2007 		create_sock_listener(&listen_opts);
2008 	}
2009 
2010 	/* Free macros and check which have not been used. */
2011 	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
2012 		next = TAILQ_NEXT(sym, entry);
2013 		if ((conf->sc_opts & SMTPD_OPT_VERBOSE) && !sym->used)
2014 			fprintf(stderr, "warning: macro '%s' not "
2015 			    "used\n", sym->nam);
2016 		if (!sym->persist) {
2017 			free(sym->nam);
2018 			free(sym->val);
2019 			TAILQ_REMOVE(&symhead, sym, entry);
2020 			free(sym);
2021 		}
2022 	}
2023 
2024 	if (TAILQ_EMPTY(conf->sc_rules)) {
2025 		log_warnx("warn: no rules, nothing to do");
2026 		errors++;
2027 	}
2028 
2029 	if (errors) {
2030 		purge_config(PURGE_EVERYTHING);
2031 		return (-1);
2032 	}
2033 
2034 	return (0);
2035 }
2036 
2037 int
2038 symset(const char *nam, const char *val, int persist)
2039 {
2040 	struct sym	*sym;
2041 
2042 	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
2043 	    sym = TAILQ_NEXT(sym, entry))
2044 		;	/* nothing */
2045 
2046 	if (sym != NULL) {
2047 		if (sym->persist == 1)
2048 			return (0);
2049 		else {
2050 			free(sym->nam);
2051 			free(sym->val);
2052 			TAILQ_REMOVE(&symhead, sym, entry);
2053 			free(sym);
2054 		}
2055 	}
2056 	if ((sym = calloc(1, sizeof(*sym))) == NULL)
2057 		return (-1);
2058 
2059 	sym->nam = strdup(nam);
2060 	if (sym->nam == NULL) {
2061 		free(sym);
2062 		return (-1);
2063 	}
2064 	sym->val = strdup(val);
2065 	if (sym->val == NULL) {
2066 		free(sym->nam);
2067 		free(sym);
2068 		return (-1);
2069 	}
2070 	sym->used = 0;
2071 	sym->persist = persist;
2072 	TAILQ_INSERT_TAIL(&symhead, sym, entry);
2073 	return (0);
2074 }
2075 
2076 int
2077 cmdline_symset(char *s)
2078 {
2079 	char	*sym, *val;
2080 	int	ret;
2081 	size_t	len;
2082 
2083 	if ((val = strrchr(s, '=')) == NULL)
2084 		return (-1);
2085 
2086 	len = strlen(s) - strlen(val) + 1;
2087 	if ((sym = malloc(len)) == NULL)
2088 		errx(1, "cmdline_symset: malloc");
2089 
2090 	(void)strlcpy(sym, s, len);
2091 
2092 	ret = symset(sym, val + 1, 1);
2093 	free(sym);
2094 
2095 	return (ret);
2096 }
2097 
2098 char *
2099 symget(const char *nam)
2100 {
2101 	struct sym	*sym;
2102 
2103 	TAILQ_FOREACH(sym, &symhead, entry)
2104 		if (strcmp(nam, sym->nam) == 0) {
2105 			sym->used = 1;
2106 			return (sym->val);
2107 		}
2108 	return (NULL);
2109 }
2110 
2111 static void
2112 create_sock_listener(struct listen_opts *lo)
2113 {
2114 	struct listener *l = xcalloc(1, sizeof(*l), "create_sock_listener");
2115 	lo->tag = "local";
2116 	lo->hostname = conf->sc_hostname;
2117 	l->ss.ss_family = AF_LOCAL;
2118 	l->ss.ss_len = sizeof(struct sockaddr *);
2119 	l->local = 1;
2120 	conf->sc_sock_listener = l;
2121 	config_listener(l, lo);
2122 }
2123 
2124 static void
2125 create_if_listener(struct listen_opts *lo)
2126 {
2127 	uint16_t	flags;
2128 
2129 	if (lo->port != 0 && lo->ssl == F_SSL)
2130 		errx(1, "invalid listen option: tls/smtps on same port");
2131 
2132 	if (lo->auth != 0 && !lo->ssl)
2133 		errx(1, "invalid listen option: auth requires tls/smtps");
2134 
2135 	if (lo->pki && !lo->ssl)
2136 		errx(1, "invalid listen option: pki requires tls/smtps");
2137 
2138 	flags = lo->flags;
2139 
2140 	if (lo->port) {
2141 		lo->flags = lo->ssl|lo->auth|flags;
2142 		lo->port = htons(lo->port);
2143 	}
2144 	else {
2145 		if (lo->ssl & F_SMTPS) {
2146 			lo->port = htons(465);
2147 			lo->flags = F_SMTPS|lo->auth|flags;
2148 		}
2149 
2150 		if (!lo->ssl || (lo->ssl & F_STARTTLS)) {
2151 			lo->port = htons(25);
2152 			lo->flags = lo->auth|flags;
2153 			if (lo->ssl & F_STARTTLS)
2154 				lo->flags |= F_STARTTLS;
2155 		}
2156 	}
2157 
2158 	if (interface(lo))
2159 		return;
2160 	if (host_v4(lo))
2161 		return;
2162 	if (host_v6(lo))
2163 		return;
2164 	if (host_dns(lo))
2165 		return;
2166 
2167 	errx(1, "invalid virtual ip or interface: %s", lo->ifx);
2168 }
2169 
2170 static void
2171 config_listener(struct listener *h,  struct listen_opts *lo)
2172 {
2173 	h->fd = -1;
2174 	h->port = lo->port;
2175 	h->flags = lo->flags;
2176 
2177 	if (lo->hostname == NULL)
2178 		lo->hostname = conf->sc_hostname;
2179 
2180 	if (lo->filtername) {
2181 		if (dict_get(&conf->sc_filters, lo->filtername) == NULL) {
2182 			log_warnx("undefined filter: %s", lo->filtername);
2183 			fatalx(NULL);
2184 		}
2185 		(void)strlcpy(h->filter, lo->filtername, sizeof(h->filter));
2186 	}
2187 
2188 	h->pki_name[0] = '\0';
2189 
2190 	if (lo->authtable != NULL)
2191 		(void)strlcpy(h->authtable, lo->authtable->t_name, sizeof(h->authtable));
2192 	if (lo->pki != NULL) {
2193 		if (!lowercase(h->pki_name, lo->pki, sizeof(h->pki_name))) {
2194 			log_warnx("pki name too long: %s", lo->pki);
2195 			fatalx(NULL);
2196 		}
2197 		if (dict_get(conf->sc_pki_dict, h->pki_name) == NULL) {
2198 			log_warnx("pki name not found: %s", lo->pki);
2199 			fatalx(NULL);
2200 		}
2201 	}
2202 
2203 	if (lo->ca != NULL) {
2204 		if (!lowercase(h->ca_name, lo->ca, sizeof(h->ca_name))) {
2205 			log_warnx("ca name too long: %s", lo->ca);
2206 			fatalx(NULL);
2207 		}
2208 		if (dict_get(conf->sc_ca_dict, h->ca_name) == NULL) {
2209 			log_warnx("ca name not found: %s", lo->ca);
2210 			fatalx(NULL);
2211 		}
2212 	}
2213 	if (lo->tag != NULL)
2214 		(void)strlcpy(h->tag, lo->tag, sizeof(h->tag));
2215 
2216 	(void)strlcpy(h->hostname, lo->hostname, sizeof(h->hostname));
2217 	if (lo->hostnametable)
2218 		(void)strlcpy(h->hostnametable, lo->hostnametable->t_name, sizeof(h->hostnametable));
2219 	if (lo->sendertable) {
2220 		(void)strlcpy(h->sendertable, lo->sendertable->t_name, sizeof(h->sendertable));
2221 		if (lo->options & LO_MASQUERADE)
2222 			h->flags |= F_MASQUERADE;
2223 	}
2224 
2225 	if (lo->ssl & F_TLS_VERIFY)
2226 		h->flags |= F_TLS_VERIFY;
2227 
2228 	if (h != conf->sc_sock_listener)
2229 		TAILQ_INSERT_TAIL(conf->sc_listeners, h, entry);
2230 }
2231 
2232 static int
2233 host_v4(struct listen_opts *lo)
2234 {
2235 	struct in_addr		 ina;
2236 	struct sockaddr_in	*sain;
2237 	struct listener		*h;
2238 
2239 	if (lo->family != AF_UNSPEC && lo->family != AF_INET)
2240 		return (0);
2241 
2242 	memset(&ina, 0, sizeof(ina));
2243 	if (inet_pton(AF_INET, lo->ifx, &ina) != 1)
2244 		return (0);
2245 
2246 	h = xcalloc(1, sizeof(*h), "host_v4");
2247 	sain = (struct sockaddr_in *)&h->ss;
2248 	sain->sin_len = sizeof(struct sockaddr_in);
2249 	sain->sin_family = AF_INET;
2250 	sain->sin_addr.s_addr = ina.s_addr;
2251 	sain->sin_port = lo->port;
2252 
2253 	if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
2254 		h->local = 1;
2255 	config_listener(h,  lo);
2256 
2257 	return (1);
2258 }
2259 
2260 static int
2261 host_v6(struct listen_opts *lo)
2262 {
2263 	struct in6_addr		 ina6;
2264 	struct sockaddr_in6	*sin6;
2265 	struct listener		*h;
2266 
2267 	if (lo->family != AF_UNSPEC && lo->family != AF_INET6)
2268 		return (0);
2269 
2270 	memset(&ina6, 0, sizeof(ina6));
2271 	if (inet_pton(AF_INET6, lo->ifx, &ina6) != 1)
2272 		return (0);
2273 
2274 	h = xcalloc(1, sizeof(*h), "host_v6");
2275 	sin6 = (struct sockaddr_in6 *)&h->ss;
2276 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2277 	sin6->sin6_family = AF_INET6;
2278 	sin6->sin6_port = lo->port;
2279 	memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
2280 
2281 	if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
2282 		h->local = 1;
2283 	config_listener(h,  lo);
2284 
2285 	return (1);
2286 }
2287 
2288 static int
2289 host_dns(struct listen_opts *lo)
2290 {
2291 	struct addrinfo		 hints, *res0, *res;
2292 	int			 error, cnt = 0;
2293 	struct sockaddr_in	*sain;
2294 	struct sockaddr_in6	*sin6;
2295 	struct listener		*h;
2296 
2297 	memset(&hints, 0, sizeof(hints));
2298 	hints.ai_family = lo->family;
2299 	hints.ai_socktype = SOCK_STREAM;
2300 	hints.ai_flags = AI_ADDRCONFIG;
2301 	error = getaddrinfo(lo->ifx, NULL, &hints, &res0);
2302 	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
2303 		return (0);
2304 	if (error) {
2305 		log_warnx("warn: host_dns: could not parse \"%s\": %s", lo->ifx,
2306 		    gai_strerror(error));
2307 		return (-1);
2308 	}
2309 
2310 	for (res = res0; res; res = res->ai_next) {
2311 		if (res->ai_family != AF_INET &&
2312 		    res->ai_family != AF_INET6)
2313 			continue;
2314 		h = xcalloc(1, sizeof(*h), "host_dns");
2315 
2316 		h->ss.ss_family = res->ai_family;
2317 		if (res->ai_family == AF_INET) {
2318 			sain = (struct sockaddr_in *)&h->ss;
2319 			sain->sin_len = sizeof(struct sockaddr_in);
2320 			sain->sin_addr.s_addr = ((struct sockaddr_in *)
2321 			    res->ai_addr)->sin_addr.s_addr;
2322 			sain->sin_port = lo->port;
2323 			if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
2324 				h->local = 1;
2325 		} else {
2326 			sin6 = (struct sockaddr_in6 *)&h->ss;
2327 			sin6->sin6_len = sizeof(struct sockaddr_in6);
2328 			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
2329 			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
2330 			sin6->sin6_port = lo->port;
2331 			if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
2332 				h->local = 1;
2333 		}
2334 
2335 		config_listener(h, lo);
2336 
2337 		cnt++;
2338 	}
2339 
2340 	freeaddrinfo(res0);
2341 	return (cnt);
2342 }
2343 
2344 static int
2345 interface(struct listen_opts *lo)
2346 {
2347 	struct ifaddrs *ifap, *p;
2348 	struct sockaddr_in	*sain;
2349 	struct sockaddr_in6	*sin6;
2350 	struct listener		*h;
2351 	int			ret = 0;
2352 
2353 	if (getifaddrs(&ifap) == -1)
2354 		fatal("getifaddrs");
2355 
2356 	for (p = ifap; p != NULL; p = p->ifa_next) {
2357 		if (p->ifa_addr == NULL)
2358 			continue;
2359 		if (strcmp(p->ifa_name, lo->ifx) != 0 &&
2360 		    !is_if_in_group(p->ifa_name, lo->ifx))
2361 			continue;
2362 		if (lo->family != AF_UNSPEC && lo->family != p->ifa_addr->sa_family)
2363 			continue;
2364 
2365 		h = xcalloc(1, sizeof(*h), "interface");
2366 
2367 		switch (p->ifa_addr->sa_family) {
2368 		case AF_INET:
2369 			sain = (struct sockaddr_in *)&h->ss;
2370 			*sain = *(struct sockaddr_in *)p->ifa_addr;
2371 			sain->sin_len = sizeof(struct sockaddr_in);
2372 			sain->sin_port = lo->port;
2373 			if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
2374 				h->local = 1;
2375 			break;
2376 
2377 		case AF_INET6:
2378 			sin6 = (struct sockaddr_in6 *)&h->ss;
2379 			*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
2380 			sin6->sin6_len = sizeof(struct sockaddr_in6);
2381 			sin6->sin6_port = lo->port;
2382 			if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
2383 				h->local = 1;
2384 			break;
2385 
2386 		default:
2387 			free(h);
2388 			continue;
2389 		}
2390 
2391 		config_listener(h, lo);
2392 		ret = 1;
2393 	}
2394 
2395 	freeifaddrs(ifap);
2396 
2397 	return ret;
2398 }
2399 
2400 void
2401 set_local(const char *hostname)
2402 {
2403 	struct table	*t;
2404 
2405 	t = table_create("static", "<localnames>", NULL, NULL);
2406 	t->t_type = T_LIST;
2407 	table_add(t, "localhost", NULL);
2408 	table_add(t, hostname, NULL);
2409 
2410 	set_localaddrs(t);
2411 }
2412 
2413 void
2414 set_localaddrs(struct table *localnames)
2415 {
2416 	struct ifaddrs *ifap, *p;
2417 	struct sockaddr_storage ss;
2418 	struct sockaddr_in	*sain;
2419 	struct sockaddr_in6	*sin6;
2420 	struct table		*t;
2421 	char buf[NI_MAXHOST + 5];
2422 
2423 	t = table_create("static", "<anyhost>", NULL, NULL);
2424 	table_add(t, "local", NULL);
2425 	table_add(t, "0.0.0.0/0", NULL);
2426 	table_add(t, "::/0", NULL);
2427 
2428 	if (getifaddrs(&ifap) == -1)
2429 		fatal("getifaddrs");
2430 
2431 	t = table_create("static", "<localhost>", NULL, NULL);
2432 	table_add(t, "local", NULL);
2433 
2434 	for (p = ifap; p != NULL; p = p->ifa_next) {
2435 		if (p->ifa_addr == NULL)
2436 			continue;
2437 		switch (p->ifa_addr->sa_family) {
2438 		case AF_INET:
2439 			sain = (struct sockaddr_in *)&ss;
2440 			*sain = *(struct sockaddr_in *)p->ifa_addr;
2441 			sain->sin_len = sizeof(struct sockaddr_in);
2442 			table_add(t, ss_to_text(&ss), NULL);
2443 			table_add(localnames, ss_to_text(&ss), NULL);
2444 			(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
2445 			table_add(localnames, buf, NULL);
2446 			break;
2447 
2448 		case AF_INET6:
2449 			sin6 = (struct sockaddr_in6 *)&ss;
2450 			*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
2451 			sin6->sin6_len = sizeof(struct sockaddr_in6);
2452 			table_add(t, ss_to_text(&ss), NULL);
2453 			table_add(localnames, ss_to_text(&ss), NULL);
2454 			(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
2455 			table_add(localnames, buf, NULL);
2456 			(void)snprintf(buf, sizeof buf, "[ipv6:%s]", ss_to_text(&ss));
2457 			table_add(localnames, buf, NULL);
2458 			break;
2459 		}
2460 	}
2461 
2462 	freeifaddrs(ifap);
2463 }
2464 
2465 int
2466 delaytonum(char *str)
2467 {
2468 	unsigned int     factor;
2469 	size_t           len;
2470 	const char      *errstr = NULL;
2471 	int              delay;
2472 
2473 	/* we need at least 1 digit and 1 unit */
2474 	len = strlen(str);
2475 	if (len < 2)
2476 		goto bad;
2477 
2478 	switch(str[len - 1]) {
2479 
2480 	case 's':
2481 		factor = 1;
2482 		break;
2483 
2484 	case 'm':
2485 		factor = 60;
2486 		break;
2487 
2488 	case 'h':
2489 		factor = 60 * 60;
2490 		break;
2491 
2492 	case 'd':
2493 		factor = 24 * 60 * 60;
2494 		break;
2495 
2496 	default:
2497 		goto bad;
2498 	}
2499 
2500 	str[len - 1] = '\0';
2501 	delay = strtonum(str, 1, INT_MAX / factor, &errstr);
2502 	if (errstr)
2503 		goto bad;
2504 
2505 	return (delay * factor);
2506 
2507 bad:
2508 	return (-1);
2509 }
2510 
2511 int
2512 is_if_in_group(const char *ifname, const char *groupname)
2513 {
2514         unsigned int		 len;
2515         struct ifgroupreq        ifgr;
2516         struct ifg_req          *ifg;
2517 	int			 s;
2518 	int			 ret = 0;
2519 
2520 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
2521 		err(1, "socket");
2522 
2523         memset(&ifgr, 0, sizeof(ifgr));
2524         if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ)
2525 		errx(1, "interface name too large");
2526 
2527         if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
2528                 if (errno == EINVAL || errno == ENOTTY)
2529 			goto end;
2530 		err(1, "SIOCGIFGROUP");
2531         }
2532 
2533         len = ifgr.ifgr_len;
2534         ifgr.ifgr_groups = xcalloc(len/sizeof(struct ifg_req),
2535 		sizeof(struct ifg_req), "is_if_in_group");
2536         if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
2537                 err(1, "SIOCGIFGROUP");
2538 
2539         ifg = ifgr.ifgr_groups;
2540         for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
2541                 len -= sizeof(struct ifg_req);
2542 		if (strcmp(ifg->ifgrq_group, groupname) == 0) {
2543 			ret = 1;
2544 			break;
2545 		}
2546         }
2547         free(ifgr.ifgr_groups);
2548 
2549 end:
2550 	close(s);
2551 	return ret;
2552 }
2553 
2554 static struct filter_conf *
2555 create_filter_proc(char *name, char *prog)
2556 {
2557 	struct filter_conf	*f;
2558 	char			*path;
2559 
2560 	if (dict_get(&conf->sc_filters, name)) {
2561 		yyerror("filter \"%s\" already defined", name);
2562 		return (NULL);
2563 	}
2564 
2565 	if (asprintf(&path, "%s/filter-%s", PATH_LIBEXEC, prog) == -1) {
2566 		yyerror("filter \"%s\" asprintf failed", name);
2567 		return (0);
2568 	}
2569 
2570 	f = xcalloc(1, sizeof(*f), "create_filter");
2571 	f->path = path;
2572 	f->name = name;
2573 	f->argv[f->argc++] = name;
2574 
2575 	dict_xset(&conf->sc_filters, name, f);
2576 
2577 	return (f);
2578 }
2579 
2580 static struct filter_conf *
2581 create_filter_chain(char *name)
2582 {
2583 	struct filter_conf	*f;
2584 
2585 	if (dict_get(&conf->sc_filters, name)) {
2586 		yyerror("filter \"%s\" already defined", name);
2587 		return (NULL);
2588 	}
2589 
2590 	f = xcalloc(1, sizeof(*f), "create_filter_chain");
2591 	f->chain = 1;
2592 	f->name = name;
2593 
2594 	dict_xset(&conf->sc_filters, name, f);
2595 
2596 	return (f);
2597 }
2598 
2599 static int
2600 add_filter_arg(struct filter_conf *f, char *arg)
2601 {
2602 	int	i;
2603 
2604 	if (f->argc == MAX_FILTER_ARGS) {
2605 		yyerror("filter \"%s\" is full", f->name);
2606 		return (0);
2607 	}
2608 
2609 	if (f->chain) {
2610 		if (dict_get(&conf->sc_filters, arg) == NULL) {
2611 			yyerror("undefined filter \"%s\"", arg);
2612 			return (0);
2613 		}
2614 		if (dict_get(&conf->sc_filters, arg) == f) {
2615 			yyerror("filter chain cannot contain itself");
2616 			return (0);
2617 		}
2618 		for (i = 0; i < f->argc; ++i)
2619 			if (strcasecmp(f->argv[i], arg) == 0) {
2620 				yyerror("filter chain cannot contain twice the same filter instance");
2621 				return (0);
2622 			}
2623 	}
2624 
2625 	f->argv[f->argc++] = arg;
2626 
2627 	return (1);
2628 }
2629 
2630 static int
2631 config_lo_filter(struct listen_opts *lo, char *filter_name) {
2632 	if (lo->options & LO_FILTER) {
2633 		yyerror("filter already specified");
2634 		return -1;
2635 	}
2636 	lo->options |= LO_FILTER;
2637 	lo->filtername = filter_name;
2638 
2639 	return 0;
2640 }
2641 
2642 static int
2643 config_lo_mask_source(struct listen_opts *lo) {
2644 	if (lo->options & LO_MASKSOURCE) {
2645 		yyerror("mask-source already specified");
2646 		return -1;
2647 	}
2648 	lo->options |= LO_MASKSOURCE;
2649 	lo->flags |= F_MASK_SOURCE;
2650 
2651 	return 0;
2652 }
2653 
2654