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