parse.y revision 1.33
1/*	$OpenBSD: parse.y,v 1.33 2005/11/06 22:51:51 hshoexer Exp $	*/
2
3/*
4 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
6 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
7 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
8 * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
9 *
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23%{
24#include <sys/types.h>
25#include <sys/queue.h>
26#include <sys/socket.h>
27#include <sys/stat.h>
28#include <netinet/in.h>
29#include <netinet/ip_ipsp.h>
30#include <arpa/inet.h>
31
32#include <ctype.h>
33#include <err.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <limits.h>
37#include <stdarg.h>
38#include <stdio.h>
39#include <string.h>
40#include <syslog.h>
41#include <unistd.h>
42
43#include "ipsecctl.h"
44
45#define KEYSIZE_LIMIT	1024
46
47static struct ipsecctl	*ipsec = NULL;
48static FILE		*fin = NULL;
49static int		 lineno = 1;
50static int		 errors = 0;
51static int		 debug = 0;
52
53const struct ipsec_xf authxfs[] = {
54	{"unknown",		AUTHXF_UNKNOWN,		0,	0},
55	{"none",		AUTHXF_NONE,		0,	0},
56	{"hmac-md5",		AUTHXF_HMAC_MD5,	16,	0},
57	{"hmac-ripemd160",	AUTHXF_HMAC_RIPEMD160,	20,	0},
58	{"hmac-sha1",		AUTHXF_HMAC_SHA1,	20,	0},
59	{"hmac-sha2-256",	AUTHXF_HMAC_SHA2_256,	32,	0},
60	{"hmac-sha2-384",	AUTHXF_HMAC_SHA2_384,	48,	0},
61	{"hmac-sha2-512",	AUTHXF_HMAC_SHA2_512,	64,	0},
62	{"md5",			AUTHXF_MD5,		16,	0},
63	{"sha1",		AUTHXF_SHA1,		20,	0},
64	{NULL,			0,			0,	0},
65};
66
67const struct ipsec_xf encxfs[] = {
68	{"unknown",		ENCXF_UNKNOWN,		0,	0},
69	{"none",		ENCXF_NONE,		0,	0},
70	{"3des-cbc",		ENCXF_3DES_CBC,		24,	24},
71	{"des-cbc",		ENCXF_DES_CBC,		8,	8},
72	{"aes",			ENCXF_AES,		16,	32},
73	{"aesctr",		ENCXF_AESCTR,		16+4,	32+4},
74	{"blowfish",		ENCXF_BLOWFISH,		5,	56},
75	{"cast128",		ENCXF_CAST128,		5,	16},
76	{"null",		ENCXF_NULL,		0,	0},
77	{"skipjack",		ENCXF_SKIPJACK,		10,	10},
78	{NULL,			0,			0,	0},
79};
80
81const struct ipsec_xf compxfs[] = {
82	{"unknown",		COMPXF_UNKNOWN,		0,	0},
83	{"deflate",		COMPXF_DEFLATE,		0,	0},
84	{"lzs",			COMPXF_LZS,		0,	0},
85	{NULL,			0,			0,	0},
86};
87
88int			 yyerror(const char *, ...);
89int			 yyparse(void);
90int			 kw_cmp(const void *, const void *);
91int			 lookup(char *);
92int			 lgetc(FILE *);
93int			 lungetc(int);
94int			 findeol(void);
95int			 yylex(void);
96
97TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
98struct sym {
99	TAILQ_ENTRY(sym)	 entries;
100	int		 used;
101	int		 persist;
102	char		*nam;
103	char		*val;
104};
105
106int			 symset(const char *, const char *, int);
107int			 cmdline_symset(char *);
108char			*symget(const char *);
109int			 atoul(char *, u_long *);
110int			 atospi(char *, u_int32_t *);
111u_int8_t		 x2i(unsigned char *);
112struct ipsec_key	*parsekey(unsigned char *, size_t);
113struct ipsec_key	*parsekeyfile(char *);
114struct ipsec_addr_wrap	*host(const char *);
115struct ipsec_addr_wrap	*host_v4(const char *, int);
116void			 set_ipmask(struct ipsec_addr_wrap *, u_int8_t);
117struct ipsec_addr_wrap	*copyhost(const struct ipsec_addr_wrap *);
118const struct ipsec_xf	*parse_xf(const char *, const struct ipsec_xf *);
119struct ipsec_transforms *transforms(const char *, const char *, const char *);
120struct ipsec_transforms *copytransforms(const struct ipsec_transforms *);
121int			 validate_sa(u_int32_t, u_int8_t,
122			     struct ipsec_transforms *, struct ipsec_key *,
123			     struct ipsec_key *);
124struct ipsec_rule	*create_sa(u_int8_t, struct ipsec_addr_wrap *,
125			     struct ipsec_addr_wrap *, u_int32_t,
126			     struct ipsec_transforms *, struct ipsec_key *,
127			     struct ipsec_key *);
128struct ipsec_rule	*reverse_sa(struct ipsec_rule *, u_int32_t,
129			     struct ipsec_key *, struct ipsec_key *);
130struct ipsec_rule	*create_flow(u_int8_t, struct ipsec_addr_wrap *, struct
131			     ipsec_addr_wrap *, struct ipsec_addr_wrap *,
132			     u_int8_t, char *, char *, u_int16_t);
133struct ipsec_rule	*reverse_rule(struct ipsec_rule *);
134struct ipsec_rule	*create_ike(struct ipsec_addr_wrap *, struct
135			     ipsec_addr_wrap *, struct ipsec_addr_wrap *,
136			     struct ipsec_transforms *, struct
137			     ipsec_transforms *, u_int8_t, u_int8_t, char *,
138			     char *);
139
140typedef struct {
141	union {
142		u_int32_t	 number;
143		u_int8_t	 ikemode;
144		u_int8_t	 dir;
145		char		*string;
146		u_int8_t	 protocol;
147		struct {
148			struct ipsec_addr_wrap *src;
149			struct ipsec_addr_wrap *dst;
150		} hosts;
151		struct ipsec_addr_wrap *peer;
152		struct ipsec_addr_wrap *host;
153		struct {
154			char *srcid;
155			char *dstid;
156		} ids;
157		char		*id;
158		u_int16_t	 authtype;
159		struct {
160			u_int32_t	spiout;
161			u_int32_t	spiin;
162		} spis;
163		struct {
164			struct ipsec_key *keyout;
165			struct ipsec_key *keyin;
166		} authkeys;
167		struct {
168			struct ipsec_key *keyout;
169			struct ipsec_key *keyin;
170		} enckeys;
171		struct {
172			struct ipsec_key *keyout;
173			struct ipsec_key *keyin;
174		} keys;
175		struct ipsec_transforms *transforms;
176		struct ipsec_transforms *mmxfs;
177		struct ipsec_transforms *qmxfs;
178	} v;
179	int lineno;
180} YYSTYPE;
181
182%}
183
184%token	FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI
185%token	AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE
186%token	ACTIVE ANY IPCOMP COMPXF
187%token	<v.string>		STRING
188%type	<v.dir>			dir
189%type	<v.protocol>		protocol
190%type	<v.number>		number
191%type	<v.hosts>		hosts
192%type	<v.peer>		peer
193%type	<v.host>		host
194%type	<v.ids>			ids
195%type	<v.id>			id
196%type	<v.authtype>		authtype
197%type	<v.spis>		spispec
198%type	<v.authkeys>		authkeyspec
199%type	<v.enckeys>		enckeyspec
200%type	<v.keys>		keyspec
201%type	<v.transforms>		transforms
202%type	<v.mmxfs>		mmxfs
203%type	<v.qmxfs>		qmxfs
204%type	<v.ikemode>		ikemode
205%%
206
207grammar		: /* empty */
208		| grammar '\n'
209		| grammar ikerule '\n'
210		| grammar flowrule '\n'
211		| grammar sarule '\n'
212		| grammar tcpmd5rule '\n'
213		| grammar error '\n'		{ errors++; }
214		;
215
216number		: STRING			{
217			unsigned long	ulval;
218
219			if (atoul($1, &ulval) == -1) {
220				yyerror("%s is not a number", $1);
221				free($1);
222				YYERROR;
223			}
224			if (ulval > UINT_MAX) {
225				yyerror("0x%lx out of range", ulval);
226				free($1);
227				YYERROR;
228			}
229			$$ = (u_int32_t)ulval;
230			free($1);
231		}
232
233tcpmd5rule	: TCPMD5 hosts spispec authkeyspec	{
234			struct ipsec_rule	*r;
235
236			r = create_sa(IPSEC_TCPMD5, $2.src, $2.dst, $3.spiout,
237			    NULL, $4.keyout, NULL);
238			if (r == NULL)
239				YYERROR;
240			r->nr = ipsec->rule_nr++;
241
242			if (ipsecctl_add_rule(ipsec, r))
243				errx(1, "tcpmd5rule: ipsecctl_add_rule");
244
245			/* Create and add reverse SA rule. */
246			if ($3.spiin != 0 || $4.keyin != NULL) {
247				r = reverse_sa(r, $3.spiin, $4.keyin, NULL);
248				if (r == NULL)
249					YYERROR;
250				r->nr = ipsec->rule_nr++;
251
252				if (ipsecctl_add_rule(ipsec, r))
253					errx(1, "tcpmd5rule: ipsecctl_add_rule");
254			}
255		}
256		;
257
258sarule		: protocol hosts spispec transforms authkeyspec enckeyspec {
259			struct ipsec_rule	*r;
260
261			r = create_sa($1, $2.src, $2.dst, $3.spiout, $4,
262			    $5.keyout, $6.keyout);
263			if (r == NULL)
264				YYERROR;
265			r->nr = ipsec->rule_nr++;
266
267			if (ipsecctl_add_rule(ipsec, r))
268				errx(1, "sarule: ipsecctl_add_rule");
269
270			/* Create and add reverse SA rule. */
271			if ($3.spiin != 0 || $5.keyin || $6.keyin) {
272				r = reverse_sa(r, $3.spiin, $5.keyin,
273				    $6.keyin);
274				if (r == NULL)
275					YYERROR;
276				r->nr = ipsec->rule_nr++;
277
278				if (ipsecctl_add_rule(ipsec, r))
279					errx(1, "sarule: ipsecctl_add_rule");
280			}
281		}
282		;
283
284flowrule	: FLOW protocol dir hosts peer ids authtype	{
285			struct ipsec_rule	*r;
286
287			r = create_flow($3, $4.src, $4.dst, $5, $2, $6.srcid,
288			    $6.dstid, $7);
289			if (r == NULL)
290				YYERROR;
291			r->nr = ipsec->rule_nr++;
292
293			if (ipsecctl_add_rule(ipsec, r))
294				errx(1, "flowrule: ipsecctl_add_rule");
295
296			/* Create and add reverse flow rule. */
297			if ($3 == IPSEC_INOUT) {
298				r = reverse_rule(r);
299				r->nr = ipsec->rule_nr++;
300
301				if (ipsecctl_add_rule(ipsec, r))
302					errx(1, "flowrule: ipsecctl_add_rule");
303			}
304		}
305		;
306
307ikerule		: IKE ikemode protocol hosts peer mmxfs qmxfs ids {
308			struct ipsec_rule	*r;
309
310			r = create_ike($4.src, $4.dst, $5, $6, $7, $3, $2,
311			    $8.srcid, $8.dstid);
312			if (r == NULL)
313				YYERROR;
314			r->nr = ipsec->rule_nr++;
315
316			if (ipsecctl_add_rule(ipsec, r))
317				errx(1, "ikerule: ipsecctl_add_rule");
318		};
319
320protocol	: /* empty */			{ $$ = IPSEC_ESP; }
321		| ESP				{ $$ = IPSEC_ESP; }
322		| AH				{ $$ = IPSEC_AH; }
323		| IPCOMP			{ $$ = IPSEC_IPCOMP; }
324		;
325
326dir		: /* empty */			{ $$ = IPSEC_INOUT; }
327		| IN				{ $$ = IPSEC_IN; }
328		| OUT				{ $$ = IPSEC_OUT; }
329		;
330
331hosts		: FROM host TO host		{
332			$$.src = $2;
333			$$.dst = $4;
334		}
335		;
336
337peer		: /* empty */			{ $$ = NULL; }
338		| PEER STRING			{
339			if (($$ = host($2)) == NULL) {
340				free($2);
341				yyerror("could not parse host specification");
342				YYERROR;
343			}
344			free($2);
345		}
346		;
347
348host		: STRING			{
349			if (($$ = host($1)) == NULL) {
350				free($1);
351				yyerror("could not parse host specification");
352				YYERROR;
353			}
354			free($1);
355		}
356		| STRING '/' number		{
357			char	*buf;
358
359			if (asprintf(&buf, "%s/%u", $1, $3) == -1)
360				err(1, "host: asprintf");
361			free($1);
362			if (($$ = host(buf)) == NULL)	{
363				free(buf);
364				yyerror("could not parse host specification");
365				YYERROR;
366			}
367			free(buf);
368		}
369		| ANY				{
370			struct ipsec_addr_wrap	*ipa;
371
372			ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
373			if (ipa == NULL)
374				err(1, "host: calloc");
375
376			ipa->af = AF_INET;
377			ipa->netaddress = 1;
378			if ((ipa->name = strdup("0.0.0.0/0")) == NULL)
379				err(1, "host: strdup");
380			$$ = ipa;
381		}
382		;
383
384ids		: /* empty */			{
385			$$.srcid = NULL;
386			$$.dstid = NULL;
387		}
388		| SRCID id DSTID id		{
389			$$.srcid = $2;
390			$$.dstid = $4;
391		}
392		| SRCID id			{
393			$$.srcid = $2;
394			$$.dstid = NULL;
395		}
396		| DSTID id			{
397			$$.srcid = NULL;
398			$$.dstid = $2;
399		}
400		;
401
402id		: STRING			{ $$ = $1; }
403		;
404
405authtype	: /* empty */			{ $$ = 0; }
406		| RSA				{ $$ = AUTH_RSA; }
407		| PSK				{ $$ = AUTH_PSK; }
408		;
409
410spispec		: SPI STRING			{
411			u_int32_t	 spi;
412			char		*p = strchr($2, ':');
413
414			if (p != NULL) {
415				*p++ = 0;
416
417				if (atospi(p, &spi) == -1) {
418					yyerror("%s is not a valid spi", p);
419					free($2);
420					YYERROR;
421				}
422				$$.spiin = spi;
423			}
424			if (atospi($2, &spi) == -1) {
425				yyerror("%s is not a valid spi", $2);
426				free($2);
427				YYERROR;
428			}
429			$$.spiout = spi;
430
431
432			free($2);
433		}
434		;
435
436transforms	: /* empty */			{
437			struct ipsec_transforms *xfs;
438
439			/* We create just an empty transform */
440			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
441			    == NULL)
442				err(1, "transforms: calloc");
443			$$ = xfs;
444		}
445		| AUTHXF STRING ENCXF STRING	{
446			if (($$ = transforms($2, $4, NULL)) == NULL) {
447				free($2);
448				free($4);
449				yyerror("could not parse transforms");
450				YYERROR;
451			}
452			free($2);
453			free($4);
454		}
455		| AUTHXF STRING			{
456			if (($$ = transforms($2, NULL, NULL)) == NULL) {
457				free($2);
458				yyerror("could not parse transforms");
459				YYERROR;
460			}
461			free($2);
462		}
463		| ENCXF STRING			{
464			if (($$ = transforms(NULL, $2, NULL)) == NULL) {
465				free($2);
466				yyerror("could not parse transforms");
467				YYERROR;
468			}
469			free($2);
470		}
471		| COMPXF STRING			{
472			if (($$ = transforms(NULL, NULL, $2)) == NULL) {
473				free($2);
474				yyerror("could not parse transforms");
475				YYERROR;
476			}
477			free($2);
478		}
479		;
480
481mmxfs		: /* empty */			{
482			struct ipsec_transforms *xfs;
483
484			/* We create just an empty transform */
485			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
486			    == NULL)
487				err(1, "mmxfs: calloc");
488			$$ = xfs;
489		}
490		| MAIN transforms		{ $$ = $2; }
491		;
492
493qmxfs		: /* empty */			{
494			struct ipsec_transforms *xfs;
495
496			/* We create just an empty transform */
497			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
498			    == NULL)
499				err(1, "qmxfs: calloc");
500			$$ = xfs;
501		}
502		| QUICK transforms		{ $$ = $2; }
503		;
504
505authkeyspec	: /* empty */			{
506			$$.keyout = NULL;
507			$$.keyin = NULL;
508		}
509		| AUTHKEY keyspec		{
510			$$.keyout = $2.keyout;
511			$$.keyin = $2.keyin;
512		}
513		;
514
515enckeyspec	: /* empty */			{
516			$$.keyout = NULL;
517			$$.keyin = NULL;
518		}
519		| ENCKEY keyspec		{
520			$$.keyout = $2.keyout;
521			$$.keyin = $2.keyin;
522		}
523		;
524
525keyspec		: STRING			{
526			unsigned char	*hex;
527			unsigned char	*p = strchr($1, ':');
528
529			if (p != NULL ) {
530				*p++ = 0;
531
532				if (!strncmp(p, "0x", 2))
533					p += 2;
534				$$.keyin = parsekey(p, strlen(p));
535			}
536
537			hex = $1;
538			if (!strncmp(hex, "0x", 2))
539				hex += 2;
540			$$.keyout = parsekey(hex, strlen(hex));
541
542			free($1);
543		}
544		| FILENAME STRING		{
545			unsigned char	*p = strchr($2, ':');
546
547			if (p != NULL) {
548				*p++ = 0;
549				$$.keyin = parsekeyfile(p);
550			}
551			$$.keyout = parsekeyfile($2);
552			free($2);
553		}
554		;
555ikemode		: /* empty */			{ $$ = IKE_ACTIVE; }
556		| PASSIVE			{ $$ = IKE_PASSIVE; }
557		| ACTIVE			{ $$ = IKE_ACTIVE; }
558		;
559%%
560
561struct keywords {
562	const char	*k_name;
563	int		 k_val;
564};
565
566int
567yyerror(const char *fmt, ...)
568{
569	va_list		 ap;
570	extern char 	*infile;
571
572	errors = 1;
573	va_start(ap, fmt);
574	fprintf(stderr, "%s: %d: ", infile, yyval.lineno);
575	vfprintf(stderr, fmt, ap);
576	fprintf(stderr, "\n");
577	va_end(ap);
578	return (0);
579}
580
581int
582kw_cmp(const void *k, const void *e)
583{
584	return (strcmp(k, ((const struct keywords *)e)->k_name));
585}
586
587int
588lookup(char *s)
589{
590	/* this has to be sorted always */
591	static const struct keywords keywords[] = {
592		{ "active",		ACTIVE},
593		{ "ah",			AH},
594		{ "any",		ANY},
595		{ "auth",		AUTHXF},
596		{ "authkey",		AUTHKEY},
597		{ "comp",		COMPXF},
598		{ "dstid",		DSTID},
599		{ "enc",		ENCXF},
600		{ "enckey",		ENCKEY},
601		{ "esp",		ESP},
602		{ "file",		FILENAME},
603		{ "flow",		FLOW},
604		{ "from",		FROM},
605		{ "ike",		IKE},
606		{ "in",			IN},
607		{ "ipcomp",		IPCOMP},
608		{ "main",		MAIN},
609		{ "out",		OUT},
610		{ "passive",		PASSIVE},
611		{ "peer",		PEER},
612		{ "psk",		PSK},
613		{ "quick",		QUICK},
614		{ "rsa",		RSA},
615		{ "spi",		SPI},
616		{ "srcid",		SRCID},
617		{ "tcpmd5",		TCPMD5},
618		{ "to",			TO},
619	};
620	const struct keywords	*p;
621
622	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
623	    sizeof(keywords[0]), kw_cmp);
624
625	if (p) {
626		if (debug > 1)
627			fprintf(stderr, "%s: %d\n", s, p->k_val);
628		return (p->k_val);
629	} else {
630		if (debug > 1)
631			fprintf(stderr, "string: %s\n", s);
632		return (STRING);
633	}
634}
635
636#define MAXPUSHBACK	128
637
638char	*parsebuf;
639int	 parseindex;
640char	 pushback_buffer[MAXPUSHBACK];
641int	 pushback_index = 0;
642
643int
644lgetc(FILE *f)
645{
646	int	c, next;
647
648	if (parsebuf) {
649		/* Read character from the parsebuffer instead of input. */
650		if (parseindex >= 0) {
651			c = parsebuf[parseindex++];
652			if (c != '\0')
653				return (c);
654			parsebuf = NULL;
655		} else
656			parseindex++;
657	}
658
659	if (pushback_index)
660		return (pushback_buffer[--pushback_index]);
661
662	while ((c = getc(f)) == '\\') {
663		next = getc(f);
664		if (next != '\n') {
665			if (isspace(next))
666				yyerror("whitespace after \\");
667			ungetc(next, f);
668			break;
669		}
670		yylval.lineno = lineno;
671		lineno++;
672	}
673	if (c == '\t' || c == ' ') {
674		/* Compress blanks to a single space. */
675		do {
676			c = getc(f);
677		} while (c == '\t' || c == ' ');
678		ungetc(c, f);
679		c = ' ';
680	}
681
682	return (c);
683}
684
685int
686lungetc(int c)
687{
688	if (c == EOF)
689		return (EOF);
690	if (parsebuf) {
691		parseindex--;
692		if (parseindex >= 0)
693			return (c);
694	}
695	if (pushback_index < MAXPUSHBACK-1)
696		return (pushback_buffer[pushback_index++] = c);
697	else
698		return (EOF);
699}
700
701int
702findeol(void)
703{
704	int	c;
705
706	parsebuf = NULL;
707	pushback_index = 0;
708
709	/* skip to either EOF or the first real EOL */
710	while (1) {
711		c = lgetc(fin);
712		if (c == '\n') {
713			lineno++;
714			break;
715		}
716		if (c == EOF)
717			break;
718	}
719	return (ERROR);
720}
721
722int
723yylex(void)
724{
725	char	 buf[8096];
726	char	*p, *val;
727	int	 endc, c;
728	int	 token;
729
730top:
731	p = buf;
732	while ((c = lgetc(fin)) == ' ')
733		; /* nothing */
734
735	yylval.lineno = lineno;
736	if (c == '#')
737		while ((c = lgetc(fin)) != '\n' && c != EOF)
738			; /* nothing */
739	if (c == '$' && parsebuf == NULL) {
740		while (1) {
741			if ((c = lgetc(fin)) == EOF)
742				return (0);
743
744			if (p + 1 >= buf + sizeof(buf) - 1) {
745				yyerror("string too long");
746				return (findeol());
747			}
748			if (isalnum(c) || c == '_') {
749				*p++ = (char)c;
750				continue;
751			}
752			*p = '\0';
753			lungetc(c);
754			break;
755		}
756		val = symget(buf);
757		if (val == NULL) {
758			yyerror("macro \"%s\" not defined", buf);
759			return (findeol());
760		}
761		parsebuf = val;
762		parseindex = 0;
763		goto top;
764	}
765
766	switch (c) {
767	case '\'':
768	case '"':
769		endc = c;
770		while (1) {
771			if ((c = lgetc(fin)) == EOF)
772				return (0);
773			if (c == endc) {
774				*p = '\0';
775				break;
776			}
777			if (c == '\n') {
778				lineno++;
779				continue;
780			}
781			if (p + 1 >= buf + sizeof(buf) - 1) {
782				yyerror("string too long");
783				return (findeol());
784			}
785			*p++ = (char)c;
786		}
787		yylval.v.string = strdup(buf);
788		if (yylval.v.string == NULL)
789			err(1, "yylex: strdup");
790		return (STRING);
791	}
792
793#define allowed_in_string(x) \
794	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
795	x != '{' && x != '}' && x != '<' && x != '>' && \
796	x != '!' && x != '=' && x != '/' && x != '#' && \
797	x != ','))
798
799	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
800		do {
801			*p++ = c;
802			if ((unsigned)(p-buf) >= sizeof(buf)) {
803				yyerror("string too long");
804				return (findeol());
805			}
806		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
807		lungetc(c);
808		*p = '\0';
809		if ((token = lookup(buf)) == STRING)
810			if ((yylval.v.string = strdup(buf)) == NULL)
811				err(1, "yylex: strdup");
812		return (token);
813	}
814	if (c == '\n') {
815		yylval.lineno = lineno;
816		lineno++;
817	}
818	if (c == EOF)
819		return (0);
820	return (c);
821}
822
823int
824parse_rules(FILE *input, struct ipsecctl *ipsecx)
825{
826	struct sym	*sym, *next;
827
828	ipsec = ipsecx;
829	fin = input;
830	lineno = 1;
831	errors = 0;
832
833	yyparse();
834
835	/* Free macros and check which have not been used. */
836	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
837		next = TAILQ_NEXT(sym, entries);
838		free(sym->nam);
839		free(sym->val);
840		TAILQ_REMOVE(&symhead, sym, entries);
841		free(sym);
842	}
843
844	return (errors ? -1 : 0);
845}
846
847int
848symset(const char *nam, const char *val, int persist)
849{
850	struct sym	*sym;
851
852	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
853	    sym = TAILQ_NEXT(sym, entries))
854		;	/* nothing */
855
856	if (sym != NULL) {
857		if (sym->persist == 1)
858			return (0);
859		else {
860			free(sym->nam);
861			free(sym->val);
862			TAILQ_REMOVE(&symhead, sym, entries);
863			free(sym);
864		}
865	}
866	if ((sym = calloc(1, sizeof(*sym))) == NULL)
867		return (-1);
868
869	sym->nam = strdup(nam);
870	if (sym->nam == NULL) {
871		free(sym);
872		return (-1);
873	}
874	sym->val = strdup(val);
875	if (sym->val == NULL) {
876		free(sym->nam);
877		free(sym);
878		return (-1);
879	}
880	sym->used = 0;
881	sym->persist = persist;
882	TAILQ_INSERT_TAIL(&symhead, sym, entries);
883	return (0);
884}
885
886int
887cmdline_symset(char *s)
888{
889	char	*sym, *val;
890	int	ret;
891	size_t	len;
892
893	if ((val = strrchr(s, '=')) == NULL)
894		return (-1);
895
896	len = strlen(s) - strlen(val) + 1;
897	if ((sym = malloc(len)) == NULL)
898		err(1, "cmdline_symset: malloc");
899
900	strlcpy(sym, s, len);
901
902	ret = symset(sym, val + 1, 1);
903	free(sym);
904
905	return (ret);
906}
907
908char *
909symget(const char *nam)
910{
911	struct sym	*sym;
912
913	TAILQ_FOREACH(sym, &symhead, entries)
914		if (strcmp(nam, sym->nam) == 0) {
915			sym->used = 1;
916			return (sym->val);
917		}
918	return (NULL);
919}
920
921int
922atoul(char *s, u_long *ulvalp)
923{
924	u_long	 ulval;
925	char	*ep;
926
927	errno = 0;
928	ulval = strtoul(s, &ep, 0);
929	if (s[0] == '\0' || *ep != '\0')
930		return (-1);
931	if (errno == ERANGE && ulval == ULONG_MAX)
932		return (-1);
933	*ulvalp = ulval;
934	return (0);
935}
936
937int
938atospi(char *s, u_int32_t *spivalp)
939{
940	unsigned long	ulval;
941
942	if (atoul(s, &ulval) == -1)
943		return (-1);
944	if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) {
945		yyerror("illegal SPI value");
946		return (-1);
947	}
948	*spivalp = ulval;
949	return (0);
950}
951
952u_int8_t
953x2i(unsigned char *s)
954{
955	char	ss[3];
956
957	ss[0] = s[0];
958	ss[1] = s[1];
959	ss[2] = 0;
960
961	if (!isxdigit(s[0]) || !isxdigit(s[1])) {
962		yyerror("keys need to be specified in hex digits");
963		return (-1);
964	}
965	return ((u_int8_t)strtoul(ss, NULL, 16));
966}
967
968struct ipsec_key *
969parsekey(unsigned char *hexkey, size_t len)
970{
971	struct ipsec_key *key;
972	int		  i;
973
974	key = calloc(1, sizeof(struct ipsec_key));
975	if (key == NULL)
976		err(1, "parsekey: calloc");
977
978	key->len = len / 2;
979	key->data = calloc(key->len, sizeof(u_int8_t));
980	if (key->data == NULL)
981		err(1, "parsekey: calloc");
982
983	for (i = 0; i < (int)key->len; i++)
984		key->data[i] = x2i(hexkey + 2 * i);
985
986	return (key);
987}
988
989struct ipsec_key *
990parsekeyfile(char *filename)
991{
992	struct stat	 sb;
993	int		 fd;
994	unsigned char	*hex;
995
996	if (stat(filename, &sb) < 0)
997		err(1, "parsekeyfile: stat %s", filename);
998	if ((sb.st_size > KEYSIZE_LIMIT) || (sb.st_size == 0))
999		errx(1, "parsekeyfile: key too %s", sb.st_size ? "large" :
1000		    "small");
1001	if ((hex = calloc(sb.st_size, sizeof(unsigned char)))
1002	    == NULL)
1003		err(1, "parsekeyfile: calloc");
1004	if ((fd = open(filename, O_RDONLY)) < 0)
1005		err(1, "parsekeyfile: open");
1006	if (read(fd, hex, sb.st_size) < sb.st_size)
1007		err(1, "parsekeyfile: read");
1008	close(fd);
1009	return (parsekey(hex, sb.st_size));
1010}
1011
1012struct ipsec_addr_wrap *
1013host(const char *s)
1014{
1015	struct ipsec_addr_wrap	*ipa = NULL;
1016	int			 mask, v4mask, cont = 1;
1017	char			*p, *q, *ps;
1018
1019	if ((p = strrchr(s, '/')) != NULL) {
1020		mask = strtol(p + 1, &q, 0);
1021		if (!q || *q || mask > 32 || q == (p + 1))
1022			errx(1, "host: invalid netmask '%s'", p);
1023		if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
1024			err(1, "host: calloc");
1025		strlcpy(ps, s, strlen(s) - strlen(p) + 1);
1026		v4mask = mask;
1027	} else {
1028		if ((ps = strdup(s)) == NULL)
1029			err(1, "host: strdup");
1030		v4mask = 32;
1031		mask = -1;
1032	}
1033
1034#if notyet
1035	/* Does interface with this name exist? */
1036	if (cont && (ipa = host_if(ps, mask)) != NULL)
1037		cont = 0;
1038#endif
1039
1040	/* IPv4 address? */
1041	if (cont && (ipa = host_v4(s, mask)) != NULL)
1042		cont = 0;
1043
1044#if notyet
1045	/* IPv6 address? */
1046	if (cont && (ipa = host_dsn(ps, v4mask, 0)) != NULL)
1047		cont = 0;
1048#endif
1049	free(ps);
1050
1051	if (ipa == NULL || cont == 1) {
1052		fprintf(stderr, "no IP address found for %s\n", s);
1053		return (NULL);
1054	}
1055	return (ipa);
1056}
1057
1058struct ipsec_addr_wrap *
1059host_v4(const char *s, int mask)
1060{
1061	struct ipsec_addr_wrap	*ipa = NULL;
1062	struct in_addr		 ina;
1063	int			 bits = 32;
1064
1065	bzero(&ina, sizeof(struct in_addr));
1066	if (strrchr(s, '/') != NULL) {
1067		if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
1068			return (NULL);
1069	} else {
1070		if (inet_pton(AF_INET, s, &ina) != 1)
1071			return (NULL);
1072	}
1073
1074	ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1075	if (ipa == NULL)
1076		err(1, "host_v4: calloc");
1077
1078	ipa->address.v4 = ina;
1079	ipa->name = strdup(s);
1080	if (ipa->name == NULL)
1081		err(1, "host_v4: strdup");
1082	ipa->af = AF_INET;
1083
1084	set_ipmask(ipa, bits);
1085	if (bits != (ipa->af == AF_INET ? 32 : 128))
1086		ipa->netaddress = 1;
1087
1088	return (ipa);
1089}
1090
1091void
1092set_ipmask(struct ipsec_addr_wrap *address, u_int8_t b)
1093{
1094	struct ipsec_addr 	*ipa;
1095	int			 i, j = 0;
1096
1097	ipa = &address->mask;
1098	bzero(ipa, sizeof(struct ipsec_addr));
1099
1100	while (b >= 32) {
1101		ipa->addr32[j++] = 0xffffffff;
1102		b -= 32;
1103	}
1104	for (i = 31; i > 31 - b; --i)
1105		ipa->addr32[j] |= (1 << i);
1106	if (b)
1107		ipa->addr32[j] = htonl(ipa->addr32[j]);
1108}
1109
1110struct ipsec_addr_wrap *
1111copyhost(const struct ipsec_addr_wrap *src)
1112{
1113	struct ipsec_addr_wrap *dst;
1114
1115	dst = calloc(1, sizeof(struct ipsec_addr_wrap));
1116	if (dst == NULL)
1117		err(1, "copyhost: calloc");
1118
1119	memcpy(dst, src, sizeof(struct ipsec_addr_wrap));
1120
1121	if ((dst->name = strdup(src->name)) == NULL)
1122		err(1, "copyhost: strdup");
1123
1124	return dst;
1125}
1126
1127const struct ipsec_xf *
1128parse_xf(const char *name, const struct ipsec_xf xfs[])
1129{
1130	int		i;
1131
1132	for (i = 0; xfs[i].name != NULL; i++) {
1133		if (strncmp(name, xfs[i].name, strlen(name)))
1134			continue;
1135		return &xfs[i];
1136	}
1137	return (NULL);
1138}
1139
1140struct ipsec_transforms *
1141transforms(const char *authname, const char *encname, const char *compname)
1142{
1143	struct ipsec_transforms *xfs;
1144
1145	xfs = calloc(1, sizeof(struct ipsec_transforms));
1146	if (xfs == NULL)
1147		err(1, "transforms: calloc");
1148
1149	if (authname) {
1150		xfs->authxf = parse_xf(authname, authxfs);
1151		if (xfs->authxf == NULL)
1152			yyerror("%s not a valid transform", authname);
1153	}
1154	if (encname) {
1155		xfs->encxf = parse_xf(encname, encxfs);
1156		if (xfs->encxf == NULL)
1157			yyerror("%s not a valid transform", encname);
1158	}
1159	if (compname) {
1160		xfs->compxf = parse_xf(compname, compxfs);
1161		if (xfs->compxf == NULL)
1162			yyerror("%s not a valid transform", compname);
1163	}
1164
1165	return (xfs);
1166}
1167
1168struct ipsec_transforms *
1169copytransforms(const struct ipsec_transforms *xfs)
1170{
1171	struct ipsec_transforms *newxfs;
1172
1173	if (xfs == NULL)
1174		return (NULL);
1175
1176	newxfs = calloc(1, sizeof(struct ipsec_transforms));
1177	if (newxfs == NULL)
1178		err(1, "copytransforms: calloc");
1179
1180	memcpy(newxfs, xfs, sizeof(struct ipsec_transforms));
1181	return (newxfs);
1182}
1183
1184int
1185validate_sa(u_int32_t spi, u_int8_t protocol, struct ipsec_transforms *xfs,
1186    struct ipsec_key *authkey, struct ipsec_key *enckey)
1187{
1188	/* Sanity checks */
1189	if (spi == 0) {
1190		yyerror("no SPI specified");
1191		return (0);
1192	}
1193	if (protocol == IPSEC_AH) {
1194		if (!xfs) {
1195			yyerror("no transforms specified");
1196			return (0);
1197		}
1198		if (!xfs->authxf)
1199			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1200		if (xfs->encxf) {
1201			yyerror("ah does not provide encryption");
1202			return (0);
1203		}
1204	}
1205	if (protocol == IPSEC_ESP) {
1206		if (!xfs) {
1207			yyerror("no transforms specified");
1208			return (0);
1209		}
1210		if (!xfs->authxf)
1211			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1212		if (!xfs->encxf)
1213			xfs->encxf = &encxfs[ENCXF_AESCTR];
1214	}
1215	if (protocol == IPSEC_IPCOMP) {
1216		if (!xfs) {
1217			yyerror("no transform specified");
1218			return (0);
1219		}
1220		if (!xfs->compxf)
1221			xfs->compxf = &compxfs[COMPXF_DEFLATE];
1222	}
1223	if (protocol == IPSEC_TCPMD5 && authkey == NULL) {
1224		yyerror("authentication key needed for tcpmd5");
1225		return (0);
1226	}
1227	if (xfs && xfs->authxf) {
1228		if (!authkey) {
1229			yyerror("no authentication key specified");
1230			return (0);
1231		}
1232		if (authkey->len != xfs->authxf->keymin) {
1233			yyerror("wrong authentication key length, needs to be "
1234			    "%d bits", xfs->authxf->keymin * 8);
1235			return (0);
1236		}
1237	}
1238	if (xfs && xfs->encxf) {
1239		if (!enckey && xfs->encxf != &encxfs[ENCXF_NULL]) {
1240			yyerror("no encryption key specified");
1241			return (0);
1242		}
1243		if (enckey) {
1244		if (enckey->len < xfs->encxf->keymin) {
1245			yyerror("encryption key too short, minimum %d bits",
1246			    xfs->encxf->keymin * 8);
1247			return (0);
1248		}
1249		if (xfs->encxf->keymax < enckey->len) {
1250			yyerror("encryption key too long, maximum %d bits",
1251			    xfs->encxf->keymax * 8);
1252			return (0);
1253		}
1254		}
1255	}
1256
1257	return 1;
1258}
1259
1260struct ipsec_rule *
1261create_sa(u_int8_t protocol, struct ipsec_addr_wrap *src, struct
1262    ipsec_addr_wrap *dst, u_int32_t spi, struct ipsec_transforms *xfs,
1263    struct ipsec_key *authkey, struct ipsec_key *enckey)
1264{
1265	struct ipsec_rule *r;
1266
1267	if (validate_sa(spi, protocol, xfs, authkey, enckey) == 0)
1268		return (NULL);
1269
1270	r = calloc(1, sizeof(struct ipsec_rule));
1271	if (r == NULL)
1272		err(1, "create_sa: calloc");
1273
1274	r->type |= RULE_SA;
1275	r->proto = protocol;
1276	r->src = src;
1277	r->dst = dst;
1278	r->spi = spi;
1279	r->xfs = xfs;
1280	r->authkey = authkey;
1281	r->enckey = enckey;
1282
1283	return r;
1284}
1285
1286struct ipsec_rule *
1287reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey,
1288    struct ipsec_key *enckey)
1289{
1290	struct ipsec_rule *reverse;
1291
1292	if (validate_sa(spi, rule->proto, rule->xfs, authkey, enckey) == 0)
1293		return (NULL);
1294
1295	reverse = calloc(1, sizeof(struct ipsec_rule));
1296	if (reverse == NULL)
1297		err(1, "reverse_sa: calloc");
1298
1299	reverse->type |= RULE_SA;
1300	reverse->proto = rule->proto;
1301	reverse->src = copyhost(rule->dst);
1302	reverse->dst = copyhost(rule->src);
1303	reverse->spi = spi;
1304	reverse->xfs = copytransforms(rule->xfs);
1305	reverse->authkey = authkey;
1306	reverse->enckey = enckey;
1307
1308	return (reverse);
1309}
1310
1311struct ipsec_rule *
1312create_flow(u_int8_t dir, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap
1313    *dst, struct ipsec_addr_wrap *peer, u_int8_t proto, char *srcid, char
1314    *dstid, u_int16_t authtype)
1315{
1316	struct ipsec_rule *r;
1317
1318	r = calloc(1, sizeof(struct ipsec_rule));
1319	if (r == NULL)
1320		err(1, "create_flow: calloc");
1321
1322	r->type |= RULE_FLOW;
1323
1324	if (dir == IPSEC_INOUT)
1325		r->direction = IPSEC_OUT;
1326	else
1327		r->direction = dir;
1328
1329	if (r->direction == IPSEC_IN)
1330		r->flowtype = TYPE_USE;
1331	else
1332		r->flowtype = TYPE_REQUIRE;
1333
1334	r->src = src;
1335	r->dst = dst;
1336
1337	if (peer == NULL) {
1338		/* Set peer to remote host.  Must be a host address. */
1339		if (r->direction == IPSEC_IN) {
1340			if (r->src->netaddress) {
1341				yyerror("no peer specified");
1342				goto errout;
1343			}
1344			r->peer = copyhost(r->src);
1345		} else {
1346			if (r->dst->netaddress) {
1347				yyerror("no peer specified");
1348				goto errout;
1349			}
1350			r->peer = copyhost(r->dst);
1351		}
1352	} else
1353		r->peer = peer;
1354
1355	r->proto = proto;
1356	r->auth = calloc(1, sizeof(struct ipsec_auth));
1357	if (r->auth == NULL)
1358		err(1, "create_flow: calloc");
1359	r->auth->srcid = srcid;
1360	r->auth->dstid = dstid;
1361	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
1362#ifdef notyet
1363	r->auth->type = authtype;
1364#endif
1365
1366	return r;
1367
1368errout:
1369	free(r);
1370	if (srcid)
1371		free(srcid);
1372	if (dstid)
1373		free(dstid);
1374	free(src);
1375	free(dst);
1376
1377	return NULL;
1378}
1379
1380struct ipsec_rule *
1381reverse_rule(struct ipsec_rule *rule)
1382{
1383	struct ipsec_rule *reverse;
1384
1385	reverse = calloc(1, sizeof(struct ipsec_rule));
1386	if (reverse == NULL)
1387		err(1, "reverse_rule: calloc");
1388
1389	reverse->type |= RULE_FLOW;
1390
1391	if (rule->direction == (u_int8_t)IPSEC_OUT) {
1392		reverse->direction = (u_int8_t)IPSEC_IN;
1393		reverse->flowtype = TYPE_USE;
1394	} else {
1395		reverse->direction = (u_int8_t)IPSEC_OUT;
1396		reverse->flowtype = TYPE_REQUIRE;
1397	}
1398
1399	reverse->src = copyhost(rule->dst);
1400	reverse->dst = copyhost(rule->src);
1401	reverse->peer = copyhost(rule->peer);
1402	reverse->proto = (u_int8_t)rule->proto;
1403
1404	reverse->auth = calloc(1, sizeof(struct ipsec_auth));
1405	if (reverse->auth == NULL)
1406		err(1, "reverse_rule: calloc");
1407	if (rule->auth->dstid && (reverse->auth->dstid =
1408	    strdup(rule->auth->dstid)) == NULL)
1409		err(1, "reverse_rule: strdup");
1410	if (rule->auth->srcid && (reverse->auth->srcid =
1411	    strdup(rule->auth->srcid)) == NULL)
1412		err(1, "reverse_rule: strdup");
1413	reverse->auth->idtype = rule->auth->idtype;
1414	reverse->auth->type = rule->auth->type;
1415
1416	return reverse;
1417}
1418
1419struct ipsec_rule *
1420create_ike(struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst, struct
1421    ipsec_addr_wrap * peer, struct ipsec_transforms *mmxfs, struct
1422    ipsec_transforms *qmxfs, u_int8_t proto, u_int8_t mode, char *srcid, char
1423    *dstid)
1424{
1425	struct ipsec_rule *r;
1426
1427	r = calloc(1, sizeof(struct ipsec_rule));
1428	if (r == NULL)
1429		err(1, "create_ike: calloc");
1430
1431	r->type = RULE_IKE;
1432
1433	r->src = src;
1434	r->dst = dst;
1435
1436	if (peer == NULL) {
1437		/* Set peer to remote host.  Must be a host address. */
1438		if (r->direction == IPSEC_IN) {
1439			if (r->src->netaddress) {
1440				yyerror("no peer specified");
1441				goto errout;
1442			}
1443			r->peer = copyhost(r->src);
1444		} else {
1445			if (r->dst->netaddress) {
1446				yyerror("no peer specified");
1447				goto errout;
1448			}
1449			r->peer = copyhost(r->dst);
1450		}
1451	} else
1452		r->peer = peer;
1453
1454	r->proto = proto;
1455	r->ikemode = mode;
1456	r->mmxfs = mmxfs;
1457	r->qmxfs = qmxfs;
1458	r->auth = calloc(1, sizeof(struct ipsec_auth));
1459	if (r->auth == NULL)
1460		err(1, "create_ike: calloc");
1461	r->auth->srcid = srcid;
1462	r->auth->dstid = dstid;
1463	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
1464
1465	return (r);
1466
1467errout:
1468	free(r);
1469	if (srcid)
1470		free(srcid);
1471	if (dstid)
1472		free(dstid);
1473	free(src);
1474	free(dst);
1475
1476	return (NULL);
1477}
1478