GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpd/../parse.y Lines: 0 586 0.0 %
Date: 2017-11-07 Branches: 0 400 0.0 %

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