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