GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpctl/parse.c Lines: 0 730 0.0 %
Date: 2017-11-07 Branches: 0 541 0.0 %

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#define YYBYACC 1
4
#define YYMAJOR 1
5
#define YYMINOR 9
6
#define YYLEX yylex()
7
#define YYEMPTY -1
8
#define yyclearin (yychar=(YYEMPTY))
9
#define yyerrok (yyerrflag=0)
10
#define YYRECOVERING() (yyerrflag!=0)
11
#define YYPREFIX "yy"
12
#line 25 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
13
#include <sys/types.h>
14
#include <sys/queue.h>
15
#include <sys/tree.h>
16
#include <sys/socket.h>
17
#include <sys/stat.h>
18
#include <sys/ioctl.h>
19
20
#include <net/if.h>
21
#include <netinet/in.h>
22
#include <arpa/inet.h>
23
24
#include <ctype.h>
25
#include <err.h>
26
#include <errno.h>
27
#include <event.h>
28
#include <ifaddrs.h>
29
#include <imsg.h>
30
#include <inttypes.h>
31
#include <limits.h>
32
#include <netdb.h>
33
#include <paths.h>
34
#include <pwd.h>
35
#include <resolv.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <syslog.h>
40
#include <unistd.h>
41
#include <util.h>
42
43
#include <openssl/ssl.h>
44
45
#include "smtpd.h"
46
#include "ssl.h"
47
#include "log.h"
48
49
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
50
static struct file {
51
	TAILQ_ENTRY(file)	 entry;
52
	FILE			*stream;
53
	char			*name;
54
	int			 lineno;
55
	int			 errors;
56
} *file, *topfile;
57
struct file	*pushfile(const char *, int);
58
int		 popfile(void);
59
int		 check_file_secrecy(int, const char *);
60
int		 yyparse(void);
61
int		 yylex(void);
62
int		 kw_cmp(const void *, const void *);
63
int		 lookup(char *);
64
int		 lgetc(int);
65
int		 lungetc(int);
66
int		 findeol(void);
67
int		 yyerror(const char *, ...)
68
    __attribute__((__format__ (printf, 1, 2)))
69
    __attribute__((__nonnull__ (1)));
70
71
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
72
struct sym {
73
	TAILQ_ENTRY(sym)	 entry;
74
	int			 used;
75
	int			 persist;
76
	char			*nam;
77
	char			*val;
78
};
79
int		 symset(const char *, const char *, int);
80
char		*symget(const char *);
81
82
struct smtpd		*conf = NULL;
83
static int		 errors = 0;
84
static uint64_t		 ruleid = 0;
85
86
struct filter_conf	*filter = NULL;
87
struct table		*table = NULL;
88
struct rule		*rule = NULL;
89
struct mta_limits	*limits;
90
static struct pki	*pki;
91
static struct ca	*sca;
92
93
enum listen_options {
94
	LO_FAMILY	= 0x000001,
95
	LO_PORT		= 0x000002,
96
	LO_SSL		= 0x000004,
97
	LO_FILTER      	= 0x000008,
98
	LO_PKI      	= 0x000010,
99
	LO_AUTH      	= 0x000020,
100
	LO_TAG      	= 0x000040,
101
	LO_HOSTNAME   	= 0x000080,
102
	LO_HOSTNAMES   	= 0x000100,
103
	LO_MASKSOURCE  	= 0x000200,
104
	LO_NODSN	= 0x000400,
105
	LO_SENDERS	= 0x000800,
106
	LO_RECEIVEDAUTH = 0x001000,
107
	LO_MASQUERADE	= 0x002000,
108
	LO_CA		= 0x010000
109
};
110
111
static struct listen_opts {
112
	char	       *ifx;
113
	int		family;
114
	in_port_t	port;
115
	uint16_t	ssl;
116
	char	       *filtername;
117
	char	       *pki;
118
	char	       *ca;
119
	uint16_t       	auth;
120
	struct table   *authtable;
121
	char	       *tag;
122
	char	       *hostname;
123
	struct table   *hostnametable;
124
	struct table   *sendertable;
125
	uint16_t	flags;
126
127
	uint32_t       	options;
128
} listen_opts;
129
130
static void	create_sock_listener(struct listen_opts *);
131
static void	create_if_listener(struct listen_opts *);
132
static void	config_listener(struct listener *, struct listen_opts *);
133
static int	host_v4(struct listen_opts *);
134
static int	host_v6(struct listen_opts *);
135
static int	host_dns(struct listen_opts *);
136
static int	interface(struct listen_opts *);
137
138
void		 set_local(const char *);
139
void		 set_localaddrs(struct table *);
140
int		 delaytonum(char *);
141
int		 is_if_in_group(const char *, const char *);
142
143
static int config_lo_filter(struct listen_opts *, char *);
144
static int config_lo_mask_source(struct listen_opts *);
145
146
typedef struct {
147
	union {
148
		int64_t		 number;
149
		struct table	*table;
150
		char		*string;
151
		struct host	*host;
152
		struct mailaddr	*maddr;
153
	} v;
154
	int lineno;
155
} YYSTYPE;
156
157
#line 158 "parse.c"
158
#define AS 257
159
#define QUEUE 258
160
#define COMPRESSION 259
161
#define ENCRYPTION 260
162
#define MAXMESSAGESIZE 261
163
#define MAXMTADEFERRED 262
164
#define LISTEN 263
165
#define ON 264
166
#define ANY 265
167
#define PORT 266
168
#define EXPIRE 267
169
#define TABLE 268
170
#define SMTPS 269
171
#define CERTIFICATE 270
172
#define DOMAIN 271
173
#define BOUNCEWARN 272
174
#define LIMIT 273
175
#define INET4 274
176
#define INET6 275
177
#define NODSN 276
178
#define SESSION 277
179
#define RELAY 278
180
#define BACKUP 279
181
#define VIA 280
182
#define DELIVER 281
183
#define TO 282
184
#define LMTP 283
185
#define MAILDIR 284
186
#define MBOX 285
187
#define RCPTTO 286
188
#define HOSTNAME 287
189
#define HOSTNAMES 288
190
#define ACCEPT 289
191
#define REJECT 290
192
#define INCLUDE 291
193
#define ERROR 292
194
#define MDA 293
195
#define FROM 294
196
#define FOR 295
197
#define SOURCE 296
198
#define MTA 297
199
#define PKI 298
200
#define SCHEDULER 299
201
#define ARROW 300
202
#define AUTH 301
203
#define TLS 302
204
#define LOCAL 303
205
#define VIRTUAL 304
206
#define TAG 305
207
#define TAGGED 306
208
#define ALIAS 307
209
#define FILTER 308
210
#define KEY 309
211
#define CA 310
212
#define DHE 311
213
#define AUTH_OPTIONAL 312
214
#define TLS_REQUIRE 313
215
#define USERBASE 314
216
#define SENDER 315
217
#define SENDERS 316
218
#define MASK_SOURCE 317
219
#define VERIFY 318
220
#define FORWARDONLY 319
221
#define RECIPIENT 320
222
#define CIPHERS 321
223
#define RECEIVEDAUTH 322
224
#define MASQUERADE 323
225
#define SOCKET 324
226
#define SUBADDRESSING_DELIM 325
227
#define AUTHENTICATED 326
228
#define STRING 327
229
#define NUMBER 328
230
#define YYERRCODE 256
231
const short yylhs[] =
232
	{                                        -1,
233
    0,    0,    0,    0,    0,    0,    0,    0,   11,   12,
234
   15,   15,   15,   17,   17,   16,    2,    2,   10,   18,
235
   19,   20,   20,   20,   21,   22,   22,   23,   24,   24,
236
   25,   25,   25,   26,   26,   27,   28,   28,   29,   30,
237
   31,   31,   31,   32,   32,   33,   33,   34,   34,   34,
238
   34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
239
   34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
240
   34,   35,   35,   36,   37,   38,   38,   39,   39,   40,
241
   40,   40,   40,   40,   40,   41,   41,   41,   41,   42,
242
   42,   42,   43,   43,   44,   44,   44,   45,   13,   13,
243
   13,   13,   13,   13,   13,   13,   13,   13,   46,   13,
244
   47,   13,   13,   48,   13,   49,   13,   50,   13,   13,
245
    1,   51,    1,   53,   53,   54,   55,   55,   56,   57,
246
   57,   52,   52,    5,   58,    5,    6,    4,    4,    7,
247
    8,   59,   59,    9,   60,   60,   61,   61,   61,   61,
248
   61,   61,   62,   63,   62,    3,    3,   64,   64,   64,
249
   65,   65,   65,   66,   67,   68,   69,   70,   70,   70,
250
   70,   70,   70,   71,   71,   72,   72,   73,   73,   74,
251
   74,   74,   75,   75,   76,   76,   77,   14,   78,   14,
252
};
253
const short yylen[] =
254
	{                                         2,
255
    0,    2,    3,    3,    3,    3,    3,    3,    2,    3,
256
    1,    1,    0,    2,    0,    2,    1,    1,    3,    2,
257
    1,    3,    1,    0,    2,    2,    0,    2,    2,    0,
258
    1,    1,    2,    2,    0,    2,    2,    0,    2,    1,
259
    2,    2,    2,    2,    0,    2,    1,    1,    1,    2,
260
    2,    2,    1,    2,    1,    1,    2,    2,    2,    1,
261
    1,    2,    2,    2,    2,    2,    1,    1,    1,    2,
262
    3,    1,    1,    2,    2,    2,    0,    2,    0,    2,
263
    2,    2,    2,    2,    2,    2,    1,    1,    2,    2,
264
    2,    0,    2,    1,    2,    2,    0,    0,    3,    2,
265
    2,    2,    4,    2,    2,    2,    3,    3,    0,    7,
266
    0,    4,    3,    0,    4,    0,    4,    0,    4,    2,
267
    3,    0,    6,    1,    1,    3,    1,    3,    1,    1,
268
    3,    1,    1,    1,    0,    4,    3,    1,    1,    2,
269
    2,    1,    1,    2,    2,    0,    3,    4,    3,    5,
270
    6,    5,    2,    0,    5,    1,    0,    4,    3,    3,
271
    4,    3,    3,    3,    3,    1,    2,    1,    1,    1,
272
    1,    1,    1,    2,    0,    1,    1,    2,    0,    1,
273
    1,    0,    1,    1,    2,    0,    0,    6,    0,    3,
274
};
275
const short yydefred[] =
276
	{                                      1,
277
    0,    0,    0,    0,    0,  114,    0,    0,   98,    0,
278
  187,  189,    0,    0,    0,    0,    0,    0,    2,    0,
279
    0,    0,    0,    0,    8,  101,    0,   18,   17,  105,
280
  106,    0,  104,    0,    0,    0,    0,    0,    0,    0,
281
    0,    9,  116,  118,  120,  100,    0,    6,    3,    4,
282
    5,    7,    0,    0,  121,    0,   21,   23,    0,    0,
283
  107,    0,    0,    0,  108,    0,    0,    0,    0,  113,
284
    0,    0,    0,    0,    0,  156,    0,  172,  173,  170,
285
  171,  168,  169,    0,    0,  190,    0,    0,   10,  103,
286
    0,    0,  115,   72,   73,    0,    0,   28,   26,   25,
287
   29,    0,   31,   32,    0,    0,  112,   36,   37,    0,
288
    0,    0,    0,    0,   20,  174,    0,    0,    0,  142,
289
  143,  176,  177,    0,    0,    0,    0,    0,    0,  117,
290
    0,   40,  119,    0,   47,    0,   74,    0,    0,   48,
291
   49,   69,    0,    0,    0,    0,   55,    0,    0,    0,
292
    0,    0,    0,   67,   68,    0,   75,    0,    0,    0,
293
  133,    0,  132,   22,  109,   33,   34,  159,    0,  160,
294
  162,    0,  163,   19,  134,  135,    0,  164,  138,  139,
295
  165,  141,  140,  144,  178,    0,    0,  180,  181,    0,
296
   41,   42,   43,   44,   39,   46,   76,   50,   51,   54,
297
   65,   66,   58,   62,   64,   52,   59,   63,   57,    0,
298
   78,  125,  124,    0,  123,    0,   11,    0,   12,    0,
299
    0,  158,  161,    0,    0,    0,    0,    0,    0,    0,
300
    0,    0,    0,    0,    0,    0,  153,    0,    0,  166,
301
  184,  183,    0,  188,   71,  126,    0,   16,    0,  128,
302
  129,  131,  110,    0,  137,   80,   86,  154,   82,   83,
303
   81,   84,   89,   85,   90,   91,    0,    0,  149,    0,
304
  167,  185,   14,  136,    0,    0,  148,    0,    0,   94,
305
    0,    0,  155,    0,    0,  150,  152,   93,   95,   96,
306
  145,  151,
307
};
308
const short yydgoto[] =
309
	{                                       1,
310
   20,   30,   77,  178,  179,  180,  120,  121,  122,   78,
311
   21,   22,   23,   24,  218,  219,  248,   79,   58,   59,
312
   64,   61,   62,   65,  106,  107,   69,   70,  132,  133,
313
  129,  130,  136,  156,   93,   94,   95,  137,  157,  235,
314
  236,  237,  282,  283,   35,  221,   67,   32,   87,   88,
315
   56,  159,  214,  160,  161,  162,  163,  224,  123,  286,
316
  188,  189,  275,   80,   81,   82,   83,  241,  242,   84,
317
   85,  124,  125,  190,  243,  244,   40,   41,
318
};
319
const short yysindex[] =
320
	{                                      0,
321
  -10,   23, -202, -219, -290,    0, -292, -268,    0, -201,
322
    0,    0, -245, -241, -236, -230, -227,   49,    0,  113,
323
  115,  122,  124,  127,    0,    0, -167,    0,    0,    0,
324
    0, -117,    0, -177, -174, -172, -166, -135, -165,    8,
325
    8,    0,    0,    0,    0,    0, -163,    0,    0,    0,
326
    0,    0, -162, -293,    0,   28,    0,    0,  123, -160,
327
    0, -172, -159, -166,    0, -101, -255, -156, -165,    0,
328
  140,  140,  140,  140,  140,    0, -152,    0,    0,    0,
329
    0,    0,    0,    8, -200,    0, -247,  -95,    0,    0,
330
 -269, -186,    0,    0,    0, -151, -174,    0,    0,    0,
331
    0, -143,    0,    0, -145, -255,    0,    0,    0, -251,
332
 -243, -142,  -54,  -54,    0,    0,  -54,  -54,  -54,    0,
333
    0,    0,    0, -200, -194, -141, -140, -138, -247,    0,
334
 -137,    0,    0, -136,    0, -269,    0, -189, -130,    0,
335
    0,    0, -134,  -54, -133,  -54,    0, -132, -131, -129,
336
  -54, -126,  -54,    0,    0, -186,    0,  -53,   72,   17,
337
    0,   17,    0,    0,    0,    0,    0,    0,  -54,    0,
338
    0,  -54,    0,    0,    0,    0, -128,    0,    0,    0,
339
    0,    0,    0,    0,    0, -139,  -82,    0,    0, -246,
340
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
341
    0,    0,    0,    0,    0,    0,    0,    0,    0, -121,
342
    0,    0,    0, -124,    0,  194,    0, -122,    0, -120,
343
 -255,    0,    0, -151,  144, -119, -118, -114, -113,  -54,
344
  -54, -112, -108, -111, -144, -144,    0, -190, -110,    0,
345
    0,    0, -246,    0,    0,    0,  194,    0,  -53,    0,
346
    0,    0,    0,   93,    0,    0,    0,    0,    0,    0,
347
    0,    0,    0,    0,    0,    0, -107, -106,    0, -105,
348
    0,    0,    0,    0, -233, -207,    0,  -38,  -54,    0,
349
 -233, -233,    0, -104,  -38,    0,    0,    0,    0,    0,
350
    0,    0,};
351
const short yyrindex[] =
352
	{                                      0,
353
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
354
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
355
    0,    0,    0,    0,    0,    0,  214,    0,    0,    0,
356
    0,    0,    0,  102,   37,  216,  217,   -9,  218,   -6,
357
   -5,    0,    0,    0,    0,    0,    0,    0,    0,    0,
358
    0,    0,    0,    0,    0,    0,    0,    0,  219,    0,
359
    0,  216,    0,  217,    0,    0,  220,    0,  218,    0,
360
 -225, -228,  -96,  -49,  -49,    0,    0,    0,    0,    0,
361
    0,    0,    0,   -6,   -7,    0,  222,    0,    0,    0,
362
  223,  224,    0,    0,    0,    0,    0,    0,    0,    0,
363
    0,    0,    0,    0,    0,  220,    0,    0,    0,    0,
364
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
365
    0,    0,    0,   -7,   15,    0,    0,    0,  222,    0,
366
    0,    0,    0,    0,    0,  223,    0,    0,   56,    0,
367
    0,    0,    0,    0,    0,  101,    0,    0,    0,    0,
368
  146,  191,    0,    0,    0,  224,    0,   -8,    0, -116,
369
    0, -115,    0,    0,    0,    0,    0,    0,    0,    0,
370
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
371
    0,    0,    0,    0,    0,   16,    0,    0,    0,  225,
372
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
373
    0,    0,    0,    0,    0,    0,    0,    0,    0,  240,
374
    0,    0,    0,    0,    0,  -91,    0,    0,    0,    0,
375
  220,    0,    0,    0,    0,    0,   -3,    0,    0,    0,
376
    0,    0,  267,    0,   16,   16,    0,    0,    0,    0,
377
    0,    0,  225,    0,    0,    0,  -91,    0,    0,    0,
378
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
379
    0,    0,    0,    0,    0,    0,    0,   19,    0,    0,
380
    0,    0,    0,    0,   20,   22,    0,   22,    0,    0,
381
   20,   20,    0,    0,   22,    0,    0,    0,    0,    0,
382
    0,    0,};
383
const short yygindex[] =
384
	{                                      0,
385
    0,    0,  107, -102,    0,    0,    0,    0,    0,    0,
386
    0,    0,    0,    0,   75,    0,   -4,    0,  141,    0,
387
    0,  177,    0,  176,    0,  -88,    0,  172,    0,    0,
388
    0,  116,    0,    0,    0,    0,    0,  106,   88, -176,
389
    0,  -90,    0, -161,    0,    0,    0,    0,    0,    0,
390
    0,   25,    0,    0,   38,    0,   35,    0,    0, -232,
391
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
392
  -28,    0,  135,    0,    0,   24,    0,    0,
393
};
394
#define YYTABLESIZE 586
395
const short yytable[] =
396
	{                                      19,
397
  111,  129,  179,  175,  175,  177,   87,  213,  127,  130,
398
  157,  181,   86,  168,  182,  183,  184,  167,  103,  104,
399
  239,  171,  126,  226,  182,   92,  216,  172,  147,   97,
400
   91,  146,   25,   92,   33,  129,  157,   31,  134,  157,
401
   76,  202,  157,  204,  169,  287,   24,  135,  208,  284,
402
  210,  170,  292,  229,  230,  116,   26,   27,   34,  173,
403
  217,  127,  231,  128,  232,   53,  222,  279,  176,  223,
404
  157,  105,  240,  157,  157,   36,  234,  157,  285,  138,
405
   24,   42,  139,  186,  280,   43,  187,  140,  141,  142,
406
   44,   37,  267,  268,  269,   38,   45,   39,  281,   46,
407
  143,  144,  270,  117,  281,  281,  118,   28,   29,   47,
408
   60,  145,  226,  119,  146,  147,  129,  226,  148,  289,
409
  290,  149,   48,  150,   49,  151,  152,  260,  261,  153,
410
  154,   50,  253,   51,  227,  155,   52,  198,  199,  227,
411
  228,   53,  229,  230,  265,  266,   54,  229,  230,   55,
412
   96,  231,   57,  232,   60,   61,  231,  233,  232,   66,
413
   63,   68,  233,   89,   90,  234,   97,   98,  100,  102,
414
  234,  108,   76,  115,  131,  158,  288,  110,  111,  112,
415
  113,  114,  166,  165,  174,  191,  192,  200,  193,  195,
416
  196,  209,  201,  203,  205,  206,  215,  207,  225,  238,
417
   56,  245,  246,  247,  249,  255,  251,  256,  257,  263,
418
   13,   13,  258,  259,  262,  264,  271,  274,  284,  276,
419
  277,  278,  291,  102,  122,   27,   30,   38,   99,   35,
420
  157,   45,   77,   79,  186,   15,  220,  164,   99,  101,
421
  109,  197,  273,  211,  194,    2,  212,    3,  254,   70,
422
    4,    5,    6,   87,  252,  250,    7,    8,  185,  179,
423
  175,    9,   10,   87,  111,  111,  272,    0,    0,    0,
424
  179,  175,  175,  179,  175,   87,   88,  157,   11,   12,
425
   13,  182,   92,   87,   87,  147,   97,   14,  146,    0,
426
    0,    0,   87,    0,   87,    0,    0,  175,   87,   15,
427
  175,   71,   72,    0,    0,    0,   87,  175,    0,    0,
428
   16,  179,  175,   73,   17,   87,   18,  111,  129,  157,
429
  157,   53,   74,    0,   53,    0,    0,   75,    0,   53,
430
   53,   53,    0,  182,   92,    0,    0,  147,   97,    0,
431
  146,    0,   53,   53,    0,    0,    0,    0,    0,    0,
432
    0,    0,    0,   53,    0,    0,   53,   53,    0,    0,
433
   53,    0,    0,   53,    0,   53,   60,   53,   53,   60,
434
    0,   53,   53,    0,   60,   60,   60,   53,    0,    0,
435
    0,    0,    0,    0,    0,    0,    0,   60,   60,    0,
436
    0,    0,    0,    0,    0,    0,    0,    0,   60,    0,
437
    0,   60,   60,    0,    0,   60,    0,    0,   60,    0,
438
   60,   61,   60,   60,   61,    0,   60,   60,    0,   61,
439
   61,   61,   60,    0,    0,    0,    0,    0,    0,    0,
440
    0,    0,   61,   61,    0,    0,    0,    0,    0,    0,
441
    0,    0,    0,   61,    0,    0,   61,   61,    0,    0,
442
   61,    0,    0,   61,    0,   61,   56,   61,   61,   56,
443
    0,   61,   61,    0,   56,   56,   56,   61,    0,    0,
444
    0,    0,    0,    0,    0,    0,    0,   56,   56,    0,
445
    0,    0,    0,    0,    0,    0,    0,    0,   56,    0,
446
    0,   56,   56,    0,    0,   56,    0,    0,   56,    0,
447
   56,    0,   56,   56,    0,   70,   56,   56,   70,    0,
448
    0,    0,   56,   70,   70,   70,    0,    0,    0,    0,
449
    0,    0,    0,   88,    0,    0,   70,   70,    0,    0,
450
    0,    0,    0,   88,    0,    0,    0,   70,    0,    0,
451
   70,   70,    0,    0,   70,   88,    0,   70,    0,   70,
452
    0,   70,   70,   88,   88,   70,   70,    0,    0,    0,
453
    0,   70,   88,    0,   88,    0,    0,    0,   88,    0,
454
    0,    0,    0,    0,    0,    0,   88,    0,    0,    0,
455
    0,    0,    0,    0,    0,   88,
456
};
457
const short yycheck[] =
458
	{                                      10,
459
   10,   10,   10,   10,   10,   60,   10,   61,  125,  125,
460
   60,  114,   41,  265,  117,  118,  119,  106,  274,  275,
461
  267,  265,  270,  257,   10,   10,   10,  271,   10,   10,
462
  324,   10,   10,  327,  327,   44,  265,  328,  308,  265,
463
   33,  144,  271,  146,  296,  278,   10,  317,  151,  257,
464
  153,  303,  285,  287,  288,   84,  259,  260,  327,  303,
465
   44,  309,  296,  311,  298,   10,  169,  301,  123,  172,
466
  296,  327,  319,  123,  303,  277,  310,  303,  286,  266,
467
   44,  327,  269,  278,  318,  327,  281,  274,  275,  276,
468
  327,  293,  283,  284,  285,  297,  327,  299,  275,  327,
469
  287,  288,  293,  304,  281,  282,  307,  327,  328,   61,
470
   10,  298,  257,  314,  301,  302,  125,  257,  305,  281,
471
  282,  308,   10,  310,   10,  312,  313,  230,  231,  316,
472
  317,   10,  221,   10,  279,  322,   10,  327,  328,  279,
473
  280,  309,  287,  288,  235,  236,  264,  287,  288,  327,
474
  123,  296,  327,  298,  327,   10,  296,  302,  298,  295,
475
  327,  327,  302,  327,  327,  310,   44,  328,  328,  271,
476
  310,  328,   33,  326,  270,  327,  279,   71,   72,   73,
477
   74,   75,  328,  327,  327,  327,  327,  318,  327,  327,
478
  327,  318,  327,  327,  327,  327,  125,  327,  327,  282,
479
   10,  323,  327,   10,  327,   62,  327,  327,  327,  318,
480
  327,  327,  327,  327,  327,  327,  327,  125,  257,  327,
481
  327,  327,  327,   10,  123,   10,   10,   10,   10,   10,
482
  327,   10,   10,   10,   10,  327,  162,   97,   62,   64,
483
   69,  136,  247,  156,  129,  256,  300,  258,  224,   10,
484
  261,  262,  263,  257,  220,  218,  267,  268,  124,  267,
485
  267,  272,  273,  267,  274,  275,  243,   -1,   -1,   -1,
486
  278,  278,  327,  281,  281,  279,   10,  327,  289,  290,
487
  291,  267,  267,  287,  288,  267,  267,  298,  267,   -1,
488
   -1,   -1,  296,   -1,  298,   -1,   -1,  304,  302,  310,
489
  307,  294,  295,   -1,   -1,   -1,  310,  314,   -1,   -1,
490
  321,  319,  319,  306,  325,  319,  327,  327,  327,  326,
491
  326,  266,  315,   -1,  269,   -1,   -1,  320,   -1,  274,
492
  275,  276,   -1,  319,  319,   -1,   -1,  319,  319,   -1,
493
  319,   -1,  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,
494
   -1,   -1,   -1,  298,   -1,   -1,  301,  302,   -1,   -1,
495
  305,   -1,   -1,  308,   -1,  310,  266,  312,  313,  269,
496
   -1,  316,  317,   -1,  274,  275,  276,  322,   -1,   -1,
497
   -1,   -1,   -1,   -1,   -1,   -1,   -1,  287,  288,   -1,
498
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  298,   -1,
499
   -1,  301,  302,   -1,   -1,  305,   -1,   -1,  308,   -1,
500
  310,  266,  312,  313,  269,   -1,  316,  317,   -1,  274,
501
  275,  276,  322,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
502
   -1,   -1,  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,
503
   -1,   -1,   -1,  298,   -1,   -1,  301,  302,   -1,   -1,
504
  305,   -1,   -1,  308,   -1,  310,  266,  312,  313,  269,
505
   -1,  316,  317,   -1,  274,  275,  276,  322,   -1,   -1,
506
   -1,   -1,   -1,   -1,   -1,   -1,   -1,  287,  288,   -1,
507
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  298,   -1,
508
   -1,  301,  302,   -1,   -1,  305,   -1,   -1,  308,   -1,
509
  310,   -1,  312,  313,   -1,  266,  316,  317,  269,   -1,
510
   -1,   -1,  322,  274,  275,  276,   -1,   -1,   -1,   -1,
511
   -1,   -1,   -1,  257,   -1,   -1,  287,  288,   -1,   -1,
512
   -1,   -1,   -1,  267,   -1,   -1,   -1,  298,   -1,   -1,
513
  301,  302,   -1,   -1,  305,  279,   -1,  308,   -1,  310,
514
   -1,  312,  313,  287,  288,  316,  317,   -1,   -1,   -1,
515
   -1,  322,  296,   -1,  298,   -1,   -1,   -1,  302,   -1,
516
   -1,   -1,   -1,   -1,   -1,   -1,  310,   -1,   -1,   -1,
517
   -1,   -1,   -1,   -1,   -1,  319,
518
};
519
#define YYFINAL 1
520
#ifndef YYDEBUG
521
#define YYDEBUG 0
522
#endif
523
#define YYMAXTOKEN 328
524
#if YYDEBUG
525
const char * const yyname[] =
526
	{
527
"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
528
0,0,"'!'",0,0,0,0,0,0,0,0,0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'<'","'='",
529
"'>'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
530
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,
531
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
532
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
533
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
534
0,"AS","QUEUE","COMPRESSION","ENCRYPTION","MAXMESSAGESIZE","MAXMTADEFERRED",
535
"LISTEN","ON","ANY","PORT","EXPIRE","TABLE","SMTPS","CERTIFICATE","DOMAIN",
536
"BOUNCEWARN","LIMIT","INET4","INET6","NODSN","SESSION","RELAY","BACKUP","VIA",
537
"DELIVER","TO","LMTP","MAILDIR","MBOX","RCPTTO","HOSTNAME","HOSTNAMES","ACCEPT",
538
"REJECT","INCLUDE","ERROR","MDA","FROM","FOR","SOURCE","MTA","PKI","SCHEDULER",
539
"ARROW","AUTH","TLS","LOCAL","VIRTUAL","TAG","TAGGED","ALIAS","FILTER","KEY",
540
"CA","DHE","AUTH_OPTIONAL","TLS_REQUIRE","USERBASE","SENDER","SENDERS",
541
"MASK_SOURCE","VERIFY","FORWARDONLY","RECIPIENT","CIPHERS","RECEIVEDAUTH",
542
"MASQUERADE","SOCKET","SUBADDRESSING_DELIM","AUTHENTICATED","STRING","NUMBER",
543
};
544
const char * const yyrule[] =
545
	{"$accept : grammar",
546
"grammar :",
547
"grammar : grammar '\\n'",
548
"grammar : grammar include '\\n'",
549
"grammar : grammar varset '\\n'",
550
"grammar : grammar main '\\n'",
551
"grammar : grammar table '\\n'",
552
"grammar : grammar rule '\\n'",
553
"grammar : grammar error '\\n'",
554
"include : INCLUDE STRING",
555
"varset : STRING '=' STRING",
556
"comma : ','",
557
"comma : nl",
558
"comma :",
559
"optnl : '\\n' optnl",
560
"optnl :",
561
"nl : '\\n' optnl",
562
"size : NUMBER",
563
"size : STRING",
564
"tagged : TAGGED negation STRING",
565
"authenticated : negation AUTHENTICATED",
566
"bouncedelay : STRING",
567
"bouncedelays : bouncedelays ',' bouncedelay",
568
"bouncedelays : bouncedelay",
569
"bouncedelays :",
570
"opt_limit_mda : STRING NUMBER",
571
"limits_session : opt_limit_session limits_session",
572
"limits_session :",
573
"opt_limit_session : STRING NUMBER",
574
"limits_mda : opt_limit_mda limits_mda",
575
"limits_mda :",
576
"opt_limit_mta : INET4",
577
"opt_limit_mta : INET6",
578
"opt_limit_mta : STRING NUMBER",
579
"limits_mta : opt_limit_mta limits_mta",
580
"limits_mta :",
581
"opt_limit_scheduler : STRING NUMBER",
582
"limits_scheduler : opt_limit_scheduler limits_scheduler",
583
"limits_scheduler :",
584
"opt_ca : CERTIFICATE STRING",
585
"ca : opt_ca",
586
"opt_pki : CERTIFICATE STRING",
587
"opt_pki : KEY STRING",
588
"opt_pki : DHE STRING",
589
"pki : opt_pki pki",
590
"pki :",
591
"opt_sock_listen : FILTER STRING",
592
"opt_sock_listen : MASK_SOURCE",
593
"opt_if_listen : INET4",
594
"opt_if_listen : INET6",
595
"opt_if_listen : PORT STRING",
596
"opt_if_listen : PORT NUMBER",
597
"opt_if_listen : FILTER STRING",
598
"opt_if_listen : SMTPS",
599
"opt_if_listen : SMTPS VERIFY",
600
"opt_if_listen : TLS",
601
"opt_if_listen : TLS_REQUIRE",
602
"opt_if_listen : TLS_REQUIRE VERIFY",
603
"opt_if_listen : PKI STRING",
604
"opt_if_listen : CA STRING",
605
"opt_if_listen : AUTH",
606
"opt_if_listen : AUTH_OPTIONAL",
607
"opt_if_listen : AUTH tables",
608
"opt_if_listen : AUTH_OPTIONAL tables",
609
"opt_if_listen : TAG STRING",
610
"opt_if_listen : HOSTNAME STRING",
611
"opt_if_listen : HOSTNAMES tables",
612
"opt_if_listen : MASK_SOURCE",
613
"opt_if_listen : RECEIVEDAUTH",
614
"opt_if_listen : NODSN",
615
"opt_if_listen : SENDERS tables",
616
"opt_if_listen : SENDERS tables MASQUERADE",
617
"listener_type : socket_listener",
618
"listener_type : if_listener",
619
"socket_listener : SOCKET sock_listen",
620
"if_listener : STRING if_listen",
621
"sock_listen : opt_sock_listen sock_listen",
622
"sock_listen :",
623
"if_listen : opt_if_listen if_listen",
624
"if_listen :",
625
"opt_relay_common : AS STRING",
626
"opt_relay_common : SOURCE tables",
627
"opt_relay_common : HOSTNAME STRING",
628
"opt_relay_common : HOSTNAMES tables",
629
"opt_relay_common : PKI STRING",
630
"opt_relay_common : CA STRING",
631
"opt_relay : BACKUP STRING",
632
"opt_relay : BACKUP",
633
"opt_relay : TLS",
634
"opt_relay : TLS VERIFY",
635
"relay : opt_relay_common relay",
636
"relay : opt_relay relay",
637
"relay :",
638
"opt_relay_via : AUTH tables",
639
"opt_relay_via : VERIFY",
640
"relay_via : opt_relay_common relay_via",
641
"relay_via : opt_relay_via relay_via",
642
"relay_via :",
643
"$$1 :",
644
"main : BOUNCEWARN $$1 bouncedelays",
645
"main : SUBADDRESSING_DELIM STRING",
646
"main : QUEUE COMPRESSION",
647
"main : QUEUE ENCRYPTION",
648
"main : QUEUE ENCRYPTION KEY STRING",
649
"main : EXPIRE STRING",
650
"main : MAXMESSAGESIZE size",
651
"main : MAXMTADEFERRED NUMBER",
652
"main : LIMIT SESSION limits_session",
653
"main : LIMIT MDA limits_mda",
654
"$$2 :",
655
"main : LIMIT MTA FOR DOMAIN STRING $$2 limits_mta",
656
"$$3 :",
657
"main : LIMIT MTA $$3 limits_mta",
658
"main : LIMIT SCHEDULER limits_scheduler",
659
"$$4 :",
660
"main : LISTEN $$4 ON listener_type",
661
"$$5 :",
662
"main : PKI STRING $$5 pki",
663
"$$6 :",
664
"main : CA STRING $$6 ca",
665
"main : CIPHERS STRING",
666
"table : TABLE STRING STRING",
667
"$$7 :",
668
"table : TABLE STRING $$7 '{' tableval_list '}'",
669
"assign : '='",
670
"assign : ARROW",
671
"keyval : STRING assign STRING",
672
"keyval_list : keyval",
673
"keyval_list : keyval comma keyval_list",
674
"stringel : STRING",
675
"string_list : stringel",
676
"string_list : stringel comma string_list",
677
"tableval_list : string_list",
678
"tableval_list : keyval_list",
679
"tablenew : STRING",
680
"$$8 :",
681
"tablenew : '{' $$8 tableval_list '}'",
682
"tableref : '<' STRING '>'",
683
"tables : tablenew",
684
"tables : tableref",
685
"alias : ALIAS tables",
686
"virtual : VIRTUAL tables",
687
"usermapping : alias",
688
"usermapping : virtual",
689
"userbase : USERBASE tables",
690
"deliver_as : AS STRING",
691
"deliver_as :",
692
"deliver_action : DELIVER TO MAILDIR",
693
"deliver_action : DELIVER TO MAILDIR STRING",
694
"deliver_action : DELIVER TO MBOX",
695
"deliver_action : DELIVER TO LMTP STRING deliver_as",
696
"deliver_action : DELIVER TO LMTP STRING RCPTTO deliver_as",
697
"deliver_action : DELIVER TO MDA STRING deliver_as",
698
"relay_action : RELAY relay",
699
"$$9 :",
700
"relay_action : RELAY VIA STRING $$9 relay_via",
701
"negation : '!'",
702
"negation :",
703
"from : FROM negation SOURCE tables",
704
"from : FROM negation ANY",
705
"from : FROM negation LOCAL",
706
"for : FOR negation DOMAIN tables",
707
"for : FOR negation ANY",
708
"for : FOR negation LOCAL",
709
"sender : SENDER negation tables",
710
"recipient : RECIPIENT negation tables",
711
"forwardonly : FORWARDONLY",
712
"expire : EXPIRE STRING",
713
"opt_decision : sender",
714
"opt_decision : recipient",
715
"opt_decision : from",
716
"opt_decision : for",
717
"opt_decision : tagged",
718
"opt_decision : authenticated",
719
"decision : opt_decision decision",
720
"decision :",
721
"opt_lookup : userbase",
722
"opt_lookup : usermapping",
723
"lookup : opt_lookup lookup",
724
"lookup :",
725
"action : deliver_action",
726
"action : relay_action",
727
"action :",
728
"opt_accept : expire",
729
"opt_accept : forwardonly",
730
"accept_params : opt_accept accept_params",
731
"accept_params :",
732
"$$10 :",
733
"rule : ACCEPT $$10 decision lookup action accept_params",
734
"$$11 :",
735
"rule : REJECT $$11 decision",
736
};
737
#endif
738
#ifdef YYSTACKSIZE
739
#undef YYMAXDEPTH
740
#define YYMAXDEPTH YYSTACKSIZE
741
#else
742
#ifdef YYMAXDEPTH
743
#define YYSTACKSIZE YYMAXDEPTH
744
#else
745
#define YYSTACKSIZE 10000
746
#define YYMAXDEPTH 10000
747
#endif
748
#endif
749
#define YYINITSTACKSIZE 200
750
/* LINTUSED */
751
int yydebug;
752
int yynerrs;
753
int yyerrflag;
754
int yychar;
755
short *yyssp;
756
YYSTYPE *yyvsp;
757
YYSTYPE yyval;
758
YYSTYPE yylval;
759
short *yyss;
760
short *yysslim;
761
YYSTYPE *yyvs;
762
unsigned int yystacksize;
763
int yyparse(void);
764
#line 1423 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
765
766
struct keywords {
767
	const char	*k_name;
768
	int		 k_val;
769
};
770
771
int
772
yyerror(const char *fmt, ...)
773
{
774
	va_list		 ap;
775
	char		*msg;
776
777
	file->errors++;
778
	va_start(ap, fmt);
779
	if (vasprintf(&msg, fmt, ap) == -1)
780
		fatalx("yyerror vasprintf");
781
	va_end(ap);
782
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
783
	free(msg);
784
	return (0);
785
}
786
787
int
788
kw_cmp(const void *k, const void *e)
789
{
790
	return (strcmp(k, ((const struct keywords *)e)->k_name));
791
}
792
793
int
794
lookup(char *s)
795
{
796
	/* this has to be sorted always */
797
	static const struct keywords keywords[] = {
798
		{ "accept",		ACCEPT },
799
		{ "alias",		ALIAS },
800
		{ "any",		ANY },
801
		{ "as",			AS },
802
		{ "auth",		AUTH },
803
		{ "auth-optional",     	AUTH_OPTIONAL },
804
		{ "authenticated",     	AUTHENTICATED },
805
		{ "backup",		BACKUP },
806
		{ "bounce-warn",	BOUNCEWARN },
807
		{ "ca",			CA },
808
		{ "certificate",	CERTIFICATE },
809
		{ "ciphers",		CIPHERS },
810
		{ "compression",	COMPRESSION },
811
		{ "deliver",		DELIVER },
812
		{ "dhe",		DHE },
813
		{ "domain",		DOMAIN },
814
		{ "encryption",		ENCRYPTION },
815
		{ "expire",		EXPIRE },
816
		{ "filter",		FILTER },
817
		{ "for",		FOR },
818
		{ "forward-only",      	FORWARDONLY },
819
		{ "from",		FROM },
820
		{ "hostname",		HOSTNAME },
821
		{ "hostnames",		HOSTNAMES },
822
		{ "include",		INCLUDE },
823
		{ "inet4",		INET4 },
824
		{ "inet6",		INET6 },
825
		{ "key",		KEY },
826
		{ "limit",		LIMIT },
827
		{ "listen",		LISTEN },
828
		{ "lmtp",		LMTP },
829
		{ "local",		LOCAL },
830
		{ "maildir",		MAILDIR },
831
		{ "mask-source",	MASK_SOURCE },
832
		{ "masquerade",		MASQUERADE },
833
		{ "max-message-size",  	MAXMESSAGESIZE },
834
		{ "max-mta-deferred",  	MAXMTADEFERRED },
835
		{ "mbox",		MBOX },
836
		{ "mda",		MDA },
837
		{ "mta",		MTA },
838
		{ "no-dsn",		NODSN },
839
		{ "on",			ON },
840
		{ "pki",		PKI },
841
		{ "port",		PORT },
842
		{ "queue",		QUEUE },
843
		{ "rcpt-to",		RCPTTO },
844
		{ "received-auth",     	RECEIVEDAUTH },
845
		{ "recipient",		RECIPIENT },
846
		{ "reject",		REJECT },
847
		{ "relay",		RELAY },
848
		{ "scheduler",		SCHEDULER },
849
		{ "sender",    		SENDER },
850
		{ "senders",   		SENDERS },
851
		{ "session",   		SESSION },
852
		{ "smtps",		SMTPS },
853
		{ "socket",		SOCKET },
854
		{ "source",		SOURCE },
855
		{ "subaddressing-delimiter",	SUBADDRESSING_DELIM },
856
		{ "table",		TABLE },
857
		{ "tag",		TAG },
858
		{ "tagged",		TAGGED },
859
		{ "tls",		TLS },
860
		{ "tls-require",       	TLS_REQUIRE },
861
		{ "to",			TO },
862
		{ "userbase",		USERBASE },
863
		{ "verify",		VERIFY },
864
		{ "via",		VIA },
865
		{ "virtual",		VIRTUAL },
866
	};
867
	const struct keywords	*p;
868
869
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
870
	    sizeof(keywords[0]), kw_cmp);
871
872
	if (p)
873
		return (p->k_val);
874
	else
875
		return (STRING);
876
}
877
878
#define MAXPUSHBACK	128
879
880
unsigned char	*parsebuf;
881
int		 parseindex;
882
unsigned char	 pushback_buffer[MAXPUSHBACK];
883
int		 pushback_index = 0;
884
885
int
886
lgetc(int quotec)
887
{
888
	int		c, next;
889
890
	if (parsebuf) {
891
		/* Read character from the parsebuffer instead of input. */
892
		if (parseindex >= 0) {
893
			c = parsebuf[parseindex++];
894
			if (c != '\0')
895
				return (c);
896
			parsebuf = NULL;
897
		} else
898
			parseindex++;
899
	}
900
901
	if (pushback_index)
902
		return (pushback_buffer[--pushback_index]);
903
904
	if (quotec) {
905
		if ((c = getc(file->stream)) == EOF) {
906
			yyerror("reached end of file while parsing "
907
			    "quoted string");
908
			if (file == topfile || popfile() == EOF)
909
				return (EOF);
910
			return (quotec);
911
		}
912
		return (c);
913
	}
914
915
	while ((c = getc(file->stream)) == '\\') {
916
		next = getc(file->stream);
917
		if (next != '\n') {
918
			c = next;
919
			break;
920
		}
921
		yylval.lineno = file->lineno;
922
		file->lineno++;
923
	}
924
925
	while (c == EOF) {
926
		if (file == topfile || popfile() == EOF)
927
			return (EOF);
928
		c = getc(file->stream);
929
	}
930
	return (c);
931
}
932
933
int
934
lungetc(int c)
935
{
936
	if (c == EOF)
937
		return (EOF);
938
	if (parsebuf) {
939
		parseindex--;
940
		if (parseindex >= 0)
941
			return (c);
942
	}
943
	if (pushback_index < MAXPUSHBACK-1)
944
		return (pushback_buffer[pushback_index++] = c);
945
	else
946
		return (EOF);
947
}
948
949
int
950
findeol(void)
951
{
952
	int	c;
953
954
	parsebuf = NULL;
955
	pushback_index = 0;
956
957
	/* skip to either EOF or the first real EOL */
958
	while (1) {
959
		c = lgetc(0);
960
		if (c == '\n') {
961
			file->lineno++;
962
			break;
963
		}
964
		if (c == EOF)
965
			break;
966
	}
967
	return (ERROR);
968
}
969
970
int
971
yylex(void)
972
{
973
	unsigned char	 buf[8096];
974
	unsigned char	*p, *val;
975
	int		 quotec, next, c;
976
	int		 token;
977
978
top:
979
	p = buf;
980
	while ((c = lgetc(0)) == ' ' || c == '\t')
981
		; /* nothing */
982
983
	yylval.lineno = file->lineno;
984
	if (c == '#')
985
		while ((c = lgetc(0)) != '\n' && c != EOF)
986
			; /* nothing */
987
	if (c == '$' && parsebuf == NULL) {
988
		while (1) {
989
			if ((c = lgetc(0)) == EOF)
990
				return (0);
991
992
			if (p + 1 >= buf + sizeof(buf) - 1) {
993
				yyerror("string too long");
994
				return (findeol());
995
			}
996
			if (isalnum(c) || c == '_') {
997
				*p++ = c;
998
				continue;
999
			}
1000
			*p = '\0';
1001
			lungetc(c);
1002
			break;
1003
		}
1004
		val = symget(buf);
1005
		if (val == NULL) {
1006
			yyerror("macro '%s' not defined", buf);
1007
			return (findeol());
1008
		}
1009
		parsebuf = val;
1010
		parseindex = 0;
1011
		goto top;
1012
	}
1013
1014
	switch (c) {
1015
	case '\'':
1016
	case '"':
1017
		quotec = c;
1018
		while (1) {
1019
			if ((c = lgetc(quotec)) == EOF)
1020
				return (0);
1021
			if (c == '\n') {
1022
				file->lineno++;
1023
				continue;
1024
			} else if (c == '\\') {
1025
				if ((next = lgetc(quotec)) == EOF)
1026
					return (0);
1027
				if (next == quotec || c == ' ' || c == '\t')
1028
					c = next;
1029
				else if (next == '\n') {
1030
					file->lineno++;
1031
					continue;
1032
				} else
1033
					lungetc(next);
1034
			} else if (c == quotec) {
1035
				*p = '\0';
1036
				break;
1037
			} else if (c == '\0') {
1038
				yyerror("syntax error");
1039
				return (findeol());
1040
			}
1041
			if (p + 1 >= buf + sizeof(buf) - 1) {
1042
				yyerror("string too long");
1043
				return (findeol());
1044
			}
1045
			*p++ = c;
1046
		}
1047
		yylval.v.string = strdup(buf);
1048
		if (yylval.v.string == NULL)
1049
			err(1, "yylex: strdup");
1050
		return (STRING);
1051
	}
1052
1053
#define allowed_to_end_number(x) \
1054
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1055
1056
	if (c == '-' || isdigit(c)) {
1057
		do {
1058
			*p++ = c;
1059
			if ((unsigned)(p-buf) >= sizeof(buf)) {
1060
				yyerror("string too long");
1061
				return (findeol());
1062
			}
1063
		} while ((c = lgetc(0)) != EOF && isdigit(c));
1064
		lungetc(c);
1065
		if (p == buf + 1 && buf[0] == '-')
1066
			goto nodigits;
1067
		if (c == EOF || allowed_to_end_number(c)) {
1068
			const char *errstr = NULL;
1069
1070
			*p = '\0';
1071
			yylval.v.number = strtonum(buf, LLONG_MIN,
1072
			    LLONG_MAX, &errstr);
1073
			if (errstr) {
1074
				yyerror("\"%s\" invalid number: %s",
1075
				    buf, errstr);
1076
				return (findeol());
1077
			}
1078
			return (NUMBER);
1079
		} else {
1080
nodigits:
1081
			while (p > buf + 1)
1082
				lungetc(*--p);
1083
			c = *--p;
1084
			if (c == '-')
1085
				return (c);
1086
		}
1087
	}
1088
1089
	if (c == '=') {
1090
		if ((c = lgetc(0)) != EOF && c == '>')
1091
			return (ARROW);
1092
		lungetc(c);
1093
		c = '=';
1094
	}
1095
1096
#define allowed_in_string(x) \
1097
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1098
	x != '{' && x != '}' && x != '<' && x != '>' && \
1099
	x != '!' && x != '=' && x != '#' && \
1100
	x != ','))
1101
1102
	if (isalnum(c) || c == ':' || c == '_') {
1103
		do {
1104
			*p++ = c;
1105
			if ((unsigned)(p-buf) >= sizeof(buf)) {
1106
				yyerror("string too long");
1107
				return (findeol());
1108
			}
1109
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
1110
		lungetc(c);
1111
		*p = '\0';
1112
		if ((token = lookup(buf)) == STRING)
1113
			if ((yylval.v.string = strdup(buf)) == NULL)
1114
				err(1, "yylex: strdup");
1115
		return (token);
1116
	}
1117
	if (c == '\n') {
1118
		yylval.lineno = file->lineno;
1119
		file->lineno++;
1120
	}
1121
	if (c == EOF)
1122
		return (0);
1123
	return (c);
1124
}
1125
1126
int
1127
check_file_secrecy(int fd, const char *fname)
1128
{
1129
	struct stat	st;
1130
1131
	if (fstat(fd, &st)) {
1132
		log_warn("warn: cannot stat %s", fname);
1133
		return (-1);
1134
	}
1135
	if (st.st_uid != 0 && st.st_uid != getuid()) {
1136
		log_warnx("warn: %s: owner not root or current user", fname);
1137
		return (-1);
1138
	}
1139
	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
1140
		log_warnx("warn: %s: group/world readable/writeable", fname);
1141
		return (-1);
1142
	}
1143
	return (0);
1144
}
1145
1146
struct file *
1147
pushfile(const char *name, int secret)
1148
{
1149
	struct file	*nfile;
1150
1151
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
1152
		log_warn("warn: malloc");
1153
		return (NULL);
1154
	}
1155
	if ((nfile->name = strdup(name)) == NULL) {
1156
		log_warn("warn: malloc");
1157
		free(nfile);
1158
		return (NULL);
1159
	}
1160
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
1161
		log_warn("warn: %s", nfile->name);
1162
		free(nfile->name);
1163
		free(nfile);
1164
		return (NULL);
1165
	} else if (secret &&
1166
	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
1167
		fclose(nfile->stream);
1168
		free(nfile->name);
1169
		free(nfile);
1170
		return (NULL);
1171
	}
1172
	nfile->lineno = 1;
1173
	TAILQ_INSERT_TAIL(&files, nfile, entry);
1174
	return (nfile);
1175
}
1176
1177
int
1178
popfile(void)
1179
{
1180
	struct file	*prev;
1181
1182
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
1183
		prev->errors += file->errors;
1184
1185
	TAILQ_REMOVE(&files, file, entry);
1186
	fclose(file->stream);
1187
	free(file->name);
1188
	free(file);
1189
	file = prev;
1190
	return (file ? 0 : EOF);
1191
}
1192
1193
int
1194
parse_config(struct smtpd *x_conf, const char *filename, int opts)
1195
{
1196
	struct sym     *sym, *next;
1197
	struct table   *t;
1198
	char		hostname[HOST_NAME_MAX+1];
1199
	char		hostname_copy[HOST_NAME_MAX+1];
1200
1201
	if (getmailname(hostname, sizeof hostname) == -1)
1202
		return (-1);
1203
1204
	conf = x_conf;
1205
	memset(conf, 0, sizeof(*conf));
1206
1207
	(void)strlcpy(conf->sc_hostname, hostname, sizeof(conf->sc_hostname));
1208
1209
	conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE;
1210
	conf->sc_subaddressing_delim = SUBADDRESSING_DELIMITER;
1211
1212
	conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict));
1213
	conf->sc_rules = calloc(1, sizeof(*conf->sc_rules));
1214
	conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners));
1215
	conf->sc_ca_dict = calloc(1, sizeof(*conf->sc_ca_dict));
1216
	conf->sc_pki_dict = calloc(1, sizeof(*conf->sc_pki_dict));
1217
	conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict));
1218
	conf->sc_limits_dict = calloc(1, sizeof(*conf->sc_limits_dict));
1219
1220
	/* Report mails delayed for more than 4 hours */
1221
	conf->sc_bounce_warn[0] = 3600 * 4;
1222
1223
	if (conf->sc_tables_dict == NULL	||
1224
	    conf->sc_rules == NULL		||
1225
	    conf->sc_listeners == NULL		||
1226
	    conf->sc_ca_dict == NULL		||
1227
	    conf->sc_pki_dict == NULL		||
1228
	    conf->sc_ssl_dict == NULL		||
1229
	    conf->sc_limits_dict == NULL) {
1230
		log_warn("warn: cannot allocate memory");
1231
		free(conf->sc_tables_dict);
1232
		free(conf->sc_rules);
1233
		free(conf->sc_listeners);
1234
		free(conf->sc_ca_dict);
1235
		free(conf->sc_pki_dict);
1236
		free(conf->sc_ssl_dict);
1237
		free(conf->sc_limits_dict);
1238
		return (-1);
1239
	}
1240
1241
	errors = 0;
1242
1243
	table = NULL;
1244
	rule = NULL;
1245
1246
	dict_init(conf->sc_ca_dict);
1247
	dict_init(conf->sc_pki_dict);
1248
	dict_init(conf->sc_ssl_dict);
1249
	dict_init(conf->sc_tables_dict);
1250
1251
	dict_init(conf->sc_limits_dict);
1252
	limits = xcalloc(1, sizeof(*limits), "mta_limits");
1253
	limit_mta_set_defaults(limits);
1254
	dict_xset(conf->sc_limits_dict, "default", limits);
1255
1256
	TAILQ_INIT(conf->sc_listeners);
1257
	TAILQ_INIT(conf->sc_rules);
1258
1259
	conf->sc_qexpire = SMTPD_QUEUE_EXPIRY;
1260
	conf->sc_opts = opts;
1261
1262
	conf->sc_mta_max_deferred = 100;
1263
	conf->sc_scheduler_max_inflight = 5000;
1264
	conf->sc_scheduler_max_schedule = 10;
1265
	conf->sc_scheduler_max_evp_batch_size = 256;
1266
	conf->sc_scheduler_max_msg_batch_size = 1024;
1267
1268
	conf->sc_session_max_rcpt = 1000;
1269
	conf->sc_session_max_mails = 100;
1270
1271
	conf->sc_mda_max_session = 50;
1272
	conf->sc_mda_max_user_session = 7;
1273
	conf->sc_mda_task_hiwat = 50;
1274
	conf->sc_mda_task_lowat = 30;
1275
	conf->sc_mda_task_release = 10;
1276
1277
	if ((file = pushfile(filename, 0)) == NULL) {
1278
		purge_config(PURGE_EVERYTHING);
1279
		return (-1);
1280
	}
1281
	topfile = file;
1282
1283
	/*
1284
	 * declare special "localhost", "anyhost" and "localnames" tables
1285
	 */
1286
	set_local(hostname);
1287
1288
	t = table_create("static", "<anydestination>", NULL, NULL);
1289
	t->t_type = T_LIST;
1290
	table_add(t, "*", NULL);
1291
1292
	/* can't truncate here */
1293
	(void)strlcpy(hostname_copy, hostname, sizeof hostname_copy);
1294
1295
	hostname_copy[strcspn(hostname_copy, ".")] = '\0';
1296
	if (strcmp(hostname, hostname_copy) != 0)
1297
		table_add(t, hostname_copy, NULL);
1298
1299
	table_create("getpwnam", "<getpwnam>", NULL, NULL);
1300
1301
	/*
1302
	 * parse configuration
1303
	 */
1304
	setservent(1);
1305
	yyparse();
1306
	errors = file->errors;
1307
	popfile();
1308
	endservent();
1309
1310
	/* If the socket listener was not configured, create a default one. */
1311
	if (!conf->sc_sock_listener) {
1312
		memset(&listen_opts, 0, sizeof listen_opts);
1313
		create_sock_listener(&listen_opts);
1314
	}
1315
1316
	/* Free macros and check which have not been used. */
1317
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
1318
		if ((conf->sc_opts & SMTPD_OPT_VERBOSE) && !sym->used)
1319
			fprintf(stderr, "warning: macro '%s' not "
1320
			    "used\n", sym->nam);
1321
		if (!sym->persist) {
1322
			free(sym->nam);
1323
			free(sym->val);
1324
			TAILQ_REMOVE(&symhead, sym, entry);
1325
			free(sym);
1326
		}
1327
	}
1328
1329
	if (TAILQ_EMPTY(conf->sc_rules)) {
1330
		log_warnx("warn: no rules, nothing to do");
1331
		errors++;
1332
	}
1333
1334
	if (errors) {
1335
		purge_config(PURGE_EVERYTHING);
1336
		return (-1);
1337
	}
1338
1339
	return (0);
1340
}
1341
1342
int
1343
symset(const char *nam, const char *val, int persist)
1344
{
1345
	struct sym	*sym;
1346
1347
	TAILQ_FOREACH(sym, &symhead, entry) {
1348
		if (strcmp(nam, sym->nam) == 0)
1349
			break;
1350
	}
1351
1352
	if (sym != NULL) {
1353
		if (sym->persist == 1)
1354
			return (0);
1355
		else {
1356
			free(sym->nam);
1357
			free(sym->val);
1358
			TAILQ_REMOVE(&symhead, sym, entry);
1359
			free(sym);
1360
		}
1361
	}
1362
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1363
		return (-1);
1364
1365
	sym->nam = strdup(nam);
1366
	if (sym->nam == NULL) {
1367
		free(sym);
1368
		return (-1);
1369
	}
1370
	sym->val = strdup(val);
1371
	if (sym->val == NULL) {
1372
		free(sym->nam);
1373
		free(sym);
1374
		return (-1);
1375
	}
1376
	sym->used = 0;
1377
	sym->persist = persist;
1378
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
1379
	return (0);
1380
}
1381
1382
int
1383
cmdline_symset(char *s)
1384
{
1385
	char	*sym, *val;
1386
	int	ret;
1387
	size_t	len;
1388
1389
	if ((val = strrchr(s, '=')) == NULL)
1390
		return (-1);
1391
1392
	len = strlen(s) - strlen(val) + 1;
1393
	if ((sym = malloc(len)) == NULL)
1394
		errx(1, "cmdline_symset: malloc");
1395
1396
	(void)strlcpy(sym, s, len);
1397
1398
	ret = symset(sym, val + 1, 1);
1399
	free(sym);
1400
1401
	return (ret);
1402
}
1403
1404
char *
1405
symget(const char *nam)
1406
{
1407
	struct sym	*sym;
1408
1409
	TAILQ_FOREACH(sym, &symhead, entry) {
1410
		if (strcmp(nam, sym->nam) == 0) {
1411
			sym->used = 1;
1412
			return (sym->val);
1413
		}
1414
	}
1415
	return (NULL);
1416
}
1417
1418
static void
1419
create_sock_listener(struct listen_opts *lo)
1420
{
1421
	struct listener *l = xcalloc(1, sizeof(*l), "create_sock_listener");
1422
	lo->tag = "local";
1423
	lo->hostname = conf->sc_hostname;
1424
	l->ss.ss_family = AF_LOCAL;
1425
	l->ss.ss_len = sizeof(struct sockaddr *);
1426
	l->local = 1;
1427
	conf->sc_sock_listener = l;
1428
	config_listener(l, lo);
1429
}
1430
1431
static void
1432
create_if_listener(struct listen_opts *lo)
1433
{
1434
	uint16_t	flags;
1435
1436
	if (lo->port != 0 && lo->ssl == F_SSL)
1437
		errx(1, "invalid listen option: tls/smtps on same port");
1438
1439
	if (lo->auth != 0 && !lo->ssl)
1440
		errx(1, "invalid listen option: auth requires tls/smtps");
1441
1442
	if (lo->pki && !lo->ssl)
1443
		errx(1, "invalid listen option: pki requires tls/smtps");
1444
1445
	flags = lo->flags;
1446
1447
	if (lo->port) {
1448
		lo->flags = lo->ssl|lo->auth|flags;
1449
		lo->port = htons(lo->port);
1450
	}
1451
	else {
1452
		if (lo->ssl & F_SMTPS) {
1453
			lo->port = htons(465);
1454
			lo->flags = F_SMTPS|lo->auth|flags;
1455
		}
1456
1457
		if (!lo->ssl || (lo->ssl & F_STARTTLS)) {
1458
			lo->port = htons(25);
1459
			lo->flags = lo->auth|flags;
1460
			if (lo->ssl & F_STARTTLS)
1461
				lo->flags |= F_STARTTLS;
1462
		}
1463
	}
1464
1465
	if (interface(lo))
1466
		return;
1467
	if (host_v4(lo))
1468
		return;
1469
	if (host_v6(lo))
1470
		return;
1471
	if (host_dns(lo))
1472
		return;
1473
1474
	errx(1, "invalid virtual ip or interface: %s", lo->ifx);
1475
}
1476
1477
static void
1478
config_listener(struct listener *h,  struct listen_opts *lo)
1479
{
1480
	h->fd = -1;
1481
	h->port = lo->port;
1482
	h->flags = lo->flags;
1483
1484
	if (lo->hostname == NULL)
1485
		lo->hostname = conf->sc_hostname;
1486
1487
	if (lo->filtername)
1488
		(void)strlcpy(h->filter, lo->filtername, sizeof(h->filter));
1489
1490
	h->pki_name[0] = '\0';
1491
1492
	if (lo->authtable != NULL)
1493
		(void)strlcpy(h->authtable, lo->authtable->t_name, sizeof(h->authtable));
1494
	if (lo->pki != NULL) {
1495
		if (!lowercase(h->pki_name, lo->pki, sizeof(h->pki_name))) {
1496
			log_warnx("pki name too long: %s", lo->pki);
1497
			fatalx(NULL);
1498
		}
1499
		if (dict_get(conf->sc_pki_dict, h->pki_name) == NULL) {
1500
			log_warnx("pki name not found: %s", lo->pki);
1501
			fatalx(NULL);
1502
		}
1503
	}
1504
1505
	if (lo->ca != NULL) {
1506
		if (!lowercase(h->ca_name, lo->ca, sizeof(h->ca_name))) {
1507
			log_warnx("ca name too long: %s", lo->ca);
1508
			fatalx(NULL);
1509
		}
1510
		if (dict_get(conf->sc_ca_dict, h->ca_name) == NULL) {
1511
			log_warnx("ca name not found: %s", lo->ca);
1512
			fatalx(NULL);
1513
		}
1514
	}
1515
	if (lo->tag != NULL)
1516
		(void)strlcpy(h->tag, lo->tag, sizeof(h->tag));
1517
1518
	(void)strlcpy(h->hostname, lo->hostname, sizeof(h->hostname));
1519
	if (lo->hostnametable)
1520
		(void)strlcpy(h->hostnametable, lo->hostnametable->t_name, sizeof(h->hostnametable));
1521
	if (lo->sendertable) {
1522
		(void)strlcpy(h->sendertable, lo->sendertable->t_name, sizeof(h->sendertable));
1523
		if (lo->options & LO_MASQUERADE)
1524
			h->flags |= F_MASQUERADE;
1525
	}
1526
1527
	if (lo->ssl & F_TLS_VERIFY)
1528
		h->flags |= F_TLS_VERIFY;
1529
1530
	if (lo->ssl & F_STARTTLS_REQUIRE)
1531
		h->flags |= F_STARTTLS_REQUIRE;
1532
1533
	if (h != conf->sc_sock_listener)
1534
		TAILQ_INSERT_TAIL(conf->sc_listeners, h, entry);
1535
}
1536
1537
static int
1538
host_v4(struct listen_opts *lo)
1539
{
1540
	struct in_addr		 ina;
1541
	struct sockaddr_in	*sain;
1542
	struct listener		*h;
1543
1544
	if (lo->family != AF_UNSPEC && lo->family != AF_INET)
1545
		return (0);
1546
1547
	memset(&ina, 0, sizeof(ina));
1548
	if (inet_pton(AF_INET, lo->ifx, &ina) != 1)
1549
		return (0);
1550
1551
	h = xcalloc(1, sizeof(*h), "host_v4");
1552
	sain = (struct sockaddr_in *)&h->ss;
1553
	sain->sin_len = sizeof(struct sockaddr_in);
1554
	sain->sin_family = AF_INET;
1555
	sain->sin_addr.s_addr = ina.s_addr;
1556
	sain->sin_port = lo->port;
1557
1558
	if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
1559
		h->local = 1;
1560
	config_listener(h,  lo);
1561
1562
	return (1);
1563
}
1564
1565
static int
1566
host_v6(struct listen_opts *lo)
1567
{
1568
	struct in6_addr		 ina6;
1569
	struct sockaddr_in6	*sin6;
1570
	struct listener		*h;
1571
1572
	if (lo->family != AF_UNSPEC && lo->family != AF_INET6)
1573
		return (0);
1574
1575
	memset(&ina6, 0, sizeof(ina6));
1576
	if (inet_pton(AF_INET6, lo->ifx, &ina6) != 1)
1577
		return (0);
1578
1579
	h = xcalloc(1, sizeof(*h), "host_v6");
1580
	sin6 = (struct sockaddr_in6 *)&h->ss;
1581
	sin6->sin6_len = sizeof(struct sockaddr_in6);
1582
	sin6->sin6_family = AF_INET6;
1583
	sin6->sin6_port = lo->port;
1584
	memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
1585
1586
	if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
1587
		h->local = 1;
1588
	config_listener(h,  lo);
1589
1590
	return (1);
1591
}
1592
1593
static int
1594
host_dns(struct listen_opts *lo)
1595
{
1596
	struct addrinfo		 hints, *res0, *res;
1597
	int			 error, cnt = 0;
1598
	struct sockaddr_in	*sain;
1599
	struct sockaddr_in6	*sin6;
1600
	struct listener		*h;
1601
1602
	memset(&hints, 0, sizeof(hints));
1603
	hints.ai_family = lo->family;
1604
	hints.ai_socktype = SOCK_STREAM;
1605
	hints.ai_flags = AI_ADDRCONFIG;
1606
	error = getaddrinfo(lo->ifx, NULL, &hints, &res0);
1607
	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
1608
		return (0);
1609
	if (error) {
1610
		log_warnx("warn: host_dns: could not parse \"%s\": %s", lo->ifx,
1611
		    gai_strerror(error));
1612
		return (-1);
1613
	}
1614
1615
	for (res = res0; res; res = res->ai_next) {
1616
		if (res->ai_family != AF_INET &&
1617
		    res->ai_family != AF_INET6)
1618
			continue;
1619
		h = xcalloc(1, sizeof(*h), "host_dns");
1620
1621
		h->ss.ss_family = res->ai_family;
1622
		if (res->ai_family == AF_INET) {
1623
			sain = (struct sockaddr_in *)&h->ss;
1624
			sain->sin_len = sizeof(struct sockaddr_in);
1625
			sain->sin_addr.s_addr = ((struct sockaddr_in *)
1626
			    res->ai_addr)->sin_addr.s_addr;
1627
			sain->sin_port = lo->port;
1628
			if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
1629
				h->local = 1;
1630
		} else {
1631
			sin6 = (struct sockaddr_in6 *)&h->ss;
1632
			sin6->sin6_len = sizeof(struct sockaddr_in6);
1633
			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
1634
			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
1635
			sin6->sin6_port = lo->port;
1636
			if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
1637
				h->local = 1;
1638
		}
1639
1640
		config_listener(h, lo);
1641
1642
		cnt++;
1643
	}
1644
1645
	freeaddrinfo(res0);
1646
	return (cnt);
1647
}
1648
1649
static int
1650
interface(struct listen_opts *lo)
1651
{
1652
	struct ifaddrs *ifap, *p;
1653
	struct sockaddr_in	*sain;
1654
	struct sockaddr_in6	*sin6;
1655
	struct listener		*h;
1656
	int			ret = 0;
1657
1658
	if (getifaddrs(&ifap) == -1)
1659
		fatal("getifaddrs");
1660
1661
	for (p = ifap; p != NULL; p = p->ifa_next) {
1662
		if (p->ifa_addr == NULL)
1663
			continue;
1664
		if (strcmp(p->ifa_name, lo->ifx) != 0 &&
1665
		    !is_if_in_group(p->ifa_name, lo->ifx))
1666
			continue;
1667
		if (lo->family != AF_UNSPEC && lo->family != p->ifa_addr->sa_family)
1668
			continue;
1669
1670
		h = xcalloc(1, sizeof(*h), "interface");
1671
1672
		switch (p->ifa_addr->sa_family) {
1673
		case AF_INET:
1674
			sain = (struct sockaddr_in *)&h->ss;
1675
			*sain = *(struct sockaddr_in *)p->ifa_addr;
1676
			sain->sin_len = sizeof(struct sockaddr_in);
1677
			sain->sin_port = lo->port;
1678
			if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
1679
				h->local = 1;
1680
			break;
1681
1682
		case AF_INET6:
1683
			sin6 = (struct sockaddr_in6 *)&h->ss;
1684
			*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
1685
			sin6->sin6_len = sizeof(struct sockaddr_in6);
1686
			sin6->sin6_port = lo->port;
1687
			if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
1688
				h->local = 1;
1689
			break;
1690
1691
		default:
1692
			free(h);
1693
			continue;
1694
		}
1695
1696
		config_listener(h, lo);
1697
		ret = 1;
1698
	}
1699
1700
	freeifaddrs(ifap);
1701
1702
	return ret;
1703
}
1704
1705
void
1706
set_local(const char *hostname)
1707
{
1708
	struct table	*t;
1709
1710
	t = table_create("static", "<localnames>", NULL, NULL);
1711
	t->t_type = T_LIST;
1712
	table_add(t, "localhost", NULL);
1713
	table_add(t, hostname, NULL);
1714
1715
	set_localaddrs(t);
1716
}
1717
1718
void
1719
set_localaddrs(struct table *localnames)
1720
{
1721
	struct ifaddrs *ifap, *p;
1722
	struct sockaddr_storage ss;
1723
	struct sockaddr_in	*sain;
1724
	struct sockaddr_in6	*sin6;
1725
	struct table		*t;
1726
	char buf[NI_MAXHOST + 5];
1727
1728
	t = table_create("static", "<anyhost>", NULL, NULL);
1729
	table_add(t, "local", NULL);
1730
	table_add(t, "0.0.0.0/0", NULL);
1731
	table_add(t, "::/0", NULL);
1732
1733
	if (getifaddrs(&ifap) == -1)
1734
		fatal("getifaddrs");
1735
1736
	t = table_create("static", "<localhost>", NULL, NULL);
1737
	table_add(t, "local", NULL);
1738
1739
	for (p = ifap; p != NULL; p = p->ifa_next) {
1740
		if (p->ifa_addr == NULL)
1741
			continue;
1742
		switch (p->ifa_addr->sa_family) {
1743
		case AF_INET:
1744
			sain = (struct sockaddr_in *)&ss;
1745
			*sain = *(struct sockaddr_in *)p->ifa_addr;
1746
			sain->sin_len = sizeof(struct sockaddr_in);
1747
			table_add(t, ss_to_text(&ss), NULL);
1748
			table_add(localnames, ss_to_text(&ss), NULL);
1749
			(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
1750
			table_add(localnames, buf, NULL);
1751
			break;
1752
1753
		case AF_INET6:
1754
			sin6 = (struct sockaddr_in6 *)&ss;
1755
			*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
1756
			sin6->sin6_len = sizeof(struct sockaddr_in6);
1757
			table_add(t, ss_to_text(&ss), NULL);
1758
			table_add(localnames, ss_to_text(&ss), NULL);
1759
			(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
1760
			table_add(localnames, buf, NULL);
1761
			(void)snprintf(buf, sizeof buf, "[ipv6:%s]", ss_to_text(&ss));
1762
			table_add(localnames, buf, NULL);
1763
			break;
1764
		}
1765
	}
1766
1767
	freeifaddrs(ifap);
1768
}
1769
1770
int
1771
delaytonum(char *str)
1772
{
1773
	unsigned int     factor;
1774
	size_t           len;
1775
	const char      *errstr = NULL;
1776
	int              delay;
1777
1778
	/* we need at least 1 digit and 1 unit */
1779
	len = strlen(str);
1780
	if (len < 2)
1781
		goto bad;
1782
1783
	switch(str[len - 1]) {
1784
1785
	case 's':
1786
		factor = 1;
1787
		break;
1788
1789
	case 'm':
1790
		factor = 60;
1791
		break;
1792
1793
	case 'h':
1794
		factor = 60 * 60;
1795
		break;
1796
1797
	case 'd':
1798
		factor = 24 * 60 * 60;
1799
		break;
1800
1801
	default:
1802
		goto bad;
1803
	}
1804
1805
	str[len - 1] = '\0';
1806
	delay = strtonum(str, 1, INT_MAX / factor, &errstr);
1807
	if (errstr)
1808
		goto bad;
1809
1810
	return (delay * factor);
1811
1812
bad:
1813
	return (-1);
1814
}
1815
1816
int
1817
is_if_in_group(const char *ifname, const char *groupname)
1818
{
1819
        unsigned int		 len;
1820
        struct ifgroupreq        ifgr;
1821
        struct ifg_req          *ifg;
1822
	int			 s;
1823
	int			 ret = 0;
1824
1825
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1826
		err(1, "socket");
1827
1828
        memset(&ifgr, 0, sizeof(ifgr));
1829
        if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ)
1830
		errx(1, "interface name too large");
1831
1832
        if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
1833
                if (errno == EINVAL || errno == ENOTTY)
1834
			goto end;
1835
		err(1, "SIOCGIFGROUP");
1836
        }
1837
1838
        len = ifgr.ifgr_len;
1839
        ifgr.ifgr_groups = xcalloc(len/sizeof(struct ifg_req),
1840
		sizeof(struct ifg_req), "is_if_in_group");
1841
        if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
1842
                err(1, "SIOCGIFGROUP");
1843
1844
        ifg = ifgr.ifgr_groups;
1845
        for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
1846
                len -= sizeof(struct ifg_req);
1847
		if (strcmp(ifg->ifgrq_group, groupname) == 0) {
1848
			ret = 1;
1849
			break;
1850
		}
1851
        }
1852
        free(ifgr.ifgr_groups);
1853
1854
end:
1855
	close(s);
1856
	return ret;
1857
}
1858
1859
static int
1860
config_lo_filter(struct listen_opts *lo, char *filter_name) {
1861
	if (lo->options & LO_FILTER) {
1862
		yyerror("filter already specified");
1863
		return -1;
1864
	}
1865
	lo->options |= LO_FILTER;
1866
	lo->filtername = filter_name;
1867
1868
	return 0;
1869
}
1870
1871
static int
1872
config_lo_mask_source(struct listen_opts *lo) {
1873
	if (lo->options & LO_MASKSOURCE) {
1874
		yyerror("mask-source already specified");
1875
		return -1;
1876
	}
1877
	lo->options |= LO_MASKSOURCE;
1878
	lo->flags |= F_MASK_SOURCE;
1879
1880
	return 0;
1881
}
1882
1883
#line 1876 "parse.c"
1884
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
1885
static int yygrowstack(void)
1886
{
1887
    unsigned int newsize;
1888
    long sslen;
1889
    short *newss;
1890
    YYSTYPE *newvs;
1891
1892
    if ((newsize = yystacksize) == 0)
1893
        newsize = YYINITSTACKSIZE;
1894
    else if (newsize >= YYMAXDEPTH)
1895
        return -1;
1896
    else if ((newsize *= 2) > YYMAXDEPTH)
1897
        newsize = YYMAXDEPTH;
1898
    sslen = yyssp - yyss;
1899
#ifdef SIZE_MAX
1900
#define YY_SIZE_MAX SIZE_MAX
1901
#else
1902
#define YY_SIZE_MAX 0xffffffffU
1903
#endif
1904
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
1905
        goto bail;
1906
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
1907
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
1908
    if (newss == NULL)
1909
        goto bail;
1910
    yyss = newss;
1911
    yyssp = newss + sslen;
1912
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
1913
        goto bail;
1914
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
1915
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
1916
    if (newvs == NULL)
1917
        goto bail;
1918
    yyvs = newvs;
1919
    yyvsp = newvs + sslen;
1920
    yystacksize = newsize;
1921
    yysslim = yyss + newsize - 1;
1922
    return 0;
1923
bail:
1924
    if (yyss)
1925
            free(yyss);
1926
    if (yyvs)
1927
            free(yyvs);
1928
    yyss = yyssp = NULL;
1929
    yyvs = yyvsp = NULL;
1930
    yystacksize = 0;
1931
    return -1;
1932
}
1933
1934
#define YYABORT goto yyabort
1935
#define YYREJECT goto yyabort
1936
#define YYACCEPT goto yyaccept
1937
#define YYERROR goto yyerrlab
1938
int
1939
yyparse(void)
1940
{
1941
    int yym, yyn, yystate;
1942
#if YYDEBUG
1943
    const char *yys;
1944
1945
    if ((yys = getenv("YYDEBUG")))
1946
    {
1947
        yyn = *yys;
1948
        if (yyn >= '0' && yyn <= '9')
1949
            yydebug = yyn - '0';
1950
    }
1951
#endif /* YYDEBUG */
1952
1953
    yynerrs = 0;
1954
    yyerrflag = 0;
1955
    yychar = (-1);
1956
1957
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
1958
    yyssp = yyss;
1959
    yyvsp = yyvs;
1960
    *yyssp = yystate = 0;
1961
1962
yyloop:
1963
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1964
    if (yychar < 0)
1965
    {
1966
        if ((yychar = yylex()) < 0) yychar = 0;
1967
#if YYDEBUG
1968
        if (yydebug)
1969
        {
1970
            yys = 0;
1971
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1972
            if (!yys) yys = "illegal-symbol";
1973
            printf("%sdebug: state %d, reading %d (%s)\n",
1974
                    YYPREFIX, yystate, yychar, yys);
1975
        }
1976
#endif
1977
    }
1978
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1979
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1980
    {
1981
#if YYDEBUG
1982
        if (yydebug)
1983
            printf("%sdebug: state %d, shifting to state %d\n",
1984
                    YYPREFIX, yystate, yytable[yyn]);
1985
#endif
1986
        if (yyssp >= yysslim && yygrowstack())
1987
        {
1988
            goto yyoverflow;
1989
        }
1990
        *++yyssp = yystate = yytable[yyn];
1991
        *++yyvsp = yylval;
1992
        yychar = (-1);
1993
        if (yyerrflag > 0)  --yyerrflag;
1994
        goto yyloop;
1995
    }
1996
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1997
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1998
    {
1999
        yyn = yytable[yyn];
2000
        goto yyreduce;
2001
    }
2002
    if (yyerrflag) goto yyinrecovery;
2003
#if defined(__GNUC__)
2004
    goto yynewerror;
2005
#endif
2006
yynewerror:
2007
    yyerror("syntax error");
2008
#if defined(__GNUC__)
2009
    goto yyerrlab;
2010
#endif
2011
yyerrlab:
2012
    ++yynerrs;
2013
yyinrecovery:
2014
    if (yyerrflag < 3)
2015
    {
2016
        yyerrflag = 3;
2017
        for (;;)
2018
        {
2019
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
2020
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
2021
            {
2022
#if YYDEBUG
2023
                if (yydebug)
2024
                    printf("%sdebug: state %d, error recovery shifting\
2025
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
2026
#endif
2027
                if (yyssp >= yysslim && yygrowstack())
2028
                {
2029
                    goto yyoverflow;
2030
                }
2031
                *++yyssp = yystate = yytable[yyn];
2032
                *++yyvsp = yylval;
2033
                goto yyloop;
2034
            }
2035
            else
2036
            {
2037
#if YYDEBUG
2038
                if (yydebug)
2039
                    printf("%sdebug: error recovery discarding state %d\n",
2040
                            YYPREFIX, *yyssp);
2041
#endif
2042
                if (yyssp <= yyss) goto yyabort;
2043
                --yyssp;
2044
                --yyvsp;
2045
            }
2046
        }
2047
    }
2048
    else
2049
    {
2050
        if (yychar == 0) goto yyabort;
2051
#if YYDEBUG
2052
        if (yydebug)
2053
        {
2054
            yys = 0;
2055
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
2056
            if (!yys) yys = "illegal-symbol";
2057
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
2058
                    YYPREFIX, yystate, yychar, yys);
2059
        }
2060
#endif
2061
        yychar = (-1);
2062
        goto yyloop;
2063
    }
2064
yyreduce:
2065
#if YYDEBUG
2066
    if (yydebug)
2067
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
2068
                YYPREFIX, yystate, yyn, yyrule[yyn]);
2069
#endif
2070
    yym = yylen[yyn];
2071
    if (yym)
2072
        yyval = yyvsp[1-yym];
2073
    else
2074
        memset(&yyval, 0, sizeof yyval);
2075
    switch (yyn)
2076
    {
2077
case 8:
2078
#line 193 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2079
{ file->errors++; }
2080
break;
2081
case 9:
2082
#line 196 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2083
{
2084
			struct file	*nfile;
2085
2086
			if ((nfile = pushfile(yyvsp[0].v.string, 0)) == NULL) {
2087
				yyerror("failed to include file %s", yyvsp[0].v.string);
2088
				free(yyvsp[0].v.string);
2089
				YYERROR;
2090
			}
2091
			free(yyvsp[0].v.string);
2092
2093
			file = nfile;
2094
			lungetc('\n');
2095
		}
2096
break;
2097
case 10:
2098
#line 211 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2099
{
2100
			char *s = yyvsp[-2].v.string;
2101
			while (*s++) {
2102
				if (isspace((unsigned char)*s)) {
2103
					yyerror("macro name cannot contain "
2104
					    "whitespace");
2105
					YYERROR;
2106
				}
2107
			}
2108
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
2109
				fatal("cannot store variable");
2110
			free(yyvsp[-2].v.string);
2111
			free(yyvsp[0].v.string);
2112
		}
2113
break;
2114
case 17:
2115
#line 239 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2116
{
2117
			if (yyvsp[0].v.number < 0) {
2118
				yyerror("invalid size: %" PRId64, yyvsp[0].v.number);
2119
				YYERROR;
2120
			}
2121
			yyval.v.number = yyvsp[0].v.number;
2122
		}
2123
break;
2124
case 18:
2125
#line 246 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2126
{
2127
			long long result;
2128
2129
			if (scan_scaled(yyvsp[0].v.string, &result) == -1 || result < 0) {
2130
				yyerror("invalid size: %s", yyvsp[0].v.string);
2131
				free(yyvsp[0].v.string);
2132
				YYERROR;
2133
			}
2134
			free(yyvsp[0].v.string);
2135
			yyval.v.number = result;
2136
		}
2137
break;
2138
case 19:
2139
#line 259 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2140
{
2141
			if (strlcpy(rule->r_tag, yyvsp[0].v.string, sizeof rule->r_tag)
2142
			    >= sizeof rule->r_tag) {
2143
				yyerror("tag name too long: %s", yyvsp[0].v.string);
2144
				free(yyvsp[0].v.string);
2145
				YYERROR;
2146
			}
2147
			free(yyvsp[0].v.string);
2148
			rule->r_nottag = yyvsp[-1].v.number;
2149
		}
2150
break;
2151
case 20:
2152
#line 271 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2153
{
2154
			rule->r_wantauth = 1;
2155
			rule->r_negwantauth = yyvsp[-1].v.number;
2156
		}
2157
break;
2158
case 21:
2159
#line 277 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2160
{
2161
			time_t	d;
2162
			int	i;
2163
2164
			d = delaytonum(yyvsp[0].v.string);
2165
			if (d < 0) {
2166
				yyerror("invalid bounce delay: %s", yyvsp[0].v.string);
2167
				free(yyvsp[0].v.string);
2168
				YYERROR;
2169
			}
2170
			free(yyvsp[0].v.string);
2171
			for (i = 0; i < MAX_BOUNCE_WARN; i++) {
2172
				if (conf->sc_bounce_warn[i] != 0)
2173
					continue;
2174
				conf->sc_bounce_warn[i] = d;
2175
				break;
2176
			}
2177
		}
2178
break;
2179
case 25:
2180
#line 301 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2181
{
2182
			if (!strcmp(yyvsp[-1].v.string, "max-session")) {
2183
				conf->sc_mda_max_session = yyvsp[0].v.number;
2184
			}
2185
			else if (!strcmp(yyvsp[-1].v.string, "max-session-per-user")) {
2186
				conf->sc_mda_max_user_session = yyvsp[0].v.number;
2187
			}
2188
			else if (!strcmp(yyvsp[-1].v.string, "task-lowat")) {
2189
				conf->sc_mda_task_lowat = yyvsp[0].v.number;
2190
			}
2191
			else if (!strcmp(yyvsp[-1].v.string, "task-hiwat")) {
2192
				conf->sc_mda_task_hiwat = yyvsp[0].v.number;
2193
			}
2194
			else if (!strcmp(yyvsp[-1].v.string, "task-release")) {
2195
				conf->sc_mda_task_release = yyvsp[0].v.number;
2196
			}
2197
			else {
2198
				yyerror("invalid scheduler limit keyword: %s", yyvsp[-1].v.string);
2199
				free(yyvsp[-1].v.string);
2200
				YYERROR;
2201
			}
2202
			free(yyvsp[-1].v.string);
2203
		}
2204
break;
2205
case 28:
2206
#line 330 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2207
{
2208
			if (!strcmp(yyvsp[-1].v.string, "max-rcpt")) {
2209
				conf->sc_session_max_rcpt = yyvsp[0].v.number;
2210
			}
2211
			else if (!strcmp(yyvsp[-1].v.string, "max-mails")) {
2212
				conf->sc_session_max_mails = yyvsp[0].v.number;
2213
			}
2214
			else {
2215
				yyerror("invalid session limit keyword: %s", yyvsp[-1].v.string);
2216
				free(yyvsp[-1].v.string);
2217
				YYERROR;
2218
			}
2219
			free(yyvsp[-1].v.string);
2220
		}
2221
break;
2222
case 31:
2223
#line 350 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2224
{
2225
			limits->family = AF_INET;
2226
		}
2227
break;
2228
case 32:
2229
#line 353 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2230
{
2231
			limits->family = AF_INET6;
2232
		}
2233
break;
2234
case 33:
2235
#line 356 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2236
{
2237
			if (!limit_mta_set(limits, yyvsp[-1].v.string, yyvsp[0].v.number)) {
2238
				yyerror("invalid mta limit keyword: %s", yyvsp[-1].v.string);
2239
				free(yyvsp[-1].v.string);
2240
				YYERROR;
2241
			}
2242
			free(yyvsp[-1].v.string);
2243
		}
2244
break;
2245
case 36:
2246
#line 370 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2247
{
2248
			if (!strcmp(yyvsp[-1].v.string, "max-inflight")) {
2249
				conf->sc_scheduler_max_inflight = yyvsp[0].v.number;
2250
			}
2251
			else if (!strcmp(yyvsp[-1].v.string, "max-evp-batch-size")) {
2252
				conf->sc_scheduler_max_evp_batch_size = yyvsp[0].v.number;
2253
			}
2254
			else if (!strcmp(yyvsp[-1].v.string, "max-msg-batch-size")) {
2255
				conf->sc_scheduler_max_msg_batch_size = yyvsp[0].v.number;
2256
			}
2257
			else if (!strcmp(yyvsp[-1].v.string, "max-schedule")) {
2258
				conf->sc_scheduler_max_schedule = yyvsp[0].v.number;
2259
			}
2260
			else {
2261
				yyerror("invalid scheduler limit keyword: %s", yyvsp[-1].v.string);
2262
				free(yyvsp[-1].v.string);
2263
				YYERROR;
2264
			}
2265
			free(yyvsp[-1].v.string);
2266
		}
2267
break;
2268
case 39:
2269
#line 396 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2270
{
2271
			sca->ca_cert_file = yyvsp[0].v.string;
2272
		}
2273
break;
2274
case 41:
2275
#line 404 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2276
{
2277
			pki->pki_cert_file = yyvsp[0].v.string;
2278
		}
2279
break;
2280
case 42:
2281
#line 407 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2282
{
2283
			pki->pki_key_file = yyvsp[0].v.string;
2284
		}
2285
break;
2286
case 43:
2287
#line 410 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2288
{
2289
			if (strcasecmp(yyvsp[0].v.string, "none") == 0)
2290
				pki->pki_dhe = 0;
2291
			else if (strcasecmp(yyvsp[0].v.string, "auto") == 0)
2292
				pki->pki_dhe = 1;
2293
			else if (strcasecmp(yyvsp[0].v.string, "legacy") == 0)
2294
				pki->pki_dhe = 2;
2295
			else {
2296
				yyerror("invalid DHE keyword: %s", yyvsp[0].v.string);
2297
				free(yyvsp[0].v.string);
2298
				YYERROR;
2299
			}
2300
			free(yyvsp[0].v.string);
2301
		}
2302
break;
2303
case 46:
2304
#line 430 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2305
{
2306
			if (config_lo_filter(&listen_opts, yyvsp[0].v.string)) {
2307
				YYERROR;
2308
			}
2309
		}
2310
break;
2311
case 47:
2312
#line 435 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2313
{
2314
			if (config_lo_mask_source(&listen_opts)) {
2315
				YYERROR;
2316
			}
2317
		}
2318
break;
2319
case 48:
2320
#line 442 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2321
{
2322
			if (listen_opts.options & LO_FAMILY) {
2323
				yyerror("address family already specified");
2324
				YYERROR;
2325
			}
2326
			listen_opts.options |= LO_FAMILY;
2327
			listen_opts.family = AF_INET;
2328
		}
2329
break;
2330
case 49:
2331
#line 450 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2332
{
2333
			if (listen_opts.options & LO_FAMILY) {
2334
				yyerror("address family already specified");
2335
				YYERROR;
2336
			}
2337
			listen_opts.options |= LO_FAMILY;
2338
			listen_opts.family = AF_INET6;
2339
		}
2340
break;
2341
case 50:
2342
#line 458 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2343
{
2344
			struct servent	*servent;
2345
2346
			if (listen_opts.options & LO_PORT) {
2347
				yyerror("port already specified");
2348
				YYERROR;
2349
			}
2350
			listen_opts.options |= LO_PORT;
2351
2352
			servent = getservbyname(yyvsp[0].v.string, "tcp");
2353
			if (servent == NULL) {
2354
				yyerror("invalid port: %s", yyvsp[0].v.string);
2355
				free(yyvsp[0].v.string);
2356
				YYERROR;
2357
			}
2358
			free(yyvsp[0].v.string);
2359
			listen_opts.port = ntohs(servent->s_port);
2360
		}
2361
break;
2362
case 51:
2363
#line 476 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2364
{
2365
			if (listen_opts.options & LO_PORT) {
2366
				yyerror("port already specified");
2367
				YYERROR;
2368
			}
2369
			listen_opts.options |= LO_PORT;
2370
2371
			if (yyvsp[0].v.number <= 0 || yyvsp[0].v.number > (int)USHRT_MAX) {
2372
				yyerror("invalid port: %" PRId64, yyvsp[0].v.number);
2373
				YYERROR;
2374
			}
2375
			listen_opts.port = yyvsp[0].v.number;
2376
		}
2377
break;
2378
case 52:
2379
#line 489 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2380
{
2381
			if (config_lo_filter(&listen_opts, yyvsp[0].v.string)) {
2382
				YYERROR;
2383
			}
2384
		}
2385
break;
2386
case 53:
2387
#line 494 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2388
{
2389
			if (listen_opts.options & LO_SSL) {
2390
				yyerror("TLS mode already specified");
2391
				YYERROR;
2392
			}
2393
			listen_opts.options |= LO_SSL;
2394
			listen_opts.ssl = F_SMTPS;
2395
		}
2396
break;
2397
case 54:
2398
#line 502 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2399
{
2400
			if (listen_opts.options & LO_SSL) {
2401
				yyerror("TLS mode already specified");
2402
				YYERROR;
2403
			}
2404
			listen_opts.options |= LO_SSL;
2405
			listen_opts.ssl = F_SMTPS|F_TLS_VERIFY;
2406
		}
2407
break;
2408
case 55:
2409
#line 510 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2410
{
2411
			if (listen_opts.options & LO_SSL) {
2412
				yyerror("TLS mode already specified");
2413
				YYERROR;
2414
			}
2415
			listen_opts.options |= LO_SSL;
2416
			listen_opts.ssl = F_STARTTLS;
2417
		}
2418
break;
2419
case 56:
2420
#line 518 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2421
{
2422
			if (listen_opts.options & LO_SSL) {
2423
				yyerror("TLS mode already specified");
2424
				YYERROR;
2425
			}
2426
			listen_opts.options |= LO_SSL;
2427
			listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE;
2428
		}
2429
break;
2430
case 57:
2431
#line 526 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2432
{
2433
			if (listen_opts.options & LO_SSL) {
2434
				yyerror("TLS mode already specified");
2435
				YYERROR;
2436
			}
2437
			listen_opts.options |= LO_SSL;
2438
			listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE|F_TLS_VERIFY;
2439
		}
2440
break;
2441
case 58:
2442
#line 534 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2443
{
2444
			if (listen_opts.options & LO_PKI) {
2445
				yyerror("pki already specified");
2446
				YYERROR;
2447
			}
2448
			listen_opts.options |= LO_PKI;
2449
			listen_opts.pki = yyvsp[0].v.string;
2450
		}
2451
break;
2452
case 59:
2453
#line 542 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2454
{
2455
			if (listen_opts.options & LO_CA) {
2456
				yyerror("ca already specified");
2457
				YYERROR;
2458
			}
2459
			listen_opts.options |= LO_CA;
2460
			listen_opts.ca = yyvsp[0].v.string;
2461
		}
2462
break;
2463
case 60:
2464
#line 550 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2465
{
2466
			if (listen_opts.options & LO_AUTH) {
2467
				yyerror("auth already specified");
2468
				YYERROR;
2469
			}
2470
			listen_opts.options |= LO_AUTH;
2471
			listen_opts.auth = F_AUTH|F_AUTH_REQUIRE;
2472
		}
2473
break;
2474
case 61:
2475
#line 558 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2476
{
2477
			if (listen_opts.options & LO_AUTH) {
2478
				yyerror("auth already specified");
2479
				YYERROR;
2480
			}
2481
			listen_opts.options |= LO_AUTH;
2482
			listen_opts.auth = F_AUTH;
2483
		}
2484
break;
2485
case 62:
2486
#line 566 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2487
{
2488
			if (listen_opts.options & LO_AUTH) {
2489
				yyerror("auth already specified");
2490
				YYERROR;
2491
			}
2492
			listen_opts.options |= LO_AUTH;
2493
			listen_opts.authtable = yyvsp[0].v.table;
2494
			listen_opts.auth = F_AUTH|F_AUTH_REQUIRE;
2495
		}
2496
break;
2497
case 63:
2498
#line 575 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2499
{
2500
			if (listen_opts.options & LO_AUTH) {
2501
				yyerror("auth already specified");
2502
				YYERROR;
2503
			}
2504
			listen_opts.options |= LO_AUTH;
2505
			listen_opts.authtable = yyvsp[0].v.table;
2506
			listen_opts.auth = F_AUTH;
2507
		}
2508
break;
2509
case 64:
2510
#line 584 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2511
{
2512
			if (listen_opts.options & LO_TAG) {
2513
				yyerror("tag already specified");
2514
				YYERROR;
2515
			}
2516
			listen_opts.options |= LO_TAG;
2517
2518
			if (strlen(yyvsp[0].v.string) >= SMTPD_TAG_SIZE) {
2519
       				yyerror("tag name too long");
2520
				free(yyvsp[0].v.string);
2521
				YYERROR;
2522
			}
2523
			listen_opts.tag = yyvsp[0].v.string;
2524
		}
2525
break;
2526
case 65:
2527
#line 598 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2528
{
2529
			if (listen_opts.options & LO_HOSTNAME) {
2530
				yyerror("hostname already specified");
2531
				YYERROR;
2532
			}
2533
			listen_opts.options |= LO_HOSTNAME;
2534
2535
			listen_opts.hostname = yyvsp[0].v.string;
2536
		}
2537
break;
2538
case 66:
2539
#line 607 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2540
{
2541
			struct table	*t = yyvsp[0].v.table;
2542
2543
			if (listen_opts.options & LO_HOSTNAMES) {
2544
				yyerror("hostnames already specified");
2545
				YYERROR;
2546
			}
2547
			listen_opts.options |= LO_HOSTNAMES;
2548
2549
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) {
2550
				yyerror("invalid use of table \"%s\" as "
2551
				    "HOSTNAMES parameter", t->t_name);
2552
				YYERROR;
2553
			}
2554
			listen_opts.hostnametable = t;
2555
		}
2556
break;
2557
case 67:
2558
#line 623 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2559
{
2560
			if (config_lo_mask_source(&listen_opts)) {
2561
				YYERROR;
2562
			}
2563
		}
2564
break;
2565
case 68:
2566
#line 628 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2567
{
2568
			if (listen_opts.options & LO_RECEIVEDAUTH) {
2569
				yyerror("received-auth already specified");
2570
				YYERROR;
2571
			}
2572
			listen_opts.options |= LO_RECEIVEDAUTH;
2573
			listen_opts.flags |= F_RECEIVEDAUTH;
2574
		}
2575
break;
2576
case 69:
2577
#line 636 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2578
{
2579
			if (listen_opts.options & LO_NODSN) {
2580
				yyerror("no-dsn already specified");
2581
				YYERROR;
2582
			}
2583
			listen_opts.options |= LO_NODSN;
2584
			listen_opts.flags &= ~F_EXT_DSN;
2585
		}
2586
break;
2587
case 70:
2588
#line 644 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2589
{
2590
			struct table	*t = yyvsp[0].v.table;
2591
2592
			if (listen_opts.options & LO_SENDERS) {
2593
				yyerror("senders already specified");
2594
				YYERROR;
2595
			}
2596
			listen_opts.options |= LO_SENDERS;
2597
2598
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) {
2599
				yyerror("invalid use of table \"%s\" as "
2600
				    "SENDERS parameter", t->t_name);
2601
				YYERROR;
2602
			}
2603
			listen_opts.sendertable = t;
2604
		}
2605
break;
2606
case 71:
2607
#line 660 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2608
{
2609
			struct table	*t = yyvsp[-1].v.table;
2610
2611
			if (listen_opts.options & LO_SENDERS) {
2612
				yyerror("senders already specified");
2613
				YYERROR;
2614
			}
2615
			listen_opts.options |= LO_SENDERS|LO_MASQUERADE;
2616
2617
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_MAILADDRMAP)) {
2618
				yyerror("invalid use of table \"%s\" as "
2619
				    "SENDERS parameter", t->t_name);
2620
				YYERROR;
2621
			}
2622
			listen_opts.sendertable = t;
2623
		}
2624
break;
2625
case 74:
2626
#line 682 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2627
{
2628
			if (conf->sc_sock_listener) {
2629
				yyerror("socket listener already configured");
2630
				YYERROR;
2631
			}
2632
			create_sock_listener(&listen_opts);
2633
		}
2634
break;
2635
case 75:
2636
#line 691 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2637
{
2638
			listen_opts.ifx = yyvsp[-1].v.string;
2639
			create_if_listener(&listen_opts);
2640
		}
2641
break;
2642
case 80:
2643
#line 705 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2644
{
2645
			struct mailaddr maddr, *maddrp;
2646
2647
			if (!text_to_mailaddr(&maddr, yyvsp[0].v.string)) {
2648
				yyerror("invalid parameter to AS: %s", yyvsp[0].v.string);
2649
				free(yyvsp[0].v.string);
2650
				YYERROR;
2651
			}
2652
			free(yyvsp[0].v.string);
2653
2654
			if (maddr.user[0] == '\0' && maddr.domain[0] == '\0') {
2655
				yyerror("invalid empty parameter to AS");
2656
				YYERROR;
2657
			}
2658
			else if (maddr.domain[0] == '\0') {
2659
				if (strlcpy(maddr.domain, conf->sc_hostname,
2660
					sizeof (maddr.domain))
2661
				    >= sizeof (maddr.domain)) {
2662
					yyerror("hostname too long for AS parameter: %s",
2663
					    conf->sc_hostname);
2664
					YYERROR;
2665
				}
2666
			}
2667
			rule->r_as = xmemdup(&maddr, sizeof (*maddrp), "parse relay_as: AS");
2668
		}
2669
break;
2670
case 81:
2671
#line 730 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2672
{
2673
			struct table	*t = yyvsp[0].v.table;
2674
			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_SOURCE)) {
2675
				yyerror("invalid use of table \"%s\" as "
2676
				    "SOURCE parameter", t->t_name);
2677
				YYERROR;
2678
			}
2679
			(void)strlcpy(rule->r_value.relayhost.sourcetable, t->t_name,
2680
			    sizeof rule->r_value.relayhost.sourcetable);
2681
		}
2682
break;
2683
case 82:
2684
#line 740 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2685
{
2686
			(void)strlcpy(rule->r_value.relayhost.heloname, yyvsp[0].v.string,
2687
			    sizeof rule->r_value.relayhost.heloname);
2688
			free(yyvsp[0].v.string);
2689
		}
2690
break;
2691
case 83:
2692
#line 745 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2693
{
2694
			struct table	*t = yyvsp[0].v.table;
2695
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ADDRNAME)) {
2696
				yyerror("invalid use of table \"%s\" as "
2697
				    "HOSTNAMES parameter", t->t_name);
2698
				YYERROR;
2699
			}
2700
			(void)strlcpy(rule->r_value.relayhost.helotable, t->t_name,
2701
			    sizeof rule->r_value.relayhost.helotable);
2702
		}
2703
break;
2704
case 84:
2705
#line 755 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2706
{
2707
			if (!lowercase(rule->r_value.relayhost.pki_name, yyvsp[0].v.string,
2708
				sizeof(rule->r_value.relayhost.pki_name))) {
2709
				yyerror("pki name too long: %s", yyvsp[0].v.string);
2710
				free(yyvsp[0].v.string);
2711
				YYERROR;
2712
			}
2713
			if (dict_get(conf->sc_pki_dict,
2714
				rule->r_value.relayhost.pki_name) == NULL) {
2715
				log_warnx("pki name not found: %s", yyvsp[0].v.string);
2716
				free(yyvsp[0].v.string);
2717
				YYERROR;
2718
			}
2719
			free(yyvsp[0].v.string);
2720
		}
2721
break;
2722
case 85:
2723
#line 770 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2724
{
2725
			if (!lowercase(rule->r_value.relayhost.ca_name, yyvsp[0].v.string,
2726
				sizeof(rule->r_value.relayhost.ca_name))) {
2727
				yyerror("ca name too long: %s", yyvsp[0].v.string);
2728
				free(yyvsp[0].v.string);
2729
				YYERROR;
2730
			}
2731
			if (dict_get(conf->sc_ca_dict,
2732
				rule->r_value.relayhost.ca_name) == NULL) {
2733
				log_warnx("ca name not found: %s", yyvsp[0].v.string);
2734
				free(yyvsp[0].v.string);
2735
				YYERROR;
2736
			}
2737
			free(yyvsp[0].v.string);
2738
		}
2739
break;
2740
case 86:
2741
#line 787 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2742
{
2743
			rule->r_value.relayhost.flags |= F_BACKUP;
2744
			if (strlcpy(rule->r_value.relayhost.hostname, yyvsp[0].v.string,
2745
				sizeof (rule->r_value.relayhost.hostname))
2746
			    >= sizeof (rule->r_value.relayhost.hostname)) {
2747
				log_warnx("hostname too long: %s", yyvsp[0].v.string);
2748
				free(yyvsp[0].v.string);
2749
				YYERROR;
2750
			}
2751
			free(yyvsp[0].v.string);
2752
		}
2753
break;
2754
case 87:
2755
#line 798 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2756
{
2757
			rule->r_value.relayhost.flags |= F_BACKUP;
2758
			(void)strlcpy(rule->r_value.relayhost.hostname,
2759
			    conf->sc_hostname,
2760
			    sizeof (rule->r_value.relayhost.hostname));
2761
		}
2762
break;
2763
case 88:
2764
#line 804 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2765
{
2766
			rule->r_value.relayhost.flags |= F_STARTTLS;
2767
		}
2768
break;
2769
case 89:
2770
#line 807 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2771
{
2772
			rule->r_value.relayhost.flags |= F_STARTTLS|F_TLS_VERIFY;
2773
		}
2774
break;
2775
case 93:
2776
#line 817 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2777
{
2778
			struct table   *t = yyvsp[0].v.table;
2779
2780
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_CREDENTIALS)) {
2781
				yyerror("invalid use of table \"%s\" as AUTH parameter",
2782
				    t->t_name);
2783
				YYERROR;
2784
			}
2785
			(void)strlcpy(rule->r_value.relayhost.authtable, t->t_name,
2786
			    sizeof(rule->r_value.relayhost.authtable));
2787
		}
2788
break;
2789
case 94:
2790
#line 828 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2791
{
2792
			if (!(rule->r_value.relayhost.flags & F_SSL)) {
2793
				yyerror("cannot \"verify\" with insecure protocol");
2794
				YYERROR;
2795
			}
2796
			rule->r_value.relayhost.flags |= F_TLS_VERIFY;
2797
		}
2798
break;
2799
case 98:
2800
#line 842 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2801
{
2802
			memset(conf->sc_bounce_warn, 0, sizeof conf->sc_bounce_warn);
2803
		}
2804
break;
2805
case 100:
2806
#line 845 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2807
{
2808
			if (strlen(yyvsp[0].v.string) != 1) {
2809
				yyerror("subaddressing-delimiter must be one character");
2810
				free(yyvsp[0].v.string);
2811
				YYERROR;
2812
			}
2813
2814
			if (isspace((int)*yyvsp[0].v.string) ||  !isprint((int)*yyvsp[0].v.string) || *yyvsp[0].v.string== '@') {
2815
				yyerror("subaddressing-delimiter uses invalid character");
2816
				free(yyvsp[0].v.string);
2817
				YYERROR;
2818
			}
2819
2820
			conf->sc_subaddressing_delim = yyvsp[0].v.string;
2821
		}
2822
break;
2823
case 101:
2824
#line 860 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2825
{
2826
			conf->sc_queue_flags |= QUEUE_COMPRESSION;
2827
		}
2828
break;
2829
case 102:
2830
#line 863 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2831
{
2832
			conf->sc_queue_flags |= QUEUE_ENCRYPTION;
2833
		}
2834
break;
2835
case 103:
2836
#line 866 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2837
{
2838
			if (strcasecmp(yyvsp[0].v.string, "stdin") == 0 || strcasecmp(yyvsp[0].v.string, "-") == 0) {
2839
				conf->sc_queue_key = "stdin";
2840
				free(yyvsp[0].v.string);
2841
			}
2842
			else
2843
				conf->sc_queue_key = yyvsp[0].v.string;
2844
			conf->sc_queue_flags |= QUEUE_ENCRYPTION;
2845
		}
2846
break;
2847
case 104:
2848
#line 875 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2849
{
2850
			conf->sc_qexpire = delaytonum(yyvsp[0].v.string);
2851
			if (conf->sc_qexpire == -1) {
2852
				yyerror("invalid expire delay: %s", yyvsp[0].v.string);
2853
				free(yyvsp[0].v.string);
2854
				YYERROR;
2855
			}
2856
			free(yyvsp[0].v.string);
2857
		}
2858
break;
2859
case 105:
2860
#line 884 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2861
{
2862
			conf->sc_maxsize = yyvsp[0].v.number;
2863
		}
2864
break;
2865
case 106:
2866
#line 887 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2867
{
2868
			conf->sc_mta_max_deferred = yyvsp[0].v.number;
2869
		}
2870
break;
2871
case 109:
2872
#line 892 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2873
{
2874
			struct mta_limits	*d;
2875
2876
			limits = dict_get(conf->sc_limits_dict, yyvsp[0].v.string);
2877
			if (limits == NULL) {
2878
				limits = xcalloc(1, sizeof(*limits), "mta_limits");
2879
				dict_xset(conf->sc_limits_dict, yyvsp[0].v.string, limits);
2880
				d = dict_xget(conf->sc_limits_dict, "default");
2881
				memmove(limits, d, sizeof(*limits));
2882
			}
2883
			free(yyvsp[0].v.string);
2884
		}
2885
break;
2886
case 111:
2887
#line 904 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2888
{
2889
			limits = dict_get(conf->sc_limits_dict, "default");
2890
		}
2891
break;
2892
case 114:
2893
#line 908 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2894
{
2895
			memset(&listen_opts, 0, sizeof listen_opts);
2896
			listen_opts.family = AF_UNSPEC;
2897
			listen_opts.flags |= F_EXT_DSN;
2898
		}
2899
break;
2900
case 116:
2901
#line 913 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2902
{
2903
			char buf[HOST_NAME_MAX+1];
2904
2905
			/* if not catchall, check that it is a valid domain */
2906
			if (strcmp(yyvsp[0].v.string, "*") != 0) {
2907
				if (!res_hnok(yyvsp[0].v.string)) {
2908
					yyerror("not a valid domain name: %s", yyvsp[0].v.string);
2909
					free(yyvsp[0].v.string);
2910
					YYERROR;
2911
				}
2912
			}
2913
			xlowercase(buf, yyvsp[0].v.string, sizeof(buf));
2914
			free(yyvsp[0].v.string);
2915
			pki = dict_get(conf->sc_pki_dict, buf);
2916
			if (pki == NULL) {
2917
				pki = xcalloc(1, sizeof *pki, "parse:pki");
2918
				(void)strlcpy(pki->pki_name, buf, sizeof(pki->pki_name));
2919
				dict_set(conf->sc_pki_dict, pki->pki_name, pki);
2920
			}
2921
		}
2922
break;
2923
case 118:
2924
#line 933 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2925
{
2926
			char buf[HOST_NAME_MAX+1];
2927
2928
			/* if not catchall, check that it is a valid domain */
2929
			if (strcmp(yyvsp[0].v.string, "*") != 0) {
2930
				if (!res_hnok(yyvsp[0].v.string)) {
2931
					yyerror("not a valid domain name: %s", yyvsp[0].v.string);
2932
					free(yyvsp[0].v.string);
2933
					YYERROR;
2934
				}
2935
			}
2936
			xlowercase(buf, yyvsp[0].v.string, sizeof(buf));
2937
			free(yyvsp[0].v.string);
2938
			sca = dict_get(conf->sc_ca_dict, buf);
2939
			if (sca == NULL) {
2940
				sca = xcalloc(1, sizeof *sca, "parse:ca");
2941
				(void)strlcpy(sca->ca_name, buf, sizeof(sca->ca_name));
2942
				dict_set(conf->sc_ca_dict, sca->ca_name, sca);
2943
			}
2944
		}
2945
break;
2946
case 120:
2947
#line 953 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2948
{
2949
			conf->sc_tls_ciphers = yyvsp[0].v.string;
2950
		}
2951
break;
2952
case 121:
2953
#line 958 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2954
{
2955
			char *p, *backend, *config;
2956
2957
			p = yyvsp[0].v.string;
2958
			if (*p == '/') {
2959
				backend = "static";
2960
				config = yyvsp[0].v.string;
2961
			}
2962
			else {
2963
				backend = yyvsp[0].v.string;
2964
				config = NULL;
2965
				for (p = yyvsp[0].v.string; *p && *p != ':'; p++)
2966
					;
2967
				if (*p == ':') {
2968
					*p = '\0';
2969
					backend = yyvsp[0].v.string;
2970
					config  = p+1;
2971
				}
2972
			}
2973
			if (config != NULL && *config != '/') {
2974
				yyerror("invalid backend parameter for table: %s",
2975
				    yyvsp[-1].v.string);
2976
				free(yyvsp[-1].v.string);
2977
				free(yyvsp[0].v.string);
2978
				YYERROR;
2979
			}
2980
			table = table_create(backend, yyvsp[-1].v.string, NULL, config);
2981
			if (!table_config(table)) {
2982
				yyerror("invalid configuration file %s for table %s",
2983
				    config, table->t_name);
2984
				free(yyvsp[-1].v.string);
2985
				free(yyvsp[0].v.string);
2986
				YYERROR;
2987
			}
2988
			free(yyvsp[-1].v.string);
2989
			free(yyvsp[0].v.string);
2990
		}
2991
break;
2992
case 122:
2993
#line 995 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
2994
{
2995
			table = table_create("static", yyvsp[0].v.string, NULL, NULL);
2996
			free(yyvsp[0].v.string);
2997
		}
2998
break;
2999
case 123:
3000
#line 998 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3001
{
3002
			table = NULL;
3003
		}
3004
break;
3005
case 126:
3006
#line 1005 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3007
{
3008
			table->t_type = T_HASH;
3009
			table_add(table, yyvsp[-2].v.string, yyvsp[0].v.string);
3010
			free(yyvsp[-2].v.string);
3011
			free(yyvsp[0].v.string);
3012
		}
3013
break;
3014
case 129:
3015
#line 1017 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3016
{
3017
			table->t_type = T_LIST;
3018
			table_add(table, yyvsp[0].v.string, NULL);
3019
			free(yyvsp[0].v.string);
3020
		}
3021
break;
3022
case 132:
3023
#line 1028 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3024
{ }
3025
break;
3026
case 133:
3027
#line 1029 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3028
{ }
3029
break;
3030
case 134:
3031
#line 1032 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3032
{
3033
			struct table	*t;
3034
3035
			t = table_create("static", NULL, NULL, NULL);
3036
			t->t_type = T_LIST;
3037
			table_add(t, yyvsp[0].v.string, NULL);
3038
			free(yyvsp[0].v.string);
3039
			yyval.v.table = t;
3040
		}
3041
break;
3042
case 135:
3043
#line 1041 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3044
{
3045
			table = table_create("static", NULL, NULL, NULL);
3046
		}
3047
break;
3048
case 136:
3049
#line 1043 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3050
{
3051
			yyval.v.table = table;
3052
		}
3053
break;
3054
case 137:
3055
#line 1048 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3056
{
3057
			struct table	*t;
3058
3059
			if ((t = table_find(yyvsp[-1].v.string, NULL)) == NULL) {
3060
				yyerror("no such table: %s", yyvsp[-1].v.string);
3061
				free(yyvsp[-1].v.string);
3062
				YYERROR;
3063
			}
3064
			free(yyvsp[-1].v.string);
3065
			yyval.v.table = t;
3066
		}
3067
break;
3068
case 138:
3069
#line 1061 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3070
{ yyval.v.table = yyvsp[0].v.table; }
3071
break;
3072
case 139:
3073
#line 1062 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3074
{ yyval.v.table = yyvsp[0].v.table; }
3075
break;
3076
case 140:
3077
#line 1065 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3078
{
3079
			struct table   *t = yyvsp[0].v.table;
3080
3081
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) {
3082
				yyerror("invalid use of table \"%s\" as ALIAS parameter",
3083
				    t->t_name);
3084
				YYERROR;
3085
			}
3086
3087
			yyval.v.table = t;
3088
		}
3089
break;
3090
case 141:
3091
#line 1078 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3092
{
3093
			struct table   *t = yyvsp[0].v.table;
3094
3095
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_ALIAS)) {
3096
				yyerror("invalid use of table \"%s\" as VIRTUAL parameter",
3097
				    t->t_name);
3098
				YYERROR;
3099
			}
3100
			yyval.v.table = t;
3101
		}
3102
break;
3103
case 142:
3104
#line 1090 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3105
{
3106
			if (rule->r_mapping) {
3107
				yyerror("alias specified multiple times");
3108
				YYERROR;
3109
			}
3110
			rule->r_desttype = DEST_DOM;
3111
			rule->r_mapping = yyvsp[0].v.table;
3112
		}
3113
break;
3114
case 143:
3115
#line 1098 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3116
{
3117
			if (rule->r_mapping) {
3118
				yyerror("virtual specified multiple times");
3119
				YYERROR;
3120
			}
3121
			rule->r_desttype = DEST_VDOM;
3122
			rule->r_mapping = yyvsp[0].v.table;
3123
		}
3124
break;
3125
case 144:
3126
#line 1108 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3127
{
3128
			struct table   *t = yyvsp[0].v.table;
3129
3130
			if (rule->r_userbase) {
3131
				yyerror("userbase specified multiple times");
3132
				YYERROR;
3133
			}
3134
			if (!table_check_use(t, T_DYNAMIC|T_HASH, K_USERINFO)) {
3135
				yyerror("invalid use of table \"%s\" as USERBASE parameter",
3136
				    t->t_name);
3137
				YYERROR;
3138
			}
3139
			rule->r_userbase = t;
3140
		}
3141
break;
3142
case 145:
3143
#line 1124 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3144
{
3145
			if (strlcpy(rule->r_delivery_user, yyvsp[0].v.string,
3146
			    sizeof(rule->r_delivery_user))
3147
			    >= sizeof(rule->r_delivery_user))
3148
				fatal("username too long");
3149
			free(yyvsp[0].v.string);
3150
		}
3151
break;
3152
case 146:
3153
#line 1131 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3154
{}
3155
break;
3156
case 147:
3157
#line 1134 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3158
{
3159
			rule->r_action = A_MAILDIR;
3160
			if (strlcpy(rule->r_value.buffer, "~/Maildir",
3161
			    sizeof(rule->r_value.buffer)) >=
3162
			    sizeof(rule->r_value.buffer))
3163
				fatal("pathname too long");
3164
		}
3165
break;
3166
case 148:
3167
#line 1141 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3168
{
3169
			rule->r_action = A_MAILDIR;
3170
			if (strlcpy(rule->r_value.buffer, yyvsp[0].v.string,
3171
			    sizeof(rule->r_value.buffer)) >=
3172
			    sizeof(rule->r_value.buffer))
3173
				fatal("pathname too long");
3174
			free(yyvsp[0].v.string);
3175
		}
3176
break;
3177
case 149:
3178
#line 1149 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3179
{
3180
			rule->r_action = A_MBOX;
3181
			if (strlcpy(rule->r_value.buffer, _PATH_MAILDIR "/%u",
3182
			    sizeof(rule->r_value.buffer))
3183
			    >= sizeof(rule->r_value.buffer))
3184
				fatal("pathname too long");
3185
		}
3186
break;
3187
case 150:
3188
#line 1156 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3189
{
3190
			rule->r_action = A_LMTP;
3191
			if (strchr(yyvsp[-1].v.string, ':') || yyvsp[-1].v.string[0] == '/') {
3192
				if (strlcpy(rule->r_value.buffer, yyvsp[-1].v.string,
3193
					sizeof(rule->r_value.buffer))
3194
					>= sizeof(rule->r_value.buffer))
3195
					fatal("lmtp destination too long");
3196
			} else
3197
				fatal("invalid lmtp destination");
3198
			free(yyvsp[-1].v.string);
3199
		}
3200
break;
3201
case 151:
3202
#line 1167 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3203
{
3204
			rule->r_action = A_LMTP;
3205
			if (strchr(yyvsp[-2].v.string, ':') || yyvsp[-2].v.string[0] == '/') {
3206
				if (strlcpy(rule->r_value.buffer, yyvsp[-2].v.string,
3207
					sizeof(rule->r_value.buffer))
3208
					>= sizeof(rule->r_value.buffer))
3209
					fatal("lmtp destination too long");
3210
				if (strlcat(rule->r_value.buffer, " rcpt-to",
3211
					sizeof(rule->r_value.buffer))
3212
					>= sizeof(rule->r_value.buffer))
3213
					fatal("lmtp recipient too long");
3214
			} else
3215
				fatal("invalid lmtp destination");
3216
			free(yyvsp[-2].v.string);
3217
		}
3218
break;
3219
case 152:
3220
#line 1182 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3221
{
3222
			rule->r_action = A_MDA;
3223
			if (strlcpy(rule->r_value.buffer, yyvsp[-1].v.string,
3224
			    sizeof(rule->r_value.buffer))
3225
			    >= sizeof(rule->r_value.buffer))
3226
				fatal("command too long");
3227
			free(yyvsp[-1].v.string);
3228
		}
3229
break;
3230
case 153:
3231
#line 1192 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3232
{
3233
			rule->r_action = A_RELAY;
3234
		}
3235
break;
3236
case 154:
3237
#line 1195 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3238
{
3239
			rule->r_action = A_RELAYVIA;
3240
			if (!text_to_relayhost(&rule->r_value.relayhost, yyvsp[0].v.string)) {
3241
				yyerror("error: invalid url: %s", yyvsp[0].v.string);
3242
				free(yyvsp[0].v.string);
3243
				YYERROR;
3244
			}
3245
			free(yyvsp[0].v.string);
3246
		}
3247
break;
3248
case 155:
3249
#line 1203 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3250
{
3251
			/* no worries, F_AUTH cant be set without SSL */
3252
			if (rule->r_value.relayhost.flags & F_AUTH) {
3253
				if (rule->r_value.relayhost.authtable[0] == '\0') {
3254
					yyerror("error: auth without auth table");
3255
					YYERROR;
3256
				}
3257
			}
3258
		}
3259
break;
3260
case 156:
3261
#line 1214 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3262
{ yyval.v.number = 1; }
3263
break;
3264
case 157:
3265
#line 1215 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3266
{ yyval.v.number = 0; }
3267
break;
3268
case 158:
3269
#line 1218 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3270
{
3271
			struct table   *t = yyvsp[0].v.table;
3272
3273
			if (rule->r_sources) {
3274
				yyerror("from specified multiple times");
3275
				YYERROR;
3276
			}
3277
			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_NETADDR)) {
3278
				yyerror("invalid use of table \"%s\" as FROM parameter",
3279
				    t->t_name);
3280
				YYERROR;
3281
			}
3282
			rule->r_notsources = yyvsp[-2].v.number;
3283
			rule->r_sources = t;
3284
		}
3285
break;
3286
case 159:
3287
#line 1233 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3288
{
3289
			if (rule->r_sources) {
3290
				yyerror("from specified multiple times");
3291
				YYERROR;
3292
			}
3293
			rule->r_sources = table_find("<anyhost>", NULL);
3294
			rule->r_notsources = yyvsp[-1].v.number;
3295
		}
3296
break;
3297
case 160:
3298
#line 1241 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3299
{
3300
			if (rule->r_sources) {
3301
				yyerror("from specified multiple times");
3302
				YYERROR;
3303
			}
3304
			rule->r_sources = table_find("<localhost>", NULL);
3305
			rule->r_notsources = yyvsp[-1].v.number;
3306
		}
3307
break;
3308
case 161:
3309
#line 1251 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3310
{
3311
			struct table   *t = yyvsp[0].v.table;
3312
3313
			if (rule->r_destination) {
3314
				yyerror("for specified multiple times");
3315
				YYERROR;
3316
			}
3317
			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) {
3318
				yyerror("invalid use of table \"%s\" as DOMAIN parameter",
3319
				    t->t_name);
3320
				YYERROR;
3321
			}
3322
			rule->r_notdestination = yyvsp[-2].v.number;
3323
			rule->r_destination = t;
3324
		}
3325
break;
3326
case 162:
3327
#line 1266 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3328
{
3329
			if (rule->r_destination) {
3330
				yyerror("for specified multiple times");
3331
				YYERROR;
3332
			}
3333
			rule->r_notdestination = yyvsp[-1].v.number;
3334
			rule->r_destination = table_find("<anydestination>", NULL);
3335
		}
3336
break;
3337
case 163:
3338
#line 1274 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3339
{
3340
			if (rule->r_destination) {
3341
				yyerror("for specified multiple times");
3342
				YYERROR;
3343
			}
3344
			rule->r_notdestination = yyvsp[-1].v.number;
3345
			rule->r_destination = table_find("<localnames>", NULL);
3346
		}
3347
break;
3348
case 164:
3349
#line 1284 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3350
{
3351
			struct table   *t = yyvsp[0].v.table;
3352
3353
			if (rule->r_senders) {
3354
				yyerror("sender specified multiple times");
3355
				YYERROR;
3356
			}
3357
3358
			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) {
3359
				yyerror("invalid use of table \"%s\" as SENDER parameter",
3360
				    t->t_name);
3361
				YYERROR;
3362
			}
3363
			rule->r_notsenders = yyvsp[-1].v.number;
3364
			rule->r_senders = t;
3365
		}
3366
break;
3367
case 165:
3368
#line 1302 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3369
{
3370
			struct table   *t = yyvsp[0].v.table;
3371
3372
			if (rule->r_recipients) {
3373
				yyerror("recipient specified multiple times");
3374
				YYERROR;
3375
			}
3376
3377
			if (!table_check_use(t, T_DYNAMIC|T_LIST, K_MAILADDR)) {
3378
				yyerror("invalid use of table \"%s\" as RECIPIENT parameter",
3379
				    t->t_name);
3380
				YYERROR;
3381
			}
3382
			rule->r_notrecipients = yyvsp[-1].v.number;
3383
			rule->r_recipients = t;
3384
		}
3385
break;
3386
case 166:
3387
#line 1320 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3388
{
3389
			if (rule->r_forwardonly) {
3390
				yyerror("forward-only specified multiple times");
3391
				YYERROR;
3392
			}
3393
			rule->r_forwardonly = 1;
3394
		}
3395
break;
3396
case 167:
3397
#line 1329 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3398
{
3399
			if (rule->r_qexpire != -1) {
3400
				yyerror("expire specified multiple times");
3401
				YYERROR;
3402
			}
3403
			rule->r_qexpire = delaytonum(yyvsp[0].v.string);
3404
			if (rule->r_qexpire == -1) {
3405
				yyerror("invalid expire delay: %s", yyvsp[0].v.string);
3406
				free(yyvsp[0].v.string);
3407
				YYERROR;
3408
			}
3409
			free(yyvsp[0].v.string);
3410
		}
3411
break;
3412
case 187:
3413
#line 1375 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3414
{
3415
			rule = xcalloc(1, sizeof(*rule), "parse rule: ACCEPT");
3416
			rule->r_id = ++ruleid;
3417
			rule->r_action = A_NONE;
3418
			rule->r_decision = R_ACCEPT;
3419
			rule->r_desttype = DEST_DOM;
3420
			rule->r_qexpire = -1;
3421
		}
3422
break;
3423
case 188:
3424
#line 1382 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3425
{
3426
			if (!rule->r_sources)
3427
				rule->r_sources = table_find("<localhost>", NULL);
3428
			if (!rule->r_destination)
3429
			 	rule->r_destination = table_find("<localnames>", NULL);
3430
			if (!rule->r_userbase)
3431
				rule->r_userbase = table_find("<getpwnam>", NULL);
3432
			if (rule->r_qexpire == -1)
3433
				rule->r_qexpire = conf->sc_qexpire;
3434
			if (rule->r_action == A_RELAY || rule->r_action == A_RELAYVIA) {
3435
				if (rule->r_userbase != table_find("<getpwnam>", NULL)) {
3436
					yyerror("userbase may not be used with a relay rule");
3437
					YYERROR;
3438
				}
3439
				if (rule->r_mapping) {
3440
					yyerror("aliases/virtual may not be used with a relay rule");
3441
					YYERROR;
3442
				}
3443
			}
3444
			if (rule->r_forwardonly && rule->r_action != A_NONE) {
3445
				yyerror("forward-only may not be used with a default action");
3446
				YYERROR;
3447
			}
3448
			TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry);
3449
			rule = NULL;
3450
		}
3451
break;
3452
case 189:
3453
#line 1408 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3454
{
3455
			rule = xcalloc(1, sizeof(*rule), "parse rule: REJECT");
3456
			rule->r_id = ++ruleid;
3457
			rule->r_decision = R_REJECT;
3458
			rule->r_desttype = DEST_DOM;
3459
		}
3460
break;
3461
case 190:
3462
#line 1413 "/usr/src/usr.sbin/smtpd/smtpctl/../parse.y"
3463
{
3464
			if (!rule->r_sources)
3465
				rule->r_sources = table_find("<localhost>", NULL);
3466
			if (!rule->r_destination)
3467
				rule->r_destination = table_find("<localnames>", NULL);
3468
			TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry);
3469
			rule = NULL;
3470
		}
3471
break;
3472
#line 3465 "parse.c"
3473
    }
3474
    yyssp -= yym;
3475
    yystate = *yyssp;
3476
    yyvsp -= yym;
3477
    yym = yylhs[yyn];
3478
    if (yystate == 0 && yym == 0)
3479
    {
3480
#if YYDEBUG
3481
        if (yydebug)
3482
            printf("%sdebug: after reduction, shifting from state 0 to\
3483
 state %d\n", YYPREFIX, YYFINAL);
3484
#endif
3485
        yystate = YYFINAL;
3486
        *++yyssp = YYFINAL;
3487
        *++yyvsp = yyval;
3488
        if (yychar < 0)
3489
        {
3490
            if ((yychar = yylex()) < 0) yychar = 0;
3491
#if YYDEBUG
3492
            if (yydebug)
3493
            {
3494
                yys = 0;
3495
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
3496
                if (!yys) yys = "illegal-symbol";
3497
                printf("%sdebug: state %d, reading %d (%s)\n",
3498
                        YYPREFIX, YYFINAL, yychar, yys);
3499
            }
3500
#endif
3501
        }
3502
        if (yychar == 0) goto yyaccept;
3503
        goto yyloop;
3504
    }
3505
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
3506
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
3507
        yystate = yytable[yyn];
3508
    else
3509
        yystate = yydgoto[yym];
3510
#if YYDEBUG
3511
    if (yydebug)
3512
        printf("%sdebug: after reduction, shifting from state %d \
3513
to state %d\n", YYPREFIX, *yyssp, yystate);
3514
#endif
3515
    if (yyssp >= yysslim && yygrowstack())
3516
    {
3517
        goto yyoverflow;
3518
    }
3519
    *++yyssp = yystate;
3520
    *++yyvsp = yyval;
3521
    goto yyloop;
3522
yyoverflow:
3523
    yyerror("yacc stack overflow");
3524
yyabort:
3525
    if (yyss)
3526
            free(yyss);
3527
    if (yyvs)
3528
            free(yyvs);
3529
    yyss = yyssp = NULL;
3530
    yyvs = yyvsp = NULL;
3531
    yystacksize = 0;
3532
    return (1);
3533
yyaccept:
3534
    if (yyss)
3535
            free(yyss);
3536
    if (yyvs)
3537
            free(yyvs);
3538
    yyss = yyssp = NULL;
3539
    yyvs = yyvsp = NULL;
3540
    yystacksize = 0;
3541
    return (0);
3542
}