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