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