parse.y revision 1.75
1/*	$OpenBSD: parse.y,v 1.75 2006/05/29 15:22:40 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/ioctl.h>
26#include <sys/queue.h>
27#include <sys/socket.h>
28#include <sys/stat.h>
29#include <net/if.h>
30#include <netinet/in.h>
31#include <netinet/ip_ipsp.h>
32#include <arpa/inet.h>
33
34#include <ctype.h>
35#include <err.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <ifaddrs.h>
39#include <limits.h>
40#include <netdb.h>
41#include <stdarg.h>
42#include <stdio.h>
43#include <string.h>
44#include <syslog.h>
45#include <unistd.h>
46#include <netdb.h>
47
48#include "ipsecctl.h"
49
50#define KEYSIZE_LIMIT	1024
51
52static struct ipsecctl	*ipsec = NULL;
53static FILE		*fin = NULL;
54static int		 lineno = 1;
55static int		 errors = 0;
56static int		 debug = 0;
57
58const struct ipsec_xf authxfs[] = {
59	{ "unknown",		AUTHXF_UNKNOWN,		0,	0 },
60	{ "none",		AUTHXF_NONE,		0,	0 },
61	{ "hmac-md5",		AUTHXF_HMAC_MD5,	16,	0 },
62	{ "hmac-ripemd160",	AUTHXF_HMAC_RIPEMD160,	20,	0 },
63	{ "hmac-sha1",		AUTHXF_HMAC_SHA1,	20,	0 },
64	{ "hmac-sha2-256",	AUTHXF_HMAC_SHA2_256,	32,	0 },
65	{ "hmac-sha2-384",	AUTHXF_HMAC_SHA2_384,	48,	0 },
66	{ "hmac-sha2-512",	AUTHXF_HMAC_SHA2_512,	64,	0 },
67	{ NULL,			0,			0,	0 },
68};
69
70const struct ipsec_xf encxfs[] = {
71	{ "unknown",		ENCXF_UNKNOWN,		0,	0 },
72	{ "none",		ENCXF_NONE,		0,	0 },
73	{ "3des-cbc",		ENCXF_3DES_CBC,		24,	24 },
74	{ "des-cbc",		ENCXF_DES_CBC,		8,	8 },
75	{ "aes",		ENCXF_AES,		16,	32 },
76	{ "aesctr",		ENCXF_AESCTR,		16+4,	32+4 },
77	{ "blowfish",		ENCXF_BLOWFISH,		5,	56 },
78	{ "cast128",		ENCXF_CAST128,		5,	16 },
79	{ "null",		ENCXF_NULL,		0,	0 },
80	{ "skipjack",		ENCXF_SKIPJACK,		10,	10 },
81	{ NULL,			0,			0,	0 },
82};
83
84const struct ipsec_xf compxfs[] = {
85	{ "unknown",		COMPXF_UNKNOWN,		0,	0 },
86	{ "deflate",		COMPXF_DEFLATE,		0,	0 },
87	{ "lzs",		COMPXF_LZS,		0,	0 },
88	{ NULL,			0,			0,	0 },
89};
90
91const struct ipsec_xf groupxfs[] = {
92	{ "unknown",		GROUPXF_UNKNOWN,	0,	0 },
93	{ "modp768",		GROUPXF_768,		768,	0 },
94	{ "grp1",		GROUPXF_768,		768,	0 },
95	{ "modp1024",		GROUPXF_1024,		1024,	0 },
96	{ "grp2",		GROUPXF_1024,		1024,	0 },
97	{ "modp1536",		GROUPXF_1536,		1536,	0 },
98	{ "grp5",		GROUPXF_1536,		1536,	0 },
99	{ "modp2048",		GROUPXF_2048,		2048,	0 },
100	{ "grp14",		GROUPXF_2048,		2048,	0 },
101	{ "modp3072",		GROUPXF_3072,		3072,	0 },
102	{ "grp15",		GROUPXF_3072,		3072,	0 },
103	{ "modp4096",		GROUPXF_4096,		4096,	0 },
104	{ "grp16",		GROUPXF_4096,		4096,	0 },
105	{ "modp6144",		GROUPXF_6144,		6144,	0 },
106	{ "grp18",		GROUPXF_6144,		6144,	0 },
107	{ "modp8192",		GROUPXF_8192,		8192,	0 },
108	{ "grp18",		GROUPXF_8192,		8192,	0 },
109	{ NULL,			0,			0,	0 },
110};
111
112int			 yyerror(const char *, ...);
113int			 yyparse(void);
114int			 kw_cmp(const void *, const void *);
115int			 lookup(char *);
116int			 lgetc(FILE *);
117int			 lungetc(int);
118int			 findeol(void);
119int			 yylex(void);
120
121TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
122struct sym {
123	TAILQ_ENTRY(sym)	 entries;
124	int		 used;
125	int		 persist;
126	char		*nam;
127	char		*val;
128};
129
130int			 symset(const char *, const char *, int);
131int			 cmdline_symset(char *);
132char			*symget(const char *);
133int			 atoul(char *, u_long *);
134int			 atospi(char *, u_int32_t *);
135u_int8_t		 x2i(unsigned char *);
136struct ipsec_key	*parsekey(unsigned char *, size_t);
137struct ipsec_key	*parsekeyfile(char *);
138struct ipsec_addr_wrap	*host(const char *);
139struct ipsec_addr_wrap	*host_v4(const char *, int);
140struct ipsec_addr_wrap	*host_dns(const char *, int, int);
141struct ipsec_addr_wrap	*host_if(const char *, int);
142void			 ifa_load(void);
143int			 ifa_exists(const char *);
144struct ipsec_addr_wrap	*ifa_lookup(const char *ifa_name);
145struct ipsec_addr_wrap	*ifa_grouplookup(const char *);
146void			 set_ipmask(struct ipsec_addr_wrap *, u_int8_t);
147struct ipsec_addr_wrap	*copyhost(const struct ipsec_addr_wrap *);
148const struct ipsec_xf	*parse_xf(const char *, const struct ipsec_xf *);
149struct ipsec_transforms *copytransforms(const struct ipsec_transforms *);
150int			 validate_sa(u_int32_t, u_int8_t,
151			     struct ipsec_transforms *, struct ipsec_key *,
152			     struct ipsec_key *, u_int8_t);
153struct ipsec_rule	*create_sa(u_int8_t, u_int8_t, struct ipsec_addr_wrap *,
154			     struct ipsec_addr_wrap *, u_int32_t,
155			     struct ipsec_transforms *, struct ipsec_key *,
156			     struct ipsec_key *);
157struct ipsec_rule	*reverse_sa(struct ipsec_rule *, u_int32_t,
158			     struct ipsec_key *, struct ipsec_key *);
159struct ipsec_rule	*create_flow(u_int8_t, u_int8_t, struct
160			     ipsec_addr_wrap *, struct ipsec_addr_wrap *,
161			     struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
162			     u_int8_t, char *, char *, u_int8_t);
163int			 expand_rule(struct ipsec_rule *, u_int8_t, u_int32_t,
164			     struct ipsec_key *, struct ipsec_key *);
165struct ipsec_rule	*reverse_rule(struct ipsec_rule *);
166struct ipsec_rule	*create_ike(u_int8_t, struct ipsec_addr_wrap *, struct
167			     ipsec_addr_wrap *, struct ipsec_addr_wrap *,
168			     struct ipsec_addr_wrap *,
169			     struct ipsec_transforms *, struct
170			     ipsec_transforms *, u_int8_t, u_int8_t, char *,
171			     char *, struct ike_auth *);
172
173struct ipsec_transforms *ipsec_transforms;
174
175typedef struct {
176	union {
177		u_int32_t	 number;
178		u_int8_t	 ikemode;
179		u_int8_t	 dir;
180		u_int8_t	 satype;	/* encapsulating prococol */
181		u_int8_t	 proto;		/* encapsulated protocol */
182		u_int8_t	 tmode;
183		char		*string;
184		struct {
185			struct ipsec_addr_wrap *src;
186			struct ipsec_addr_wrap *dst;
187		} hosts;
188		struct {
189			struct ipsec_addr_wrap *peer;
190			struct ipsec_addr_wrap *local;
191		} peers;
192		struct ipsec_addr_wrap *singlehost;
193		struct ipsec_addr_wrap *host;
194		struct {
195			char *srcid;
196			char *dstid;
197		} ids;
198		char		*id;
199		u_int8_t	 type;
200		struct ike_auth	 ikeauth;
201		struct {
202			u_int32_t	spiout;
203			u_int32_t	spiin;
204		} spis;
205		struct {
206			struct ipsec_key *keyout;
207			struct ipsec_key *keyin;
208		} authkeys;
209		struct {
210			struct ipsec_key *keyout;
211			struct ipsec_key *keyin;
212		} enckeys;
213		struct {
214			struct ipsec_key *keyout;
215			struct ipsec_key *keyin;
216		} keys;
217		struct ipsec_transforms *transforms;
218		struct ipsec_transforms *mmxfs;
219		struct ipsec_transforms *qmxfs;
220	} v;
221	int lineno;
222} YYSTYPE;
223
224%}
225
226%token	FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI
227%token	AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE
228%token	ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC
229%token	TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP
230%token	<v.string>		STRING
231%type	<v.string>		string
232%type	<v.dir>			dir
233%type	<v.satype>		satype
234%type	<v.proto>		proto
235%type	<v.tmode>		tmode
236%type	<v.number>		number
237%type	<v.hosts>		hosts
238%type	<v.peers>		peers
239%type	<v.singlehost>		singlehost
240%type	<v.host>		host
241%type	<v.ids>			ids
242%type	<v.id>			id
243%type	<v.spis>		spispec
244%type	<v.authkeys>		authkeyspec
245%type	<v.enckeys>		enckeyspec
246%type	<v.keys>		keyspec
247%type	<v.transforms>		transforms
248%type	<v.mmxfs>		mmxfs
249%type	<v.qmxfs>		qmxfs
250%type	<v.ikemode>		ikemode
251%type	<v.ikeauth>		ikeauth
252%type	<v.type>		type
253%%
254
255grammar		: /* empty */
256		| grammar '\n'
257		| grammar ikerule '\n'
258		| grammar flowrule '\n'
259		| grammar sarule '\n'
260		| grammar tcpmd5rule '\n'
261		| grammar varset '\n'
262		| grammar error '\n'		{ errors++; }
263		;
264
265number		: STRING			{
266			unsigned long	ulval;
267
268			if (atoul($1, &ulval) == -1) {
269				yyerror("%s is not a number", $1);
270				free($1);
271				YYERROR;
272			}
273			if (ulval > UINT_MAX) {
274				yyerror("0x%lx out of range", ulval);
275				free($1);
276				YYERROR;
277			}
278			$$ = (u_int32_t)ulval;
279			free($1);
280		}
281		;
282
283tcpmd5rule	: TCPMD5 hosts spispec authkeyspec	{
284			struct ipsec_rule	*r;
285
286			r = create_sa(IPSEC_TCPMD5, IPSEC_TRANSPORT, $2.src,
287			    $2.dst, $3.spiout, NULL, $4.keyout, NULL);
288			if (r == NULL)
289				YYERROR;
290			r->nr = ipsec->rule_nr++;
291
292			if (expand_rule(r, 0, $3.spiin, $4.keyin, NULL))
293				errx(1, "tcpmd5rule: expand_rule");
294		}
295		;
296
297sarule		: satype tmode hosts spispec transforms authkeyspec
298		    enckeyspec {
299			struct ipsec_rule	*r;
300
301			r = create_sa($1, $2, $3.src, $3.dst, $4.spiout, $5,
302			    $6.keyout, $7.keyout);
303			if (r == NULL)
304				YYERROR;
305			r->nr = ipsec->rule_nr++;
306
307			if (expand_rule(r, 0, $4.spiin, $6.keyin, $7.keyin))
308				errx(1, "sarule: expand_rule");
309		}
310		;
311
312flowrule	: FLOW satype dir proto hosts peers ids type {
313			struct ipsec_rule	*r;
314
315			r = create_flow($3, $4, $5.src, $5.dst, $6.local,
316			    $6.peer, $2, $7.srcid, $7.dstid, $8);
317			if (r == NULL)
318				YYERROR;
319
320			if (expand_rule(r, $3, 0, NULL, NULL))
321				errx(1, "flowrule: expand_rule");
322		}
323		;
324
325ikerule		: IKE ikemode satype proto hosts peers mmxfs qmxfs ids ikeauth {
326			struct ipsec_rule	*r;
327
328			r = create_ike($4, $5.src, $5.dst, $6.local, $6.peer,
329			    $7, $8, $3, $2, $9.srcid, $9.dstid, &$10);
330			if (r == NULL)
331				YYERROR;
332			r->nr = ipsec->rule_nr++;
333
334			if (expand_rule(r, 0, 0, NULL, NULL))
335				errx(1, "ikerule: expand_rule");
336		}
337		;
338
339satype		: /* empty */			{ $$ = IPSEC_ESP; }
340		| ESP				{ $$ = IPSEC_ESP; }
341		| AH				{ $$ = IPSEC_AH; }
342		| IPCOMP			{ $$ = IPSEC_IPCOMP; }
343		| IPIP				{ $$ = IPSEC_IPIP; }
344		;
345
346proto		: /* empty */			{ $$ = 0; }
347		| PROTO STRING			{
348			struct protoent *p;
349			const char *errstr;
350			int proto;
351
352			if ((p = getprotobyname($2)) != NULL) {
353				$$ = p->p_proto;
354			} else {
355				errstr = NULL;
356				proto = strtonum($2, 0, 255, &errstr);
357				if (errstr)
358					errx(1, "unknown protocol: %s", $2);
359				$$ = proto;
360			}
361
362		}
363		;
364
365tmode		: /* empty */			{ $$ = IPSEC_TUNNEL; }
366		| TUNNEL			{ $$ = IPSEC_TUNNEL; }
367		| TRANSPORT			{ $$ = IPSEC_TRANSPORT; }
368		;
369
370dir		: /* empty */			{ $$ = IPSEC_INOUT; }
371		| IN				{ $$ = IPSEC_IN; }
372		| OUT				{ $$ = IPSEC_OUT; }
373		;
374
375hosts		: FROM host TO host		{
376			$$.src = $2;
377			$$.dst = $4;
378		}
379		| TO host FROM host		{
380			$$.src = $4;
381			$$.dst = $2;
382		}
383		;
384
385peers		: /* empty */				{
386			$$.peer = NULL;
387			$$.local = NULL;
388		}
389		| PEER singlehost LOCAL singlehost	{
390			$$.peer = $2;
391			$$.local = $4;
392		}
393		| LOCAL singlehost PEER singlehost	{
394			$$.peer = $4;
395			$$.local = $2;
396		}
397		| PEER singlehost			{
398			$$.peer = $2;
399			$$.local = NULL;
400		}
401		| LOCAL singlehost			{
402			$$.peer = NULL;
403			$$.local = $2;
404		}
405		;
406
407singlehost	: /* empty */			{ $$ = NULL; }
408		| STRING			{
409			if (($$ = host($1)) == NULL) {
410				free($1);
411				yyerror("could not parse host specification");
412				YYERROR;
413			}
414			free($1);
415		}
416		;
417
418host		: STRING			{
419			if (($$ = host($1)) == NULL) {
420				free($1);
421				yyerror("could not parse host specification");
422				YYERROR;
423			}
424			free($1);
425		}
426		| STRING '/' number		{
427			char	*buf;
428
429			if (asprintf(&buf, "%s/%u", $1, $3) == -1)
430				err(1, "host: asprintf");
431			free($1);
432			if (($$ = host(buf)) == NULL)	{
433				free(buf);
434				yyerror("could not parse host specification");
435				YYERROR;
436			}
437			free(buf);
438		}
439		| ANY				{
440			struct ipsec_addr_wrap	*ipa;
441
442			ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
443			if (ipa == NULL)
444				err(1, "host: calloc");
445
446			ipa->af = AF_INET;
447			ipa->netaddress = 1;
448			if ((ipa->name = strdup("0.0.0.0/0")) == NULL)
449				err(1, "host: strdup");
450			$$ = ipa;
451		}
452		;
453
454ids		: /* empty */			{
455			$$.srcid = NULL;
456			$$.dstid = NULL;
457		}
458		| SRCID id DSTID id		{
459			$$.srcid = $2;
460			$$.dstid = $4;
461		}
462		| SRCID id			{
463			$$.srcid = $2;
464			$$.dstid = NULL;
465		}
466		| DSTID id			{
467			$$.srcid = NULL;
468			$$.dstid = $2;
469		}
470		;
471
472type		: /* empty */			{
473			$$ = TYPE_REQUIRE;
474		}
475		| TYPE USE			{
476			$$ = TYPE_USE;
477		}
478		| TYPE ACQUIRE			{
479			$$ = TYPE_ACQUIRE;
480		}
481		| TYPE REQUIRE			{
482			$$ = TYPE_REQUIRE;
483		}
484		| TYPE DENY			{
485			$$ = TYPE_DENY;
486		}
487		| TYPE BYPASS			{
488			$$ = TYPE_BYPASS;
489		}
490		| TYPE DONTACQ			{
491			$$ = TYPE_DONTACQ;
492		}
493		;
494
495id		: STRING			{ $$ = $1; }
496		;
497
498spispec		: SPI STRING			{
499			u_int32_t	 spi;
500			char		*p = strchr($2, ':');
501
502			if (p != NULL) {
503				*p++ = 0;
504
505				if (atospi(p, &spi) == -1) {
506					yyerror("%s is not a valid spi", p);
507					free($2);
508					YYERROR;
509				}
510				$$.spiin = spi;
511			}
512			if (atospi($2, &spi) == -1) {
513				yyerror("%s is not a valid spi", $2);
514				free($2);
515				YYERROR;
516			}
517			$$.spiout = spi;
518
519
520			free($2);
521		}
522		;
523
524transforms	:					{
525			if ((ipsec_transforms = calloc(1,
526			    sizeof(struct ipsec_transforms))) == NULL)
527				err(1, "transforms: calloc");
528		}
529		    transforms_l
530			{ $$ = ipsec_transforms; }
531		| /* empty */				{
532			if (($$ = calloc(1,
533			    sizeof(struct ipsec_transforms))) == NULL)
534				err(1, "transforms: calloc");
535		}
536		;
537
538transforms_l	: transforms_l transform
539		| transform
540		;
541
542transform	: AUTHXF STRING			{
543			if (ipsec_transforms->authxf)
544				yyerror("auth already set");
545			else {
546				ipsec_transforms->authxf = parse_xf($2,
547				    authxfs);
548				if (!ipsec_transforms->authxf)
549					yyerror("%s not a valid transform", $2);
550			}
551		}
552		| ENCXF STRING			{
553			if (ipsec_transforms->encxf)
554				yyerror("enc already set");
555			else {
556				ipsec_transforms->encxf = parse_xf($2, encxfs);
557				if (!ipsec_transforms->encxf)
558					yyerror("%s not a valid transform", $2);
559			}
560		}
561		| COMPXF STRING			{
562			if (ipsec_transforms->compxf)
563				yyerror("comp already set");
564			else {
565				ipsec_transforms->compxf = parse_xf($2,
566				    compxfs);
567				if (!ipsec_transforms->compxf)
568					yyerror("%s not a valid transform", $2);
569			}
570		}
571		| GROUP STRING			{
572			if (ipsec_transforms->groupxf)
573				yyerror("group already set");
574			else {
575				ipsec_transforms->groupxf = parse_xf($2,
576				    groupxfs);
577				if (!ipsec_transforms->groupxf)
578					yyerror("%s not a valid transform", $2);
579			}
580		}
581		;
582
583mmxfs		: /* empty */			{
584			struct ipsec_transforms *xfs;
585
586			/* We create just an empty transform */
587			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
588			    == NULL)
589				err(1, "mmxfs: calloc");
590			$$ = xfs;
591		}
592		| MAIN transforms		{ $$ = $2; }
593		;
594
595qmxfs		: /* empty */			{
596			struct ipsec_transforms *xfs;
597
598			/* We create just an empty transform */
599			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
600			    == NULL)
601				err(1, "qmxfs: calloc");
602			$$ = xfs;
603		}
604		| QUICK transforms		{ $$ = $2; }
605		;
606
607authkeyspec	: /* empty */			{
608			$$.keyout = NULL;
609			$$.keyin = NULL;
610		}
611		| AUTHKEY keyspec		{
612			$$.keyout = $2.keyout;
613			$$.keyin = $2.keyin;
614		}
615		;
616
617enckeyspec	: /* empty */			{
618			$$.keyout = NULL;
619			$$.keyin = NULL;
620		}
621		| ENCKEY keyspec		{
622			$$.keyout = $2.keyout;
623			$$.keyin = $2.keyin;
624		}
625		;
626
627keyspec		: STRING			{
628			unsigned char	*hex;
629			unsigned char	*p = strchr($1, ':');
630
631			if (p != NULL ) {
632				*p++ = 0;
633
634				if (!strncmp(p, "0x", 2))
635					p += 2;
636				$$.keyin = parsekey(p, strlen(p));
637			}
638
639			hex = $1;
640			if (!strncmp(hex, "0x", 2))
641				hex += 2;
642			$$.keyout = parsekey(hex, strlen(hex));
643
644			free($1);
645		}
646		| FILENAME STRING		{
647			unsigned char	*p = strchr($2, ':');
648
649			if (p != NULL) {
650				*p++ = 0;
651				$$.keyin = parsekeyfile(p);
652			}
653			$$.keyout = parsekeyfile($2);
654			free($2);
655		}
656		;
657
658ikemode		: /* empty */			{ $$ = IKE_ACTIVE; }
659		| PASSIVE			{ $$ = IKE_PASSIVE; }
660		| DYNAMIC			{ $$ = IKE_DYNAMIC; }
661		| ACTIVE			{ $$ = IKE_ACTIVE; }
662		;
663
664ikeauth		: /* empty */			{
665			$$.type = IKE_AUTH_RSA;
666			$$.string = NULL;
667		}
668		| RSA				{
669			$$.type = IKE_AUTH_RSA;
670			$$.string = NULL;
671		}
672		| PSK STRING			{
673			$$.type = IKE_AUTH_PSK;
674			if (($$.string = strdup($2)) == NULL)
675				err(1, "ikeauth: strdup");
676		}
677		;
678
679string		: string STRING
680		{
681			if (asprintf(&$$, "%s %s", $1, $2) == -1)
682				err(1, "string: asprintf");
683			free($1);
684			free($2);
685		}
686		| STRING
687		;
688
689varset		: STRING '=' string
690		{
691			if (ipsec->opts & IPSECCTL_OPT_VERBOSE)
692				printf("%s = \"%s\"\n", $1, $3);
693			if (symset($1, $3, 0) == -1)
694				err(1, "cannot store variable");
695			free($1);
696			free($3);
697		}
698		;
699
700%%
701
702struct keywords {
703	const char	*k_name;
704	int		 k_val;
705};
706
707int
708yyerror(const char *fmt, ...)
709{
710	va_list		 ap;
711	extern const char *infile;
712
713	errors = 1;
714	va_start(ap, fmt);
715	fprintf(stderr, "%s: %d: ", infile, yyval.lineno);
716	vfprintf(stderr, fmt, ap);
717	fprintf(stderr, "\n");
718	va_end(ap);
719	return (0);
720}
721
722int
723kw_cmp(const void *k, const void *e)
724{
725	return (strcmp(k, ((const struct keywords *)e)->k_name));
726}
727
728int
729lookup(char *s)
730{
731	/* this has to be sorted always */
732	static const struct keywords keywords[] = {
733		{ "acquire",		ACQUIRE },
734		{ "active",		ACTIVE },
735		{ "ah",			AH },
736		{ "any",		ANY },
737		{ "auth",		AUTHXF },
738		{ "authkey",		AUTHKEY },
739		{ "bypass",		BYPASS },
740		{ "comp",		COMPXF },
741		{ "deny",		DENY },
742		{ "dontacq",		DONTACQ },
743		{ "dstid",		DSTID },
744		{ "dynamic",		DYNAMIC },
745		{ "enc",		ENCXF },
746		{ "enckey",		ENCKEY },
747		{ "esp",		ESP },
748		{ "file",		FILENAME },
749		{ "flow",		FLOW },
750		{ "from",		FROM },
751		{ "group",		GROUP },
752		{ "ike",		IKE },
753		{ "in",			IN },
754		{ "ipcomp",		IPCOMP },
755		{ "ipip",		IPIP },
756		{ "local",		LOCAL },
757		{ "main",		MAIN },
758		{ "out",		OUT },
759		{ "passive",		PASSIVE },
760		{ "peer",		PEER },
761		{ "proto",		PROTO },
762		{ "psk",		PSK },
763		{ "quick",		QUICK },
764		{ "require",		REQUIRE },
765		{ "rsa",		RSA },
766		{ "spi",		SPI },
767		{ "srcid",		SRCID },
768		{ "tcpmd5",		TCPMD5 },
769		{ "to",			TO },
770		{ "transport",		TRANSPORT },
771		{ "tunnel",		TUNNEL },
772		{ "type",		TYPE },
773		{ "use",		USE }
774	};
775	const struct keywords	*p;
776
777	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
778	    sizeof(keywords[0]), kw_cmp);
779
780	if (p) {
781		if (debug > 1)
782			fprintf(stderr, "%s: %d\n", s, p->k_val);
783		return (p->k_val);
784	} else {
785		if (debug > 1)
786			fprintf(stderr, "string: %s\n", s);
787		return (STRING);
788	}
789}
790
791#define MAXPUSHBACK	128
792
793char	*parsebuf;
794int	 parseindex;
795char	 pushback_buffer[MAXPUSHBACK];
796int	 pushback_index = 0;
797
798int
799lgetc(FILE *f)
800{
801	int	c, next;
802
803	if (parsebuf) {
804		/* Read character from the parsebuffer instead of input. */
805		if (parseindex >= 0) {
806			c = parsebuf[parseindex++];
807			if (c != '\0')
808				return (c);
809			parsebuf = NULL;
810		} else
811			parseindex++;
812	}
813
814	if (pushback_index)
815		return (pushback_buffer[--pushback_index]);
816
817	while ((c = getc(f)) == '\\') {
818		next = getc(f);
819		if (next != '\n') {
820			c = next;
821			break;
822		}
823		yylval.lineno = lineno;
824		lineno++;
825	}
826	if (c == '\t' || c == ' ') {
827		/* Compress blanks to a single space. */
828		do {
829			c = getc(f);
830		} while (c == '\t' || c == ' ');
831		ungetc(c, f);
832		c = ' ';
833	}
834
835	return (c);
836}
837
838int
839lungetc(int c)
840{
841	if (c == EOF)
842		return (EOF);
843	if (parsebuf) {
844		parseindex--;
845		if (parseindex >= 0)
846			return (c);
847	}
848	if (pushback_index < MAXPUSHBACK-1)
849		return (pushback_buffer[pushback_index++] = c);
850	else
851		return (EOF);
852}
853
854int
855findeol(void)
856{
857	int	c;
858
859	parsebuf = NULL;
860	pushback_index = 0;
861
862	/* skip to either EOF or the first real EOL */
863	while (1) {
864		c = lgetc(fin);
865		if (c == '\n') {
866			lineno++;
867			break;
868		}
869		if (c == EOF)
870			break;
871	}
872	return (ERROR);
873}
874
875int
876yylex(void)
877{
878	char	 buf[8096];
879	char	*p, *val;
880	int	 endc, c;
881	int	 token;
882
883top:
884	p = buf;
885	while ((c = lgetc(fin)) == ' ')
886		; /* nothing */
887
888	yylval.lineno = lineno;
889	if (c == '#')
890		while ((c = lgetc(fin)) != '\n' && c != EOF)
891			; /* nothing */
892	if (c == '$' && parsebuf == NULL) {
893		while (1) {
894			if ((c = lgetc(fin)) == EOF)
895				return (0);
896
897			if (p + 1 >= buf + sizeof(buf) - 1) {
898				yyerror("string too long");
899				return (findeol());
900			}
901			if (isalnum(c) || c == '_') {
902				*p++ = (char)c;
903				continue;
904			}
905			*p = '\0';
906			lungetc(c);
907			break;
908		}
909		val = symget(buf);
910		if (val == NULL) {
911			yyerror("macro \"%s\" not defined", buf);
912			return (findeol());
913		}
914		parsebuf = val;
915		parseindex = 0;
916		goto top;
917	}
918
919	switch (c) {
920	case '\'':
921	case '"':
922		endc = c;
923		while (1) {
924			if ((c = lgetc(fin)) == EOF)
925				return (0);
926			if (c == endc) {
927				*p = '\0';
928				break;
929			}
930			if (c == '\n') {
931				lineno++;
932				continue;
933			}
934			if (p + 1 >= buf + sizeof(buf) - 1) {
935				yyerror("string too long");
936				return (findeol());
937			}
938			*p++ = (char)c;
939		}
940		yylval.v.string = strdup(buf);
941		if (yylval.v.string == NULL)
942			err(1, "yylex: strdup");
943		return (STRING);
944	}
945
946#define allowed_in_string(x) \
947	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
948	x != '{' && x != '}' && x != '<' && x != '>' && \
949	x != '!' && x != '=' && x != '/' && x != '#' && \
950	x != ','))
951
952	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
953		do {
954			*p++ = c;
955			if ((unsigned)(p-buf) >= sizeof(buf)) {
956				yyerror("string too long");
957				return (findeol());
958			}
959		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
960		lungetc(c);
961		*p = '\0';
962		if ((token = lookup(buf)) == STRING)
963			if ((yylval.v.string = strdup(buf)) == NULL)
964				err(1, "yylex: strdup");
965		return (token);
966	}
967	if (c == '\n') {
968		yylval.lineno = lineno;
969		lineno++;
970	}
971	if (c == EOF)
972		return (0);
973	return (c);
974}
975
976int
977parse_rules(FILE *input, struct ipsecctl *ipsecx)
978{
979	struct sym	*sym;
980
981	ipsec = ipsecx;
982	fin = input;
983	lineno = 1;
984	errors = 0;
985
986	yyparse();
987
988	/* Free macros and check which have not been used. */
989	while ((sym = TAILQ_FIRST(&symhead))) {
990		if ((ipsec->opts & IPSECCTL_OPT_VERBOSE2) && !sym->used)
991			fprintf(stderr, "warning: macro '%s' not "
992			    "used\n", sym->nam);
993		TAILQ_REMOVE(&symhead, sym, entries);
994		free(sym->nam);
995		free(sym->val);
996		free(sym);
997	}
998
999	return (errors ? -1 : 0);
1000}
1001
1002int
1003symset(const char *nam, const char *val, int persist)
1004{
1005	struct sym	*sym;
1006
1007	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
1008	    sym = TAILQ_NEXT(sym, entries))
1009		;	/* nothing */
1010
1011	if (sym != NULL) {
1012		if (sym->persist == 1)
1013			return (0);
1014		else {
1015			TAILQ_REMOVE(&symhead, sym, entries);
1016			free(sym->nam);
1017			free(sym->val);
1018			free(sym);
1019		}
1020	}
1021	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1022		return (-1);
1023
1024	sym->nam = strdup(nam);
1025	if (sym->nam == NULL) {
1026		free(sym);
1027		return (-1);
1028	}
1029	sym->val = strdup(val);
1030	if (sym->val == NULL) {
1031		free(sym->nam);
1032		free(sym);
1033		return (-1);
1034	}
1035	sym->used = 0;
1036	sym->persist = persist;
1037	TAILQ_INSERT_TAIL(&symhead, sym, entries);
1038	return (0);
1039}
1040
1041int
1042cmdline_symset(char *s)
1043{
1044	char	*sym, *val;
1045	int	ret;
1046	size_t	len;
1047
1048	if ((val = strrchr(s, '=')) == NULL)
1049		return (-1);
1050
1051	len = strlen(s) - strlen(val) + 1;
1052	if ((sym = malloc(len)) == NULL)
1053		err(1, "cmdline_symset: malloc");
1054
1055	strlcpy(sym, s, len);
1056
1057	ret = symset(sym, val + 1, 1);
1058	free(sym);
1059
1060	return (ret);
1061}
1062
1063char *
1064symget(const char *nam)
1065{
1066	struct sym	*sym;
1067
1068	TAILQ_FOREACH(sym, &symhead, entries)
1069		if (strcmp(nam, sym->nam) == 0) {
1070			sym->used = 1;
1071			return (sym->val);
1072		}
1073	return (NULL);
1074}
1075
1076int
1077atoul(char *s, u_long *ulvalp)
1078{
1079	u_long	 ulval;
1080	char	*ep;
1081
1082	errno = 0;
1083	ulval = strtoul(s, &ep, 0);
1084	if (s[0] == '\0' || *ep != '\0')
1085		return (-1);
1086	if (errno == ERANGE && ulval == ULONG_MAX)
1087		return (-1);
1088	*ulvalp = ulval;
1089	return (0);
1090}
1091
1092int
1093atospi(char *s, u_int32_t *spivalp)
1094{
1095	unsigned long	ulval;
1096
1097	if (atoul(s, &ulval) == -1)
1098		return (-1);
1099	if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) {
1100		yyerror("illegal SPI value");
1101		return (-1);
1102	}
1103	*spivalp = ulval;
1104	return (0);
1105}
1106
1107u_int8_t
1108x2i(unsigned char *s)
1109{
1110	char	ss[3];
1111
1112	ss[0] = s[0];
1113	ss[1] = s[1];
1114	ss[2] = 0;
1115
1116	if (!isxdigit(s[0]) || !isxdigit(s[1])) {
1117		yyerror("keys need to be specified in hex digits");
1118		return (-1);
1119	}
1120	return ((u_int8_t)strtoul(ss, NULL, 16));
1121}
1122
1123struct ipsec_key *
1124parsekey(unsigned char *hexkey, size_t len)
1125{
1126	struct ipsec_key *key;
1127	int		  i;
1128
1129	key = calloc(1, sizeof(struct ipsec_key));
1130	if (key == NULL)
1131		err(1, "parsekey: calloc");
1132
1133	key->len = len / 2;
1134	key->data = calloc(key->len, sizeof(u_int8_t));
1135	if (key->data == NULL)
1136		err(1, "parsekey: calloc");
1137
1138	for (i = 0; i < (int)key->len; i++)
1139		key->data[i] = x2i(hexkey + 2 * i);
1140
1141	return (key);
1142}
1143
1144struct ipsec_key *
1145parsekeyfile(char *filename)
1146{
1147	struct stat	 sb;
1148	int		 fd;
1149	unsigned char	*hex;
1150
1151	if ((fd = open(filename, O_RDONLY)) < 0)
1152		err(1, "parsekeyfile: open");
1153	if (fstat(fd, &sb) < 0)
1154		err(1, "parsekeyfile: stat %s", filename);
1155	if ((sb.st_size > KEYSIZE_LIMIT) || (sb.st_size == 0))
1156		errx(1, "parsekeyfile: key too %s", sb.st_size ? "large" :
1157		    "small");
1158	if ((hex = calloc(sb.st_size, sizeof(unsigned char))) == NULL)
1159		err(1, "parsekeyfile: calloc");
1160	if (read(fd, hex, sb.st_size) < sb.st_size)
1161		err(1, "parsekeyfile: read");
1162	close(fd);
1163	return (parsekey(hex, sb.st_size));
1164}
1165
1166struct ipsec_addr_wrap *
1167host(const char *s)
1168{
1169	struct ipsec_addr_wrap	*ipa = NULL;
1170	int			 mask, v4mask, cont = 1;
1171	char			*p, *q, *ps;
1172
1173	if ((p = strrchr(s, '/')) != NULL) {
1174		errno = 0;
1175		mask = strtol(p + 1, &q, 0);
1176		if (errno == ERANGE || !q || *q || mask > 32 || q == (p + 1))
1177			errx(1, "host: invalid netmask '%s'", p);
1178		if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
1179			err(1, "host: calloc");
1180		strlcpy(ps, s, strlen(s) - strlen(p) + 1);
1181		v4mask = mask;
1182	} else {
1183		if ((ps = strdup(s)) == NULL)
1184			err(1, "host: strdup");
1185		v4mask = 32;
1186		mask = -1;
1187	}
1188
1189	/* Does interface with this name exist? */
1190	if (cont && (ipa = host_if(ps, mask)) != NULL)
1191		cont = 0;
1192
1193	/* IPv4 address? */
1194	if (cont && (ipa = host_v4(s, v4mask)) != NULL)
1195		cont = 0;
1196
1197#if notyet
1198	/* IPv6 address? */
1199	if (cont && (ipa = host_v6(s, v6mask)) != NULL)
1200		cont = 0;
1201#endif
1202
1203	/* dns lookup */
1204	if (cont && (ipa = host_dns(s, v4mask, 0)) != NULL)
1205		cont = 0;
1206	free(ps);
1207
1208	if (ipa == NULL || cont == 1) {
1209		fprintf(stderr, "no IP address found for %s\n", s);
1210		return (NULL);
1211	}
1212	return (ipa);
1213}
1214
1215struct ipsec_addr_wrap *
1216host_v4(const char *s, int mask)
1217{
1218	struct ipsec_addr_wrap	*ipa = NULL;
1219	struct in_addr		 ina;
1220	int			 bits = 32;
1221
1222	bzero(&ina, sizeof(struct in_addr));
1223	if (strrchr(s, '/') != NULL) {
1224		if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
1225			return (NULL);
1226	} else {
1227		if (inet_pton(AF_INET, s, &ina) != 1)
1228			return (NULL);
1229	}
1230
1231	ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1232	if (ipa == NULL)
1233		err(1, "host_v4: calloc");
1234
1235	ipa->address.v4 = ina;
1236	ipa->name = strdup(s);
1237	if (ipa->name == NULL)
1238		err(1, "host_v4: strdup");
1239	ipa->af = AF_INET;
1240	ipa->next = NULL;
1241	ipa->tail = ipa;
1242
1243	set_ipmask(ipa, bits);
1244	if (bits != (ipa->af == AF_INET ? 32 : 128))
1245		ipa->netaddress = 1;
1246
1247	return (ipa);
1248}
1249
1250struct ipsec_addr_wrap *
1251host_dns(const char *s, int v4mask, int v6mask)
1252{
1253	struct ipsec_addr_wrap	*ipa = NULL;
1254	struct addrinfo		 hints, *res0, *res;
1255	int			 error;
1256	int			 bits = 32;
1257
1258	bzero(&hints, sizeof(struct addrinfo));
1259	hints.ai_family = PF_UNSPEC;
1260	hints.ai_socktype = SOCK_STREAM;
1261	error = getaddrinfo(s, NULL, &hints, &res0);
1262	if (error)
1263		return (NULL);
1264
1265	for (res = res0; res; res = res->ai_next) {
1266		if (res->ai_family != AF_INET)
1267			continue;
1268		ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1269		if (ipa == NULL)
1270			err(1, "host_dns: calloc");
1271		memcpy(&ipa->address.v4,
1272		    &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr,
1273		    sizeof(struct in_addr));
1274		ipa->name = strdup(inet_ntoa(ipa->address.v4));
1275		if (ipa->name == NULL)
1276			err(1, "host_dns: strdup");
1277		ipa->af = AF_INET;
1278		ipa->next = NULL;
1279		ipa->tail = ipa;
1280
1281		set_ipmask(ipa, bits);
1282		if (bits != (ipa->af == AF_INET ? 32 : 128))
1283			ipa->netaddress = 1;
1284		break;
1285	}
1286	freeaddrinfo(res0);
1287
1288	return (ipa);
1289}
1290
1291struct ipsec_addr_wrap *
1292host_if(const char *s, int mask)
1293{
1294	struct ipsec_addr_wrap *ipa = NULL;
1295
1296	if (ifa_exists(s))
1297		ipa = ifa_lookup(s);
1298
1299	return (ipa);
1300}
1301
1302/* interface lookup routintes */
1303
1304struct ipsec_addr_wrap	*iftab;
1305
1306void
1307ifa_load(void)
1308{
1309	struct ifaddrs		*ifap, *ifa;
1310	struct ipsec_addr_wrap	*n = NULL, *h = NULL;
1311
1312	if (getifaddrs(&ifap) < 0)
1313		err(1, "ifa_load: getiffaddrs");
1314
1315	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1316		if (!(ifa->ifa_addr->sa_family == AF_INET ||
1317		    ifa->ifa_addr->sa_family == AF_INET6 ||
1318		    ifa->ifa_addr->sa_family == AF_LINK))
1319			continue;
1320		n = calloc(1, sizeof(struct ipsec_addr_wrap));
1321		if (n == NULL)
1322			err(1, "ifa_load: calloc");
1323		n->af = ifa->ifa_addr->sa_family;
1324		if ((n->name = strdup(ifa->ifa_name)) == NULL)
1325			err(1, "ifa_load: strdup");
1326		if (n->af == AF_INET) {
1327			n->af = AF_INET;
1328			memcpy(&n->address.v4, &((struct sockaddr_in *)
1329			    ifa->ifa_addr)->sin_addr.s_addr,
1330			    sizeof(struct in_addr));
1331			memcpy(&n->mask.v4, &((struct sockaddr_in *)
1332			    ifa->ifa_netmask)->sin_addr.s_addr,
1333			    sizeof(struct in_addr));
1334		} else if (n->af == AF_INET6) {
1335			n->af = AF_INET6;
1336			memcpy(&n->address.v6, &((struct sockaddr_in6 *)
1337			    ifa->ifa_addr)->sin6_addr.s6_addr,
1338			    sizeof(struct in6_addr));
1339			memcpy(&n->mask.v6, &((struct sockaddr_in6 *)
1340			    ifa->ifa_netmask)->sin6_addr.s6_addr,
1341			    sizeof(struct in6_addr));
1342		}
1343		if ((n->name = strdup(ifa->ifa_name)) == NULL)
1344			err(1, "ifa_load: strdup");
1345		n->next = NULL;
1346		n->tail = n;
1347		if (h == NULL)
1348			h = n;
1349		else {
1350			h->tail->next = n;
1351			h->tail = n;
1352		}
1353	}
1354
1355	iftab = h;
1356	freeifaddrs(ifap);
1357}
1358
1359int
1360ifa_exists(const char *ifa_name)
1361{
1362	struct ipsec_addr_wrap	*n;
1363	struct ifgroupreq	 ifgr;
1364	int			 s;
1365
1366	if (iftab == NULL)
1367		ifa_load();
1368
1369	/* check wether this is a group */
1370	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1371		err(1, "ifa_exists: socket");
1372	bzero(&ifgr, sizeof(ifgr));
1373	strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
1374	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) {
1375		close(s);
1376		return (1);
1377	}
1378	close(s);
1379
1380	for (n = iftab; n; n = n->next) {
1381		if (n->af == AF_LINK && !strncmp(n->name, ifa_name,
1382		    IFNAMSIZ))
1383			return (1);
1384	}
1385
1386	return (0);
1387}
1388
1389struct ipsec_addr_wrap *
1390ifa_grouplookup(const char *ifa_name)
1391{
1392	struct ifg_req		*ifg;
1393	struct ifgroupreq	 ifgr;
1394	int			 s;
1395	size_t			 len;
1396	struct ipsec_addr_wrap	*ipa = NULL;
1397
1398	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1399		err(1, "socket");
1400	bzero(&ifgr, sizeof(ifgr));
1401	strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
1402	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
1403		close(s);
1404		return (NULL);
1405	}
1406
1407	len = ifgr.ifgr_len;
1408	if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
1409		err(1, "calloc");
1410	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
1411		err(1, "ioctl");
1412
1413	for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
1414	    ifg++) {
1415		len -= sizeof(struct ifg_req);
1416		if ((ipa = ifa_lookup(ifg->ifgrq_member)) != NULL)
1417			break;
1418	}
1419	free(ifgr.ifgr_groups);
1420	close(s);
1421
1422	return (ipa);
1423}
1424
1425struct ipsec_addr_wrap *
1426ifa_lookup(const char *ifa_name)
1427{
1428	struct ipsec_addr_wrap	*ipa = NULL, *p = NULL;
1429
1430	if (iftab == NULL)
1431		ifa_load();
1432
1433	if ((ipa = ifa_grouplookup(ifa_name)) != NULL)
1434		return (ipa);
1435
1436	for (p = iftab; p; p = p->next) {
1437		if (p->af != AF_INET)
1438			continue;
1439		if (strncmp(p->name, ifa_name, IFNAMSIZ))
1440			continue;
1441		ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1442		if (ipa == NULL)
1443			err(1, "ifa_lookup: calloc");
1444		memcpy(ipa, p, sizeof(struct ipsec_addr_wrap));
1445		if ((ipa->name = strdup(p->name)) == NULL)
1446			err(1, "ifa_lookup: strdup");
1447		set_ipmask(ipa, 32);
1448		break;
1449	}
1450
1451	return (ipa);
1452}
1453
1454void
1455set_ipmask(struct ipsec_addr_wrap *address, u_int8_t b)
1456{
1457	struct ipsec_addr	*ipa;
1458	int			 i, j = 0;
1459
1460	ipa = &address->mask;
1461	bzero(ipa, sizeof(struct ipsec_addr));
1462
1463	while (b >= 32) {
1464		ipa->addr32[j++] = 0xffffffff;
1465		b -= 32;
1466	}
1467	for (i = 31; i > 31 - b; --i)
1468		ipa->addr32[j] |= (1 << i);
1469	if (b)
1470		ipa->addr32[j] = htonl(ipa->addr32[j]);
1471}
1472
1473struct ipsec_addr_wrap *
1474copyhost(const struct ipsec_addr_wrap *src)
1475{
1476	struct ipsec_addr_wrap *dst;
1477
1478	dst = calloc(1, sizeof(struct ipsec_addr_wrap));
1479	if (dst == NULL)
1480		err(1, "copyhost: calloc");
1481
1482	memcpy(dst, src, sizeof(struct ipsec_addr_wrap));
1483
1484	if ((dst->name = strdup(src->name)) == NULL)
1485		err(1, "copyhost: strdup");
1486
1487	return dst;
1488}
1489
1490const struct ipsec_xf *
1491parse_xf(const char *name, const struct ipsec_xf xfs[])
1492{
1493	int		i;
1494
1495	for (i = 0; xfs[i].name != NULL; i++) {
1496		if (strncmp(name, xfs[i].name, strlen(name)))
1497			continue;
1498		return &xfs[i];
1499	}
1500	return (NULL);
1501}
1502
1503struct ipsec_transforms *
1504copytransforms(const struct ipsec_transforms *xfs)
1505{
1506	struct ipsec_transforms *newxfs;
1507
1508	if (xfs == NULL)
1509		return (NULL);
1510
1511	newxfs = calloc(1, sizeof(struct ipsec_transforms));
1512	if (newxfs == NULL)
1513		err(1, "copytransforms: calloc");
1514
1515	memcpy(newxfs, xfs, sizeof(struct ipsec_transforms));
1516	return (newxfs);
1517}
1518
1519int
1520validate_sa(u_int32_t spi, u_int8_t satype, struct ipsec_transforms *xfs,
1521    struct ipsec_key *authkey, struct ipsec_key *enckey, u_int8_t tmode)
1522{
1523	/* Sanity checks */
1524	if (spi == 0) {
1525		yyerror("no SPI specified");
1526		return (0);
1527	}
1528	if (satype == IPSEC_AH) {
1529		if (!xfs) {
1530			yyerror("no transforms specified");
1531			return (0);
1532		}
1533		if (!xfs->authxf)
1534			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1535		if (xfs->encxf) {
1536			yyerror("ah does not provide encryption");
1537			return (0);
1538		}
1539		if (xfs->compxf) {
1540			yyerror("ah does not provide compression");
1541			return (0);
1542		}
1543	}
1544	if (satype == IPSEC_ESP) {
1545		if (!xfs) {
1546			yyerror("no transforms specified");
1547			return (0);
1548		}
1549		if (xfs->compxf) {
1550			yyerror("esp does not provide compression");
1551			return (0);
1552		}
1553		if (!xfs->authxf)
1554			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1555		if (!xfs->encxf)
1556			xfs->encxf = &encxfs[ENCXF_AESCTR];
1557	}
1558	if (satype == IPSEC_IPCOMP) {
1559		if (!xfs) {
1560			yyerror("no transform specified");
1561			return (0);
1562		}
1563		if (xfs->authxf || xfs->encxf) {
1564			yyerror("no encryption or authentication with ipcomp");
1565			return (0);
1566		}
1567		if (!xfs->compxf)
1568			xfs->compxf = &compxfs[COMPXF_DEFLATE];
1569	}
1570	if (satype == IPSEC_IPIP) {
1571		if (!xfs) {
1572			yyerror("no transform specified");
1573			return (0);
1574		}
1575		if (xfs->authxf || xfs->encxf || xfs->compxf) {
1576			yyerror("no encryption, authentication or compression"
1577			    " with ipip");
1578			return (0);
1579		}
1580	}
1581	if (satype == IPSEC_TCPMD5 && authkey == NULL && tmode !=
1582	    IPSEC_TRANSPORT) {
1583		yyerror("authentication key needed for tcpmd5");
1584		return (0);
1585	}
1586	if (xfs && xfs->authxf) {
1587		if (!authkey) {
1588			yyerror("no authentication key specified");
1589			return (0);
1590		}
1591		if (authkey->len != xfs->authxf->keymin) {
1592			yyerror("wrong authentication key length, needs to be "
1593			    "%d bits", xfs->authxf->keymin * 8);
1594			return (0);
1595		}
1596	}
1597	if (xfs && xfs->encxf) {
1598		if (!enckey && xfs->encxf != &encxfs[ENCXF_NULL]) {
1599			yyerror("no encryption key specified");
1600			return (0);
1601		}
1602		if (enckey) {
1603			if (enckey->len < xfs->encxf->keymin) {
1604				yyerror("encryption key too short, "
1605				    "minimum %d bits", xfs->encxf->keymin * 8);
1606				return (0);
1607			}
1608			if (xfs->encxf->keymax < enckey->len) {
1609				yyerror("encryption key too long, "
1610				    "maximum %d bits", xfs->encxf->keymax * 8);
1611				return (0);
1612			}
1613		}
1614	}
1615
1616	return 1;
1617}
1618
1619struct ipsec_rule *
1620create_sa(u_int8_t satype, u_int8_t tmode, struct ipsec_addr_wrap *src, struct
1621    ipsec_addr_wrap *dst, u_int32_t spi, struct ipsec_transforms *xfs,
1622    struct ipsec_key *authkey, struct ipsec_key *enckey)
1623{
1624	struct ipsec_rule *r;
1625
1626	if (validate_sa(spi, satype, xfs, authkey, enckey, tmode) == 0)
1627		return (NULL);
1628
1629	r = calloc(1, sizeof(struct ipsec_rule));
1630	if (r == NULL)
1631		err(1, "create_sa: calloc");
1632
1633	r->type |= RULE_SA;
1634	r->satype = satype;
1635	r->tmode = tmode;
1636	r->src = src;
1637	r->dst = dst;
1638	r->spi = spi;
1639	r->xfs = xfs;
1640	r->authkey = authkey;
1641	r->enckey = enckey;
1642
1643	return r;
1644}
1645
1646struct ipsec_rule *
1647reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey,
1648    struct ipsec_key *enckey)
1649{
1650	struct ipsec_rule *reverse;
1651
1652	if (validate_sa(spi, rule->satype, rule->xfs, authkey, enckey,
1653	    rule->tmode) == 0)
1654		return (NULL);
1655
1656	reverse = calloc(1, sizeof(struct ipsec_rule));
1657	if (reverse == NULL)
1658		err(1, "reverse_sa: calloc");
1659
1660	reverse->type |= RULE_SA;
1661	reverse->satype = rule->satype;
1662	reverse->tmode = rule->tmode;
1663	reverse->src = copyhost(rule->dst);
1664	reverse->dst = copyhost(rule->src);
1665	reverse->spi = spi;
1666	reverse->xfs = copytransforms(rule->xfs);
1667	reverse->authkey = authkey;
1668	reverse->enckey = enckey;
1669
1670	return (reverse);
1671}
1672
1673struct ipsec_rule *
1674create_flow(u_int8_t dir, u_int8_t proto, struct ipsec_addr_wrap *src,
1675    struct ipsec_addr_wrap *dst, struct ipsec_addr_wrap *local,
1676    struct ipsec_addr_wrap *peer, u_int8_t satype, char *srcid, char *dstid,
1677    u_int8_t type)
1678{
1679	struct ipsec_rule *r;
1680
1681	r = calloc(1, sizeof(struct ipsec_rule));
1682	if (r == NULL)
1683		err(1, "create_flow: calloc");
1684
1685	r->type |= RULE_FLOW;
1686
1687	if (dir == IPSEC_INOUT)
1688		r->direction = IPSEC_OUT;
1689	else
1690		r->direction = dir;
1691
1692	r->satype = satype;
1693	r->proto = proto;
1694	r->src = src;
1695	r->dst = dst;
1696
1697	if (type == TYPE_DENY || type == TYPE_BYPASS) {
1698		r->flowtype = type;
1699		return (r);
1700	}
1701
1702	r->flowtype = type;
1703	r->local = local;
1704	if (peer == NULL) {
1705		/* Set peer to remote host.  Must be a host address. */
1706		if (r->direction == IPSEC_IN) {
1707			if (r->src->netaddress) {
1708				yyerror("no peer specified");
1709				goto errout;
1710			}
1711			r->peer = copyhost(r->src);
1712		} else {
1713			if (r->dst->netaddress) {
1714				yyerror("no peer specified");
1715				goto errout;
1716			}
1717			r->peer = copyhost(r->dst);
1718		}
1719	} else
1720		r->peer = peer;
1721
1722	r->auth = calloc(1, sizeof(struct ipsec_auth));
1723	if (r->auth == NULL)
1724		err(1, "create_flow: calloc");
1725	r->auth->srcid = srcid;
1726	r->auth->dstid = dstid;
1727	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
1728
1729	return r;
1730
1731errout:
1732	free(r);
1733	if (srcid)
1734		free(srcid);
1735	if (dstid)
1736		free(dstid);
1737	free(src);
1738	free(dst);
1739
1740	return NULL;
1741}
1742
1743int
1744expand_rule(struct ipsec_rule *rule, u_int8_t direction, u_int32_t spi,
1745    struct ipsec_key *authkey, struct ipsec_key *enckey)
1746{
1747	struct ipsec_rule	*r;
1748	struct ipsec_addr_wrap	*src, *dst, *tsrc, *tdst;
1749
1750	src = rule->src;
1751	dst = rule->dst;
1752
1753	for (tsrc = src; tsrc; tsrc = tsrc->next) {
1754		rule->src = tsrc;
1755
1756		for (tdst = dst; tdst; tdst = tdst->next) {
1757			rule->dst = tdst;
1758
1759			rule->nr = ipsec->rule_nr++;
1760			if (ipsecctl_add_rule(ipsec, rule))
1761				return (1);
1762
1763			if (direction == IPSEC_INOUT) {
1764				/* Create and add reverse flow rule. */
1765				r = reverse_rule(rule);
1766				if (r == NULL)
1767					return (1);
1768
1769				r->nr = ipsec->rule_nr++;
1770				if (ipsecctl_add_rule(ipsec, r))
1771					return (1);
1772			} else if (spi != 0 || authkey || enckey) {
1773				/* Create and add reverse sa rule. */
1774				r = reverse_sa(rule, spi, authkey, enckey);
1775				if (r == NULL)
1776					return (1);
1777
1778				r->nr = ipsec->rule_nr++;
1779				if (ipsecctl_add_rule(ipsec, r))
1780					return (1);
1781			}
1782		}
1783	}
1784	return (0);
1785}
1786
1787struct ipsec_rule *
1788reverse_rule(struct ipsec_rule *rule)
1789{
1790	struct ipsec_rule *reverse;
1791
1792	reverse = calloc(1, sizeof(struct ipsec_rule));
1793	if (reverse == NULL)
1794		err(1, "reverse_rule: calloc");
1795
1796	reverse->type |= RULE_FLOW;
1797
1798	/* Reverse direction */
1799	if (rule->direction == (u_int8_t)IPSEC_OUT)
1800		reverse->direction = (u_int8_t)IPSEC_IN;
1801	else
1802		reverse->direction = (u_int8_t)IPSEC_OUT;
1803
1804	reverse->flowtype = rule->flowtype;
1805	reverse->src = copyhost(rule->dst);
1806	reverse->dst = copyhost(rule->src);
1807	if (rule->local)
1808		reverse->local = copyhost(rule->local);
1809	if (rule->peer)
1810		reverse->peer = copyhost(rule->peer);
1811	reverse->satype = rule->satype;
1812	reverse->proto = rule->proto;
1813
1814	if (rule->auth) {
1815		reverse->auth = calloc(1, sizeof(struct ipsec_auth));
1816		if (reverse->auth == NULL)
1817			err(1, "reverse_rule: calloc");
1818		if (rule->auth->dstid && (reverse->auth->dstid =
1819		    strdup(rule->auth->dstid)) == NULL)
1820			err(1, "reverse_rule: strdup");
1821		if (rule->auth->srcid && (reverse->auth->srcid =
1822		    strdup(rule->auth->srcid)) == NULL)
1823			err(1, "reverse_rule: strdup");
1824		reverse->auth->idtype = rule->auth->idtype;
1825		reverse->auth->type = rule->auth->type;
1826	}
1827
1828	return reverse;
1829}
1830
1831struct ipsec_rule *
1832create_ike(u_int8_t proto, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap
1833    *dst, struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer,
1834    struct ipsec_transforms *mmxfs, struct ipsec_transforms *qmxfs,
1835    u_int8_t satype, u_int8_t mode, char *srcid, char *dstid,
1836    struct ike_auth *authtype)
1837{
1838	struct ipsec_rule *r;
1839
1840	r = calloc(1, sizeof(struct ipsec_rule));
1841	if (r == NULL)
1842		err(1, "create_ike: calloc");
1843
1844	r->type = RULE_IKE;
1845
1846	r->proto = proto;
1847	r->src = src;
1848	r->dst = dst;
1849
1850	if (peer == NULL) {
1851		/* Set peer to remote host.  Must be a host address. */
1852		if (r->direction == IPSEC_IN) {
1853			if (r->src->netaddress) {
1854				yyerror("no peer specified");
1855				goto errout;
1856			}
1857			r->peer = copyhost(r->src);
1858		} else {
1859			if (r->dst->netaddress) {
1860				yyerror("no peer specified");
1861				goto errout;
1862			}
1863			r->peer = copyhost(r->dst);
1864		}
1865	} else
1866		r->peer = peer;
1867
1868	if (local)
1869		r->local = local;
1870
1871	r->satype = satype;
1872	r->ikemode = mode;
1873	r->mmxfs = mmxfs;
1874	r->qmxfs = qmxfs;
1875	r->auth = calloc(1, sizeof(struct ipsec_auth));
1876	if (r->auth == NULL)
1877		err(1, "create_ike: calloc");
1878	r->auth->srcid = srcid;
1879	r->auth->dstid = dstid;
1880	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
1881	r->ikeauth = calloc(1, sizeof(struct ike_auth));
1882	if (r->ikeauth == NULL)
1883		err(1, "create_ike: calloc");
1884	r->ikeauth->type = authtype->type;
1885	r->ikeauth->string = authtype->string;
1886
1887	return (r);
1888
1889errout:
1890	free(r);
1891	if (srcid)
1892		free(srcid);
1893	if (dstid)
1894		free(dstid);
1895	free(src);
1896	free(dst);
1897	if (authtype->string)
1898		free(authtype->string);
1899
1900	return (NULL);
1901}
1902