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