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