1/*	$NetBSD: cfparse.y,v 1.18.4.7 2008/07/21 20:45:32 tteras Exp $	*/
2
3/* Id: cfparse.y,v 1.66 2006/08/22 18:17:17 manubsd Exp */
4
5%{
6/*
7 * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 and 2003 WIDE Project.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the project nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include "config.h"
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/queue.h>
40#include <sys/socket.h>
41
42#include <netinet/in.h>
43#include PATH_IPSEC_H
44
45#ifdef ENABLE_HYBRID
46#include <arpa/inet.h>
47#endif
48
49#include <stdlib.h>
50#include <stdio.h>
51#include <string.h>
52#include <errno.h>
53#include <netdb.h>
54#include <pwd.h>
55#include <grp.h>
56
57#include "var.h"
58#include "misc.h"
59#include "vmbuf.h"
60#include "plog.h"
61#include "sockmisc.h"
62#include "str2val.h"
63#include "genlist.h"
64#include "debug.h"
65
66#include "admin.h"
67#include "privsep.h"
68#include "cfparse_proto.h"
69#include "cftoken_proto.h"
70#include "algorithm.h"
71#include "localconf.h"
72#include "policy.h"
73#include "sainfo.h"
74#include "oakley.h"
75#include "pfkey.h"
76#include "remoteconf.h"
77#include "grabmyaddr.h"
78#include "isakmp_var.h"
79#include "handler.h"
80#include "isakmp.h"
81#include "nattraversal.h"
82#include "isakmp_frag.h"
83#ifdef ENABLE_HYBRID
84#include "resolv.h"
85#include "isakmp_unity.h"
86#include "isakmp_xauth.h"
87#include "isakmp_cfg.h"
88#endif
89#include "ipsec_doi.h"
90#include "strnames.h"
91#include "gcmalloc.h"
92#ifdef HAVE_GSSAPI
93#include "gssapi.h"
94#endif
95#include "vendorid.h"
96#include "rsalist.h"
97
98struct proposalspec {
99	time_t lifetime;		/* for isakmp/ipsec */
100	int lifebyte;			/* for isakmp/ipsec */
101	struct secprotospec *spspec;	/* the head is always current spec. */
102	struct proposalspec *next;	/* the tail is the most prefered. */
103	struct proposalspec *prev;
104};
105
106struct secprotospec {
107	int prop_no;
108	int trns_no;
109	int strength;		/* for isakmp/ipsec */
110	int encklen;		/* for isakmp/ipsec */
111	time_t lifetime;	/* for isakmp */
112	int lifebyte;		/* for isakmp */
113	int proto_id;		/* for ipsec (isakmp?) */
114	int ipsec_level;	/* for ipsec */
115	int encmode;		/* for ipsec */
116	int vendorid;		/* for isakmp */
117	char *gssid;
118	struct sockaddr *remote;
119	int algclass[MAXALGCLASS];
120
121	struct secprotospec *next;	/* the tail is the most prefiered. */
122	struct secprotospec *prev;
123	struct proposalspec *back;
124};
125
126static int num2dhgroup[] = {
127	0,
128	OAKLEY_ATTR_GRP_DESC_MODP768,
129	OAKLEY_ATTR_GRP_DESC_MODP1024,
130	OAKLEY_ATTR_GRP_DESC_EC2N155,
131	OAKLEY_ATTR_GRP_DESC_EC2N185,
132	OAKLEY_ATTR_GRP_DESC_MODP1536,
133	0,
134	0,
135	0,
136	0,
137	0,
138	0,
139	0,
140	0,
141	OAKLEY_ATTR_GRP_DESC_MODP2048,
142	OAKLEY_ATTR_GRP_DESC_MODP3072,
143	OAKLEY_ATTR_GRP_DESC_MODP4096,
144	OAKLEY_ATTR_GRP_DESC_MODP6144,
145	OAKLEY_ATTR_GRP_DESC_MODP8192
146};
147
148static struct remoteconf *cur_rmconf;
149static int tmpalgtype[MAXALGCLASS];
150static struct sainfo *cur_sainfo;
151static int cur_algclass;
152static int oldloglevel = LLV_BASE;
153
154static struct proposalspec *newprspec __P((void));
155static void insprspec __P((struct proposalspec *, struct proposalspec **));
156static struct secprotospec *newspspec __P((void));
157static void insspspec __P((struct secprotospec *, struct proposalspec **));
158static void adminsock_conf __P((vchar_t *, vchar_t *, vchar_t *, int));
159
160static int set_isakmp_proposal
161	__P((struct remoteconf *, struct proposalspec *));
162static void clean_tmpalgtype __P((void));
163static int expand_isakmpspec __P((int, int, int *,
164	int, int, time_t, int, int, int, char *, struct remoteconf *));
165static int listen_addr __P((struct sockaddr *addr, int udp_encap));
166
167void freeetypes (struct etypes **etypes);
168
169#if 0
170static int fix_lifebyte __P((u_long));
171#endif
172%}
173
174%union {
175	unsigned long num;
176	vchar_t *val;
177	struct remoteconf *rmconf;
178	struct sockaddr *saddr;
179	struct sainfoalg *alg;
180}
181
182	/* privsep */
183%token PRIVSEP USER GROUP CHROOT
184	/* path */
185%token PATH PATHTYPE
186	/* include */
187%token INCLUDE
188	/* self information */
189%token IDENTIFIER VENDORID
190	/* logging */
191%token LOGGING LOGLEV
192	/* padding */
193%token PADDING PAD_RANDOMIZE PAD_RANDOMIZELEN PAD_MAXLEN PAD_STRICT PAD_EXCLTAIL
194	/* listen */
195%token LISTEN X_ISAKMP X_ISAKMP_NATT X_ADMIN STRICT_ADDRESS ADMINSOCK DISABLED
196	/* ldap config */
197%token LDAPCFG LDAP_HOST LDAP_PORT LDAP_PVER LDAP_BASE LDAP_BIND_DN LDAP_BIND_PW LDAP_SUBTREE
198%token LDAP_ATTR_USER LDAP_ATTR_ADDR LDAP_ATTR_MASK LDAP_ATTR_GROUP LDAP_ATTR_MEMBER
199	/* modecfg */
200%token MODECFG CFG_NET4 CFG_MASK4 CFG_DNS4 CFG_NBNS4 CFG_DEFAULT_DOMAIN
201%token CFG_AUTH_SOURCE CFG_AUTH_GROUPS CFG_SYSTEM CFG_RADIUS CFG_PAM CFG_LDAP CFG_LOCAL CFG_NONE
202%token CFG_GROUP_SOURCE CFG_ACCOUNTING CFG_CONF_SOURCE CFG_MOTD CFG_POOL_SIZE CFG_AUTH_THROTTLE
203%token CFG_SPLIT_NETWORK CFG_SPLIT_LOCAL CFG_SPLIT_INCLUDE CFG_SPLIT_DNS
204%token CFG_PFS_GROUP CFG_SAVE_PASSWD
205
206	/* timer */
207%token RETRY RETRY_COUNTER RETRY_INTERVAL RETRY_PERSEND
208%token RETRY_PHASE1 RETRY_PHASE2 NATT_KA
209	/* algorithm */
210%token ALGORITHM_CLASS ALGORITHMTYPE STRENGTHTYPE
211	/* sainfo */
212%token SAINFO FROM
213	/* remote */
214%token REMOTE ANONYMOUS INHERIT
215%token EXCHANGE_MODE EXCHANGETYPE DOI DOITYPE SITUATION SITUATIONTYPE
216%token CERTIFICATE_TYPE CERTTYPE PEERS_CERTFILE CA_TYPE
217%token VERIFY_CERT SEND_CERT SEND_CR
218%token IDENTIFIERTYPE IDENTIFIERQUAL MY_IDENTIFIER
219%token PEERS_IDENTIFIER VERIFY_IDENTIFIER
220%token DNSSEC CERT_X509 CERT_PLAINRSA
221%token NONCE_SIZE DH_GROUP KEEPALIVE PASSIVE INITIAL_CONTACT
222%token NAT_TRAVERSAL REMOTE_FORCE_LEVEL
223%token PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL
224%token GENERATE_POLICY GENERATE_LEVEL SUPPORT_PROXY
225%token PROPOSAL
226%token EXEC_PATH EXEC_COMMAND EXEC_SUCCESS EXEC_FAILURE
227%token GSS_ID GSS_ID_ENC GSS_ID_ENCTYPE
228%token COMPLEX_BUNDLE
229%token DPD DPD_DELAY DPD_RETRY DPD_MAXFAIL
230%token PH1ID
231%token XAUTH_LOGIN WEAK_PHASE1_CHECK
232
233%token PREFIX PORT PORTANY UL_PROTO ANY IKE_FRAG ESP_FRAG MODE_CFG
234%token PFS_GROUP LIFETIME LIFETYPE_TIME LIFETYPE_BYTE STRENGTH REMOTEID
235
236%token SCRIPT PHASE1_UP PHASE1_DOWN
237
238%token NUMBER SWITCH BOOLEAN
239%token HEXSTRING QUOTEDSTRING ADDRSTRING ADDRRANGE
240%token UNITTYPE_BYTE UNITTYPE_KBYTES UNITTYPE_MBYTES UNITTYPE_TBYTES
241%token UNITTYPE_SEC UNITTYPE_MIN UNITTYPE_HOUR
242%token EOS BOC EOC COMMA
243
244%type <num> NUMBER BOOLEAN SWITCH keylength
245%type <num> PATHTYPE IDENTIFIERTYPE IDENTIFIERQUAL LOGLEV GSS_ID_ENCTYPE
246%type <num> ALGORITHM_CLASS dh_group_num
247%type <num> ALGORITHMTYPE STRENGTHTYPE
248%type <num> PREFIX prefix PORT port ike_port
249%type <num> ul_proto UL_PROTO
250%type <num> EXCHANGETYPE DOITYPE SITUATIONTYPE
251%type <num> CERTTYPE CERT_X509 CERT_PLAINRSA PROPOSAL_CHECK_LEVEL REMOTE_FORCE_LEVEL GENERATE_LEVEL
252%type <num> unittype_time unittype_byte
253%type <val> QUOTEDSTRING HEXSTRING ADDRSTRING ADDRRANGE sainfo_id
254%type <val> identifierstring
255%type <saddr> remote_index ike_addrinfo_port
256%type <alg> algorithm
257
258%%
259
260statements
261	:	/* nothing */
262	|	statements statement
263	;
264statement
265	:	privsep_statement
266	|	path_statement
267	|	include_statement
268	|	gssenc_statement
269	|	identifier_statement
270	|	logging_statement
271	|	padding_statement
272	|	listen_statement
273	|	ldapcfg_statement
274	|	modecfg_statement
275	|	timer_statement
276	|	sainfo_statement
277	|	remote_statement
278	|	special_statement
279	;
280
281	/* privsep */
282privsep_statement
283	:	PRIVSEP BOC privsep_stmts EOC
284	;
285privsep_stmts
286	:	/* nothing */
287	|	privsep_stmts privsep_stmt
288	;
289privsep_stmt
290	:	USER QUOTEDSTRING
291		{
292			struct passwd *pw;
293
294			if ((pw = getpwnam($2->v)) == NULL) {
295				yyerror("unknown user \"%s\"", $2->v);
296				return -1;
297			}
298			lcconf->uid = pw->pw_uid;
299		}
300		EOS
301	|	USER NUMBER { lcconf->uid = $2; } EOS
302	|	GROUP QUOTEDSTRING
303		{
304			struct group *gr;
305
306			if ((gr = getgrnam($2->v)) == NULL) {
307				yyerror("unknown group \"%s\"", $2->v);
308				return -1;
309			}
310			lcconf->gid = gr->gr_gid;
311		}
312		EOS
313	|	GROUP NUMBER { lcconf->gid = $2; } EOS
314	|	CHROOT QUOTEDSTRING { lcconf->chroot = $2->v; } EOS
315	;
316
317	/* path */
318path_statement
319	:	PATH PATHTYPE QUOTEDSTRING
320		{
321			if ($2 >= LC_PATHTYPE_MAX) {
322				yyerror("invalid path type %d", $2);
323				return -1;
324			}
325
326			/* free old pathinfo */
327			if (lcconf->pathinfo[$2])
328				racoon_free(lcconf->pathinfo[$2]);
329
330			/* set new pathinfo */
331			lcconf->pathinfo[$2] = racoon_strdup($3->v);
332			STRDUP_FATAL(lcconf->pathinfo[$2]);
333			vfree($3);
334		}
335		EOS
336	;
337
338	/* special */
339special_statement
340	:	COMPLEX_BUNDLE SWITCH { lcconf->complex_bundle = $2; } EOS
341	;
342
343	/* include */
344include_statement
345	:	INCLUDE QUOTEDSTRING EOS
346		{
347			char path[MAXPATHLEN];
348
349			getpathname(path, sizeof(path),
350				LC_PATHTYPE_INCLUDE, $2->v);
351			vfree($2);
352			if (yycf_switch_buffer(path) != 0)
353				return -1;
354		}
355	;
356
357	/* gss_id_enc */
358gssenc_statement
359	:	GSS_ID_ENC GSS_ID_ENCTYPE EOS
360		{
361			if ($2 >= LC_GSSENC_MAX) {
362				yyerror("invalid GSS ID encoding %d", $2);
363				return -1;
364			}
365			lcconf->gss_id_enc = $2;
366		}
367	;
368
369	/* self information */
370identifier_statement
371	:	IDENTIFIER identifier_stmt
372	;
373identifier_stmt
374	:	VENDORID
375		{
376			/*XXX to be deleted */
377		}
378		QUOTEDSTRING EOS
379	|	IDENTIFIERTYPE QUOTEDSTRING
380		{
381			/*XXX to be deleted */
382			$2->l--;	/* nuke '\0' */
383			lcconf->ident[$1] = $2;
384			if (lcconf->ident[$1] == NULL) {
385				yyerror("failed to set my ident: %s",
386					strerror(errno));
387				return -1;
388			}
389		}
390		EOS
391	;
392
393	/* logging */
394logging_statement
395	:	LOGGING log_level EOS
396	;
397log_level
398	:	HEXSTRING
399		{
400			/*
401			 * XXX ignore it because this specification
402			 * will be obsoleted.
403			 */
404			yywarn("see racoon.conf(5), such a log specification will be obsoleted.");
405			vfree($1);
406		}
407	|	LOGLEV
408		{
409			/*
410			 * set the loglevel to the value specified
411			 * in the configuration file plus the number
412			 * of -d options specified on the command line
413			 */
414			loglevel += $1 - oldloglevel;
415			oldloglevel = $1;
416		}
417	;
418
419	/* padding */
420padding_statement
421	:	PADDING BOC padding_stmts EOC
422	;
423padding_stmts
424	:	/* nothing */
425	|	padding_stmts padding_stmt
426	;
427padding_stmt
428	:	PAD_RANDOMIZE SWITCH { lcconf->pad_random = $2; } EOS
429	|	PAD_RANDOMIZELEN SWITCH { lcconf->pad_randomlen = $2; } EOS
430	|	PAD_MAXLEN NUMBER { lcconf->pad_maxsize = $2; } EOS
431	|	PAD_STRICT SWITCH { lcconf->pad_strict = $2; } EOS
432	|	PAD_EXCLTAIL SWITCH { lcconf->pad_excltail = $2; } EOS
433	;
434
435	/* listen */
436listen_statement
437	:	LISTEN BOC listen_stmts EOC
438	;
439listen_stmts
440	:	/* nothing */
441	|	listen_stmts listen_stmt
442	;
443listen_stmt
444	:	X_ISAKMP ike_addrinfo_port
445		{
446			listen_addr ($2, 0);
447		}
448		EOS
449	|	X_ISAKMP_NATT ike_addrinfo_port
450		{
451#ifdef ENABLE_NATT
452			listen_addr ($2, 1);
453#else
454			yyerror("NAT-T support not compiled in.");
455#endif
456		}
457		EOS
458	|	X_ADMIN
459		{
460			yyerror("admin directive is obsoleted.");
461		}
462		PORT EOS
463	|	ADMINSOCK QUOTEDSTRING QUOTEDSTRING QUOTEDSTRING NUMBER
464		{
465#ifdef ENABLE_ADMINPORT
466			adminsock_conf($2, $3, $4, $5);
467#else
468			yywarn("admin port support not compiled in");
469#endif
470		}
471		EOS
472	|	ADMINSOCK QUOTEDSTRING
473		{
474#ifdef ENABLE_ADMINPORT
475			adminsock_conf($2, NULL, NULL, -1);
476#else
477			yywarn("admin port support not compiled in");
478#endif
479		}
480		EOS
481	|	ADMINSOCK DISABLED
482		{
483#ifdef ENABLE_ADMINPORT
484			adminsock_path = NULL;
485#else
486			yywarn("admin port support not compiled in");
487#endif
488		}
489		EOS
490	|	STRICT_ADDRESS { lcconf->strict_address = TRUE; } EOS
491	;
492ike_addrinfo_port
493	:	ADDRSTRING ike_port
494		{
495			char portbuf[10];
496
497			snprintf(portbuf, sizeof(portbuf), "%ld", $2);
498			$$ = str2saddr($1->v, portbuf);
499			vfree($1);
500			if (!$$)
501				return -1;
502		}
503	;
504ike_port
505	:	/* nothing */	{ $$ = PORT_ISAKMP; }
506	|	PORT		{ $$ = $1; }
507	;
508
509	/* ldap configuration */
510ldapcfg_statement
511	:	LDAPCFG {
512#ifndef ENABLE_HYBRID
513			yyerror("racoon not configured with --enable-hybrid");
514			return -1;
515#endif
516#ifndef HAVE_LIBLDAP
517			yyerror("racoon not configured with --with-libldap");
518			return -1;
519#endif
520		} BOC ldapcfg_stmts EOC
521	;
522ldapcfg_stmts
523	:	/* nothing */
524	|	ldapcfg_stmts ldapcfg_stmt
525	;
526ldapcfg_stmt
527	:	LDAP_PVER NUMBER
528		{
529#ifdef ENABLE_HYBRID
530#ifdef HAVE_LIBLDAP
531			if (($2<2)||($2>3))
532				yyerror("invalid ldap protocol version (2|3)");
533			xauth_ldap_config.pver = $2;
534#endif
535#endif
536		}
537		EOS
538	|	LDAP_HOST QUOTEDSTRING
539		{
540#ifdef ENABLE_HYBRID
541#ifdef HAVE_LIBLDAP
542			if (xauth_ldap_config.host != NULL)
543				vfree(xauth_ldap_config.host);
544			xauth_ldap_config.host = vdup($2);
545#endif
546#endif
547		}
548		EOS
549	|	LDAP_PORT NUMBER
550		{
551#ifdef ENABLE_HYBRID
552#ifdef HAVE_LIBLDAP
553			xauth_ldap_config.port = $2;
554#endif
555#endif
556		}
557		EOS
558	|	LDAP_BASE QUOTEDSTRING
559		{
560#ifdef ENABLE_HYBRID
561#ifdef HAVE_LIBLDAP
562			if (xauth_ldap_config.base != NULL)
563				vfree(xauth_ldap_config.base);
564			xauth_ldap_config.base = vdup($2);
565#endif
566#endif
567		}
568		EOS
569	|	LDAP_SUBTREE SWITCH
570		{
571#ifdef ENABLE_HYBRID
572#ifdef HAVE_LIBLDAP
573			xauth_ldap_config.subtree = $2;
574#endif
575#endif
576		}
577		EOS
578	|	LDAP_BIND_DN QUOTEDSTRING
579		{
580#ifdef ENABLE_HYBRID
581#ifdef HAVE_LIBLDAP
582			if (xauth_ldap_config.bind_dn != NULL)
583				vfree(xauth_ldap_config.bind_dn);
584			xauth_ldap_config.bind_dn = vdup($2);
585#endif
586#endif
587		}
588		EOS
589	|	LDAP_BIND_PW QUOTEDSTRING
590		{
591#ifdef ENABLE_HYBRID
592#ifdef HAVE_LIBLDAP
593			if (xauth_ldap_config.bind_pw != NULL)
594				vfree(xauth_ldap_config.bind_pw);
595			xauth_ldap_config.bind_pw = vdup($2);
596#endif
597#endif
598		}
599		EOS
600	|	LDAP_ATTR_USER QUOTEDSTRING
601		{
602#ifdef ENABLE_HYBRID
603#ifdef HAVE_LIBLDAP
604			if (xauth_ldap_config.attr_user != NULL)
605				vfree(xauth_ldap_config.attr_user);
606			xauth_ldap_config.attr_user = vdup($2);
607#endif
608#endif
609		}
610		EOS
611	|	LDAP_ATTR_ADDR QUOTEDSTRING
612		{
613#ifdef ENABLE_HYBRID
614#ifdef HAVE_LIBLDAP
615			if (xauth_ldap_config.attr_addr != NULL)
616				vfree(xauth_ldap_config.attr_addr);
617			xauth_ldap_config.attr_addr = vdup($2);
618#endif
619#endif
620		}
621		EOS
622	|	LDAP_ATTR_MASK QUOTEDSTRING
623		{
624#ifdef ENABLE_HYBRID
625#ifdef HAVE_LIBLDAP
626			if (xauth_ldap_config.attr_mask != NULL)
627				vfree(xauth_ldap_config.attr_mask);
628			xauth_ldap_config.attr_mask = vdup($2);
629#endif
630#endif
631		}
632		EOS
633	|	LDAP_ATTR_GROUP QUOTEDSTRING
634		{
635#ifdef ENABLE_HYBRID
636#ifdef HAVE_LIBLDAP
637			if (xauth_ldap_config.attr_group != NULL)
638				vfree(xauth_ldap_config.attr_group);
639			xauth_ldap_config.attr_group = vdup($2);
640#endif
641#endif
642		}
643		EOS
644	|	LDAP_ATTR_MEMBER QUOTEDSTRING
645		{
646#ifdef ENABLE_HYBRID
647#ifdef HAVE_LIBLDAP
648			if (xauth_ldap_config.attr_member != NULL)
649				vfree(xauth_ldap_config.attr_member);
650			xauth_ldap_config.attr_member = vdup($2);
651#endif
652#endif
653		}
654		EOS
655	;
656
657	/* modecfg */
658modecfg_statement
659	:	MODECFG BOC modecfg_stmts EOC
660	;
661modecfg_stmts
662	:	/* nothing */
663	|	modecfg_stmts modecfg_stmt
664	;
665modecfg_stmt
666	:	CFG_NET4 ADDRSTRING
667		{
668#ifdef ENABLE_HYBRID
669			if (inet_pton(AF_INET, $2->v,
670			     &isakmp_cfg_config.network4) != 1)
671				yyerror("bad IPv4 network address.");
672#else
673			yyerror("racoon not configured with --enable-hybrid");
674#endif
675		}
676		EOS
677	|	CFG_MASK4 ADDRSTRING
678		{
679#ifdef ENABLE_HYBRID
680			if (inet_pton(AF_INET, $2->v,
681			    &isakmp_cfg_config.netmask4) != 1)
682				yyerror("bad IPv4 netmask address.");
683#else
684			yyerror("racoon not configured with --enable-hybrid");
685#endif
686		}
687		EOS
688	|	CFG_DNS4 addrdnslist
689		EOS
690	|	CFG_NBNS4 addrwinslist
691		EOS
692	|	CFG_SPLIT_NETWORK CFG_SPLIT_LOCAL splitnetlist
693		{
694#ifdef ENABLE_HYBRID
695			isakmp_cfg_config.splitnet_type = UNITY_LOCAL_LAN;
696#else
697			yyerror("racoon not configured with --enable-hybrid");
698#endif
699		}
700		EOS
701	|	CFG_SPLIT_NETWORK CFG_SPLIT_INCLUDE splitnetlist
702		{
703#ifdef ENABLE_HYBRID
704			isakmp_cfg_config.splitnet_type = UNITY_SPLIT_INCLUDE;
705#else
706			yyerror("racoon not configured with --enable-hybrid");
707#endif
708		}
709		EOS
710	|	CFG_SPLIT_DNS splitdnslist
711		{
712#ifndef ENABLE_HYBRID
713			yyerror("racoon not configured with --enable-hybrid");
714#endif
715		}
716		EOS
717	|	CFG_DEFAULT_DOMAIN QUOTEDSTRING
718		{
719#ifdef ENABLE_HYBRID
720			strncpy(&isakmp_cfg_config.default_domain[0],
721			    $2->v, MAXPATHLEN);
722			isakmp_cfg_config.default_domain[MAXPATHLEN] = '\0';
723			vfree($2);
724#else
725			yyerror("racoon not configured with --enable-hybrid");
726#endif
727		}
728		EOS
729	|	CFG_AUTH_SOURCE CFG_SYSTEM
730		{
731#ifdef ENABLE_HYBRID
732			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
733#else
734			yyerror("racoon not configured with --enable-hybrid");
735#endif
736		}
737		EOS
738	|	CFG_AUTH_SOURCE CFG_RADIUS
739		{
740#ifdef ENABLE_HYBRID
741#ifdef HAVE_LIBRADIUS
742			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_RADIUS;
743#else /* HAVE_LIBRADIUS */
744			yyerror("racoon not configured with --with-libradius");
745#endif /* HAVE_LIBRADIUS */
746#else /* ENABLE_HYBRID */
747			yyerror("racoon not configured with --enable-hybrid");
748#endif /* ENABLE_HYBRID */
749		}
750		EOS
751	|	CFG_AUTH_SOURCE CFG_PAM
752		{
753#ifdef ENABLE_HYBRID
754#ifdef HAVE_LIBPAM
755			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_PAM;
756#else /* HAVE_LIBPAM */
757			yyerror("racoon not configured with --with-libpam");
758#endif /* HAVE_LIBPAM */
759#else /* ENABLE_HYBRID */
760			yyerror("racoon not configured with --enable-hybrid");
761#endif /* ENABLE_HYBRID */
762		}
763		EOS
764	|	CFG_AUTH_SOURCE CFG_LDAP
765		{
766#ifdef ENABLE_HYBRID
767#ifdef HAVE_LIBLDAP
768			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_LDAP;
769#else /* HAVE_LIBLDAP */
770			yyerror("racoon not configured with --with-libldap");
771#endif /* HAVE_LIBLDAP */
772#else /* ENABLE_HYBRID */
773			yyerror("racoon not configured with --enable-hybrid");
774#endif /* ENABLE_HYBRID */
775		}
776		EOS
777	|	CFG_AUTH_GROUPS authgrouplist
778		{
779#ifndef ENABLE_HYBRID
780			yyerror("racoon not configured with --enable-hybrid");
781#endif
782		}
783		EOS
784	|	CFG_GROUP_SOURCE CFG_SYSTEM
785		{
786#ifdef ENABLE_HYBRID
787			isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_SYSTEM;
788#else
789			yyerror("racoon not configured with --enable-hybrid");
790#endif
791		}
792		EOS
793	|	CFG_GROUP_SOURCE CFG_LDAP
794		{
795#ifdef ENABLE_HYBRID
796#ifdef HAVE_LIBLDAP
797			isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_LDAP;
798#else /* HAVE_LIBLDAP */
799			yyerror("racoon not configured with --with-libldap");
800#endif /* HAVE_LIBLDAP */
801#else /* ENABLE_HYBRID */
802			yyerror("racoon not configured with --enable-hybrid");
803#endif /* ENABLE_HYBRID */
804		}
805		EOS
806	|	CFG_ACCOUNTING CFG_NONE
807		{
808#ifdef ENABLE_HYBRID
809			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
810#else
811			yyerror("racoon not configured with --enable-hybrid");
812#endif
813		}
814		EOS
815	|	CFG_ACCOUNTING CFG_SYSTEM
816		{
817#ifdef ENABLE_HYBRID
818			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_SYSTEM;
819#else
820			yyerror("racoon not configured with --enable-hybrid");
821#endif
822		}
823		EOS
824	|	CFG_ACCOUNTING CFG_RADIUS
825		{
826#ifdef ENABLE_HYBRID
827#ifdef HAVE_LIBRADIUS
828			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_RADIUS;
829#else /* HAVE_LIBRADIUS */
830			yyerror("racoon not configured with --with-libradius");
831#endif /* HAVE_LIBRADIUS */
832#else /* ENABLE_HYBRID */
833			yyerror("racoon not configured with --enable-hybrid");
834#endif /* ENABLE_HYBRID */
835		}
836		EOS
837	|	CFG_ACCOUNTING CFG_PAM
838		{
839#ifdef ENABLE_HYBRID
840#ifdef HAVE_LIBPAM
841			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_PAM;
842#else /* HAVE_LIBPAM */
843			yyerror("racoon not configured with --with-libpam");
844#endif /* HAVE_LIBPAM */
845#else /* ENABLE_HYBRID */
846			yyerror("racoon not configured with --enable-hybrid");
847#endif /* ENABLE_HYBRID */
848		}
849		EOS
850	|	CFG_POOL_SIZE NUMBER
851		{
852#ifdef ENABLE_HYBRID
853			if (isakmp_cfg_resize_pool($2) != 0)
854				yyerror("cannot allocate memory for pool");
855#else /* ENABLE_HYBRID */
856			yyerror("racoon not configured with --enable-hybrid");
857#endif /* ENABLE_HYBRID */
858		}
859		EOS
860	|	CFG_PFS_GROUP NUMBER
861		{
862#ifdef ENABLE_HYBRID
863			isakmp_cfg_config.pfs_group = $2;
864#else /* ENABLE_HYBRID */
865			yyerror("racoon not configured with --enable-hybrid");
866#endif /* ENABLE_HYBRID */
867		}
868		EOS
869	|	CFG_SAVE_PASSWD SWITCH
870		{
871#ifdef ENABLE_HYBRID
872			isakmp_cfg_config.save_passwd = $2;
873#else /* ENABLE_HYBRID */
874			yyerror("racoon not configured with --enable-hybrid");
875#endif /* ENABLE_HYBRID */
876		}
877		EOS
878	|	CFG_AUTH_THROTTLE NUMBER
879		{
880#ifdef ENABLE_HYBRID
881			isakmp_cfg_config.auth_throttle = $2;
882#else /* ENABLE_HYBRID */
883			yyerror("racoon not configured with --enable-hybrid");
884#endif /* ENABLE_HYBRID */
885		}
886		EOS
887	|	CFG_CONF_SOURCE CFG_LOCAL
888		{
889#ifdef ENABLE_HYBRID
890			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
891#else /* ENABLE_HYBRID */
892			yyerror("racoon not configured with --enable-hybrid");
893#endif /* ENABLE_HYBRID */
894		}
895		EOS
896	|	CFG_CONF_SOURCE CFG_RADIUS
897		{
898#ifdef ENABLE_HYBRID
899#ifdef HAVE_LIBRADIUS
900			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_RADIUS;
901#else /* HAVE_LIBRADIUS */
902			yyerror("racoon not configured with --with-libradius");
903#endif /* HAVE_LIBRADIUS */
904#else /* ENABLE_HYBRID */
905			yyerror("racoon not configured with --enable-hybrid");
906#endif /* ENABLE_HYBRID */
907		}
908		EOS
909	|	CFG_CONF_SOURCE CFG_LDAP
910		{
911#ifdef ENABLE_HYBRID
912#ifdef HAVE_LIBLDAP
913			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LDAP;
914#else /* HAVE_LIBLDAP */
915			yyerror("racoon not configured with --with-libldap");
916#endif /* HAVE_LIBLDAP */
917#else /* ENABLE_HYBRID */
918			yyerror("racoon not configured with --enable-hybrid");
919#endif /* ENABLE_HYBRID */
920		}
921		EOS
922	|	CFG_MOTD QUOTEDSTRING
923		{
924#ifdef ENABLE_HYBRID
925			strncpy(&isakmp_cfg_config.motd[0], $2->v, MAXPATHLEN);
926			isakmp_cfg_config.motd[MAXPATHLEN] = '\0';
927			vfree($2);
928#else
929			yyerror("racoon not configured with --enable-hybrid");
930#endif
931		}
932		EOS
933	;
934
935addrdnslist
936	:	addrdns
937	|	addrdns COMMA addrdnslist
938	;
939addrdns
940	:	ADDRSTRING
941		{
942#ifdef ENABLE_HYBRID
943			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
944
945			if (icc->dns4_index > MAXNS)
946				yyerror("No more than %d DNS", MAXNS);
947			if (inet_pton(AF_INET, $1->v,
948			    &icc->dns4[icc->dns4_index++]) != 1)
949				yyerror("bad IPv4 DNS address.");
950#else
951			yyerror("racoon not configured with --enable-hybrid");
952#endif
953		}
954	;
955
956addrwinslist
957	:	addrwins
958	|	addrwins COMMA addrwinslist
959	;
960addrwins
961	:	ADDRSTRING
962		{
963#ifdef ENABLE_HYBRID
964			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
965
966			if (icc->nbns4_index > MAXWINS)
967				yyerror("No more than %d WINS", MAXWINS);
968			if (inet_pton(AF_INET, $1->v,
969			    &icc->nbns4[icc->nbns4_index++]) != 1)
970				yyerror("bad IPv4 WINS address.");
971#else
972			yyerror("racoon not configured with --enable-hybrid");
973#endif
974		}
975	;
976
977splitnetlist
978	:	splitnet
979	|	splitnetlist COMMA splitnet
980	;
981splitnet
982	:	ADDRSTRING PREFIX
983		{
984#ifdef ENABLE_HYBRID
985			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
986			struct unity_network network;
987			memset(&network,0,sizeof(network));
988
989			if (inet_pton(AF_INET, $1->v, &network.addr4) != 1)
990				yyerror("bad IPv4 SPLIT address.");
991
992			/* Turn $2 (the prefix) into a subnet mask */
993			network.mask4.s_addr = ($2) ? htonl(~((1 << (32 - $2)) - 1)) : 0;
994
995			/* add the network to our list */
996			if (splitnet_list_add(&icc->splitnet_list, &network,&icc->splitnet_count))
997				yyerror("Unable to allocate split network");
998#else
999			yyerror("racoon not configured with --enable-hybrid");
1000#endif
1001		}
1002	;
1003
1004authgrouplist
1005	:	authgroup
1006	|	authgroup COMMA authgrouplist
1007	;
1008authgroup
1009	:	QUOTEDSTRING
1010		{
1011#ifdef ENABLE_HYBRID
1012			char * groupname = NULL;
1013			char ** grouplist = NULL;
1014			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
1015
1016			grouplist = racoon_realloc(icc->grouplist,
1017					sizeof(char**)*(icc->groupcount+1));
1018			if (grouplist == NULL)
1019				yyerror("unable to allocate auth group list");
1020
1021			groupname = racoon_malloc($1->l+1);
1022			if (groupname == NULL)
1023				yyerror("unable to allocate auth group name");
1024
1025			memcpy(groupname,$1->v,$1->l);
1026			groupname[$1->l]=0;
1027			grouplist[icc->groupcount]=groupname;
1028			icc->grouplist = grouplist;
1029			icc->groupcount++;
1030
1031			vfree($1);
1032#else
1033			yyerror("racoon not configured with --enable-hybrid");
1034#endif
1035		}
1036	;
1037
1038splitdnslist
1039	:	splitdns
1040	|	splitdns COMMA splitdnslist
1041	;
1042splitdns
1043	:	QUOTEDSTRING
1044		{
1045#ifdef ENABLE_HYBRID
1046			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
1047
1048			if (!icc->splitdns_len)
1049			{
1050				icc->splitdns_list = racoon_malloc($1->l);
1051				if(icc->splitdns_list == NULL)
1052					yyerror("error allocating splitdns list buffer");
1053				memcpy(icc->splitdns_list,$1->v,$1->l);
1054				icc->splitdns_len = $1->l;
1055			}
1056			else
1057			{
1058				int len = icc->splitdns_len + $1->l + 1;
1059				icc->splitdns_list = racoon_realloc(icc->splitdns_list,len);
1060				if(icc->splitdns_list == NULL)
1061					yyerror("error allocating splitdns list buffer");
1062				icc->splitdns_list[icc->splitdns_len] = ',';
1063				memcpy(icc->splitdns_list + icc->splitdns_len + 1, $1->v, $1->l);
1064				icc->splitdns_len = len;
1065			}
1066			vfree($1);
1067#else
1068			yyerror("racoon not configured with --enable-hybrid");
1069#endif
1070		}
1071	;
1072
1073
1074	/* timer */
1075timer_statement
1076	:	RETRY BOC timer_stmts EOC
1077	;
1078timer_stmts
1079	:	/* nothing */
1080	|	timer_stmts timer_stmt
1081	;
1082timer_stmt
1083	:	RETRY_COUNTER NUMBER
1084		{
1085			lcconf->retry_counter = $2;
1086		}
1087		EOS
1088	|	RETRY_INTERVAL NUMBER unittype_time
1089		{
1090			lcconf->retry_interval = $2 * $3;
1091		}
1092		EOS
1093	|	RETRY_PERSEND NUMBER
1094		{
1095			lcconf->count_persend = $2;
1096		}
1097		EOS
1098	|	RETRY_PHASE1 NUMBER unittype_time
1099		{
1100			lcconf->retry_checkph1 = $2 * $3;
1101		}
1102		EOS
1103	|	RETRY_PHASE2 NUMBER unittype_time
1104		{
1105			lcconf->wait_ph2complete = $2 * $3;
1106		}
1107		EOS
1108	|	NATT_KA NUMBER unittype_time
1109		{
1110#ifdef ENABLE_NATT
1111        		if (libipsec_opt & LIBIPSEC_OPT_NATT)
1112				lcconf->natt_ka_interval = $2 * $3;
1113			else
1114                		yyerror("libipsec lacks NAT-T support");
1115#else
1116			yyerror("NAT-T support not compiled in.");
1117#endif
1118		}
1119		EOS
1120	;
1121
1122	/* sainfo */
1123sainfo_statement
1124	:	SAINFO
1125		{
1126			cur_sainfo = newsainfo();
1127			if (cur_sainfo == NULL) {
1128				yyerror("failed to allocate sainfo");
1129				return -1;
1130			}
1131		}
1132		sainfo_name sainfo_param BOC sainfo_specs
1133		{
1134			struct sainfo *check;
1135
1136			/* default */
1137			if (cur_sainfo->algs[algclass_ipsec_enc] == 0) {
1138				yyerror("no encryption algorithm at %s",
1139					sainfo2str(cur_sainfo));
1140				return -1;
1141			}
1142			if (cur_sainfo->algs[algclass_ipsec_auth] == 0) {
1143				yyerror("no authentication algorithm at %s",
1144					sainfo2str(cur_sainfo));
1145				return -1;
1146			}
1147			if (cur_sainfo->algs[algclass_ipsec_comp] == 0) {
1148				yyerror("no compression algorithm at %s",
1149					sainfo2str(cur_sainfo));
1150				return -1;
1151			}
1152
1153			/* duplicate check */
1154			check = getsainfo(cur_sainfo->idsrc,
1155					  cur_sainfo->iddst,
1156					  cur_sainfo->id_i,
1157					  cur_sainfo->remoteid);
1158			if (check && (!check->idsrc && !cur_sainfo->idsrc)) {
1159				yyerror("duplicated sainfo: %s",
1160					sainfo2str(cur_sainfo));
1161				return -1;
1162			}
1163			inssainfo(cur_sainfo);
1164		}
1165		EOC
1166	;
1167sainfo_name
1168	:	ANONYMOUS
1169		{
1170			cur_sainfo->idsrc = NULL;
1171			cur_sainfo->iddst = NULL;
1172		}
1173	|	ANONYMOUS sainfo_id
1174		{
1175			cur_sainfo->idsrc = NULL;
1176			cur_sainfo->iddst = $2;
1177		}
1178	|	sainfo_id ANONYMOUS
1179		{
1180			cur_sainfo->idsrc = $1;
1181			cur_sainfo->iddst = NULL;
1182		}
1183	|	sainfo_id sainfo_id
1184		{
1185			cur_sainfo->idsrc = $1;
1186			cur_sainfo->iddst = $2;
1187		}
1188	;
1189sainfo_id
1190	:	IDENTIFIERTYPE ADDRSTRING prefix port ul_proto
1191		{
1192			char portbuf[10];
1193			struct sockaddr *saddr;
1194
1195			if (($5 == IPPROTO_ICMP || $5 == IPPROTO_ICMPV6)
1196			 && ($4 != IPSEC_PORT_ANY || $4 != IPSEC_PORT_ANY)) {
1197				yyerror("port number must be \"any\".");
1198				return -1;
1199			}
1200
1201			snprintf(portbuf, sizeof(portbuf), "%lu", $4);
1202			saddr = str2saddr($2->v, portbuf);
1203			vfree($2);
1204			if (saddr == NULL)
1205				return -1;
1206
1207			switch (saddr->sa_family) {
1208			case AF_INET:
1209				if ($5 == IPPROTO_ICMPV6) {
1210					yyerror("upper layer protocol mismatched.\n");
1211					racoon_free(saddr);
1212					return -1;
1213				}
1214				$$ = ipsecdoi_sockaddr2id(saddr,
1215										  $3 == ~0 ? (sizeof(struct in_addr) << 3): $3,
1216										  $5);
1217				break;
1218#ifdef INET6
1219			case AF_INET6:
1220				if ($5 == IPPROTO_ICMP) {
1221					yyerror("upper layer protocol mismatched.\n");
1222					racoon_free(saddr);
1223					return -1;
1224				}
1225				$$ = ipsecdoi_sockaddr2id(saddr,
1226										  $3 == ~0 ? (sizeof(struct in6_addr) << 3): $3,
1227										  $5);
1228				break;
1229#endif
1230			default:
1231				yyerror("invalid family: %d", saddr->sa_family);
1232				$$ = NULL;
1233				break;
1234			}
1235			racoon_free(saddr);
1236			if ($$ == NULL)
1237				return -1;
1238		}
1239	|	IDENTIFIERTYPE ADDRSTRING ADDRRANGE prefix port ul_proto
1240		{
1241			char portbuf[10];
1242			struct sockaddr *laddr = NULL, *haddr = NULL;
1243			char *cur = NULL;
1244
1245			if (($6 == IPPROTO_ICMP || $6 == IPPROTO_ICMPV6)
1246			 && ($5 != IPSEC_PORT_ANY || $5 != IPSEC_PORT_ANY)) {
1247				yyerror("port number must be \"any\".");
1248				return -1;
1249			}
1250
1251			snprintf(portbuf, sizeof(portbuf), "%lu", $5);
1252
1253			laddr = str2saddr($2->v, portbuf);
1254			if (laddr == NULL) {
1255			    return -1;
1256			}
1257			vfree($2);
1258			haddr = str2saddr($3->v, portbuf);
1259			if (haddr == NULL) {
1260			    racoon_free(laddr);
1261			    return -1;
1262			}
1263			vfree($3);
1264
1265			switch (laddr->sa_family) {
1266			case AF_INET:
1267				if ($6 == IPPROTO_ICMPV6) {
1268				    yyerror("upper layer protocol mismatched.\n");
1269				    if (laddr)
1270					racoon_free(laddr);
1271				    if (haddr)
1272					racoon_free(haddr);
1273				    return -1;
1274				}
1275                                $$ = ipsecdoi_sockrange2id(laddr, haddr,
1276							   $6);
1277				break;
1278#ifdef INET6
1279			case AF_INET6:
1280				if ($6 == IPPROTO_ICMP) {
1281					yyerror("upper layer protocol mismatched.\n");
1282					if (laddr)
1283					    racoon_free(laddr);
1284					if (haddr)
1285					    racoon_free(haddr);
1286					return -1;
1287				}
1288				$$ = ipsecdoi_sockrange2id(laddr, haddr,
1289							       $6);
1290				break;
1291#endif
1292			default:
1293				yyerror("invalid family: %d", laddr->sa_family);
1294				$$ = NULL;
1295				break;
1296			}
1297			if (laddr)
1298			    racoon_free(laddr);
1299			if (haddr)
1300			    racoon_free(haddr);
1301			if ($$ == NULL)
1302				return -1;
1303		}
1304	|	IDENTIFIERTYPE QUOTEDSTRING
1305		{
1306			struct ipsecdoi_id_b *id_b;
1307
1308			if ($1 == IDTYPE_ASN1DN) {
1309				yyerror("id type forbidden: %d", $1);
1310				$$ = NULL;
1311				return -1;
1312			}
1313
1314			$2->l--;
1315
1316			$$ = vmalloc(sizeof(*id_b) + $2->l);
1317			if ($$ == NULL) {
1318				yyerror("failed to allocate identifier");
1319				return -1;
1320			}
1321
1322			id_b = (struct ipsecdoi_id_b *)$$->v;
1323			id_b->type = idtype2doi($1);
1324
1325			id_b->proto_id = 0;
1326			id_b->port = 0;
1327
1328			memcpy($$->v + sizeof(*id_b), $2->v, $2->l);
1329		}
1330	;
1331sainfo_param
1332	:	/* nothing */
1333		{
1334			cur_sainfo->id_i = NULL;
1335		}
1336	|	FROM IDENTIFIERTYPE identifierstring
1337		{
1338			struct ipsecdoi_id_b *id_b;
1339			vchar_t *idv;
1340
1341			if (set_identifier(&idv, $2, $3) != 0) {
1342				yyerror("failed to set identifer.\n");
1343				return -1;
1344			}
1345			cur_sainfo->id_i = vmalloc(sizeof(*id_b) + idv->l);
1346			if (cur_sainfo->id_i == NULL) {
1347				yyerror("failed to allocate identifier");
1348				return -1;
1349			}
1350
1351			id_b = (struct ipsecdoi_id_b *)cur_sainfo->id_i->v;
1352			id_b->type = idtype2doi($2);
1353
1354			id_b->proto_id = 0;
1355			id_b->port = 0;
1356
1357			memcpy(cur_sainfo->id_i->v + sizeof(*id_b),
1358			       idv->v, idv->l);
1359			vfree(idv);
1360		}
1361	|	GROUP QUOTEDSTRING
1362		{
1363#ifdef ENABLE_HYBRID
1364			if ((cur_sainfo->group = vdup($2)) == NULL) {
1365				yyerror("failed to set sainfo xauth group.\n");
1366				return -1;
1367			}
1368#else
1369			yyerror("racoon not configured with --enable-hybrid");
1370			return -1;
1371#endif
1372 		}
1373	;
1374sainfo_specs
1375	:	/* nothing */
1376	|	sainfo_specs sainfo_spec
1377	;
1378sainfo_spec
1379	:	PFS_GROUP dh_group_num
1380		{
1381			cur_sainfo->pfs_group = $2;
1382		}
1383		EOS
1384	|	REMOTEID NUMBER
1385		{
1386			cur_sainfo->remoteid = $2;
1387		}
1388		EOS
1389	|	LIFETIME LIFETYPE_TIME NUMBER unittype_time
1390		{
1391			cur_sainfo->lifetime = $3 * $4;
1392		}
1393		EOS
1394	|	LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
1395		{
1396#if 1
1397			yyerror("byte lifetime support is deprecated");
1398			return -1;
1399#else
1400			cur_sainfo->lifebyte = fix_lifebyte($3 * $4);
1401			if (cur_sainfo->lifebyte == 0)
1402				return -1;
1403#endif
1404		}
1405		EOS
1406	|	ALGORITHM_CLASS {
1407			cur_algclass = $1;
1408		}
1409		algorithms EOS
1410	|	IDENTIFIER IDENTIFIERTYPE
1411		{
1412			yyerror("it's deprecated to specify a identifier in phase 2");
1413		}
1414		EOS
1415	|	MY_IDENTIFIER IDENTIFIERTYPE QUOTEDSTRING
1416		{
1417			yyerror("it's deprecated to specify a identifier in phase 2");
1418		}
1419		EOS
1420	;
1421
1422algorithms
1423	:	algorithm
1424		{
1425			inssainfoalg(&cur_sainfo->algs[cur_algclass], $1);
1426		}
1427	|	algorithm
1428		{
1429			inssainfoalg(&cur_sainfo->algs[cur_algclass], $1);
1430		}
1431		COMMA algorithms
1432	;
1433algorithm
1434	:	ALGORITHMTYPE keylength
1435		{
1436			int defklen;
1437
1438			$$ = newsainfoalg();
1439			if ($$ == NULL) {
1440				yyerror("failed to get algorithm allocation");
1441				return -1;
1442			}
1443
1444			$$->alg = algtype2doi(cur_algclass, $1);
1445			if ($$->alg == -1) {
1446				yyerror("algorithm mismatched");
1447				racoon_free($$);
1448				$$ = NULL;
1449				return -1;
1450			}
1451
1452			defklen = default_keylen(cur_algclass, $1);
1453			if (defklen == 0) {
1454				if ($2) {
1455					yyerror("keylen not allowed");
1456					racoon_free($$);
1457					$$ = NULL;
1458					return -1;
1459				}
1460			} else {
1461				if ($2 && check_keylen(cur_algclass, $1, $2) < 0) {
1462					yyerror("invalid keylen %d", $2);
1463					racoon_free($$);
1464					$$ = NULL;
1465					return -1;
1466				}
1467			}
1468
1469			if ($2)
1470				$$->encklen = $2;
1471			else
1472				$$->encklen = defklen;
1473
1474			/* check if it's supported algorithm by kernel */
1475			if (!(cur_algclass == algclass_ipsec_auth && $1 == algtype_non_auth)
1476			 && pk_checkalg(cur_algclass, $1, $$->encklen)) {
1477				int a = algclass2doi(cur_algclass);
1478				int b = algtype2doi(cur_algclass, $1);
1479				if (a == IPSECDOI_ATTR_AUTH)
1480					a = IPSECDOI_PROTO_IPSEC_AH;
1481				yyerror("algorithm %s not supported by the kernel (missing module?)",
1482					s_ipsecdoi_trns(a, b));
1483				racoon_free($$);
1484				$$ = NULL;
1485				return -1;
1486			}
1487		}
1488	;
1489prefix
1490	:	/* nothing */ { $$ = ~0; }
1491	|	PREFIX { $$ = $1; }
1492	;
1493port
1494	:	/* nothing */ { $$ = IPSEC_PORT_ANY; }
1495	|	PORT { $$ = $1; }
1496	|	PORTANY { $$ = IPSEC_PORT_ANY; }
1497	;
1498ul_proto
1499	:	NUMBER { $$ = $1; }
1500	|	UL_PROTO { $$ = $1; }
1501	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
1502	;
1503keylength
1504	:	/* nothing */ { $$ = 0; }
1505	|	NUMBER { $$ = $1; }
1506	;
1507
1508	/* remote */
1509remote_statement
1510	:	REMOTE remote_index INHERIT remote_index
1511		{
1512			struct remoteconf *new;
1513			struct proposalspec *prspec;
1514
1515			new = copyrmconf($4);
1516			if (new == NULL) {
1517				yyerror("failed to get remoteconf for %s.", saddr2str ($4));
1518				return -1;
1519			}
1520
1521			new->remote = $2;
1522			new->inherited_from = getrmconf_strict($4, 1);
1523			new->proposal = NULL;
1524			new->prhead = NULL;
1525			cur_rmconf = new;
1526
1527			prspec = newprspec();
1528			if (prspec == NULL || !cur_rmconf->inherited_from
1529				|| !cur_rmconf->inherited_from->proposal)
1530				return -1;
1531			prspec->lifetime = cur_rmconf->inherited_from->proposal->lifetime;
1532			prspec->lifebyte = cur_rmconf->inherited_from->proposal->lifebyte;
1533			insprspec(prspec, &cur_rmconf->prhead);
1534		}
1535		remote_specs_block
1536	|	REMOTE remote_index
1537		{
1538			struct remoteconf *new;
1539			struct proposalspec *prspec;
1540
1541			new = newrmconf();
1542			if (new == NULL) {
1543				yyerror("failed to get new remoteconf.");
1544				return -1;
1545			}
1546
1547			new->remote = $2;
1548			cur_rmconf = new;
1549
1550			prspec = newprspec();
1551			if (prspec == NULL)
1552				return -1;
1553			prspec->lifetime = oakley_get_defaultlifetime();
1554			insprspec(prspec, &cur_rmconf->prhead);
1555		}
1556		remote_specs_block
1557	;
1558
1559remote_specs_block
1560	:	BOC remote_specs EOC
1561		{
1562			/* check a exchange mode */
1563			if (cur_rmconf->etypes == NULL) {
1564				yyerror("no exchange mode specified.\n");
1565				return -1;
1566			}
1567
1568			if (cur_rmconf->idvtype == IDTYPE_UNDEFINED)
1569				cur_rmconf->idvtype = IDTYPE_ADDRESS;
1570
1571
1572			if (cur_rmconf->idvtype == IDTYPE_ASN1DN) {
1573				if (cur_rmconf->mycertfile) {
1574					if (cur_rmconf->idv)
1575						yywarn("Both CERT and ASN1 ID "
1576						       "are set. Hope this is OK.\n");
1577					/* TODO: Preparse the DN here */
1578				} else if (cur_rmconf->idv) {
1579					/* OK, using asn1dn without X.509. */
1580				} else {
1581					yyerror("ASN1 ID not specified "
1582						"and no CERT defined!\n");
1583					return -1;
1584				}
1585			}
1586
1587			if (cur_rmconf->prhead->spspec == NULL
1588				&& cur_rmconf->inherited_from
1589				&& cur_rmconf->inherited_from->prhead) {
1590				cur_rmconf->prhead->spspec = cur_rmconf->inherited_from->prhead->spspec;
1591			}
1592			if (set_isakmp_proposal(cur_rmconf, cur_rmconf->prhead) != 0)
1593				return -1;
1594
1595			/* DH group settting if aggressive mode is there. */
1596			if (check_etypeok(cur_rmconf, ISAKMP_ETYPE_AGG) != NULL) {
1597				struct isakmpsa *p;
1598				int b = 0;
1599
1600				/* DH group */
1601				for (p = cur_rmconf->proposal; p; p = p->next) {
1602					if (b == 0 || (b && b == p->dh_group)) {
1603						b = p->dh_group;
1604						continue;
1605					}
1606					yyerror("DH group must be equal "
1607						"in all proposals "
1608						"when aggressive mode is "
1609						"used.\n");
1610					return -1;
1611				}
1612				cur_rmconf->dh_group = b;
1613
1614				if (cur_rmconf->dh_group == 0) {
1615					yyerror("DH group must be set in the proposal.\n");
1616					return -1;
1617				}
1618
1619				/* DH group settting if PFS is required. */
1620				if (oakley_setdhgroup(cur_rmconf->dh_group,
1621						&cur_rmconf->dhgrp) < 0) {
1622					yyerror("failed to set DH value.\n");
1623					return -1;
1624				}
1625			}
1626
1627			insrmconf(cur_rmconf);
1628		}
1629	;
1630remote_index
1631	:	ANONYMOUS ike_port
1632		{
1633			$$ = newsaddr(sizeof(struct sockaddr));
1634			$$->sa_family = AF_UNSPEC;
1635			((struct sockaddr_in *)$$)->sin_port = htons($2);
1636		}
1637	|	ike_addrinfo_port
1638		{
1639			$$ = $1;
1640			if ($$ == NULL) {
1641				yyerror("failed to allocate sockaddr");
1642				return -1;
1643			}
1644		}
1645	;
1646remote_specs
1647	:	/* nothing */
1648	|	remote_specs remote_spec
1649	;
1650remote_spec
1651	:	EXCHANGE_MODE
1652		{
1653			cur_rmconf->etypes = NULL;
1654		}
1655		exchange_types EOS
1656	|	DOI DOITYPE { cur_rmconf->doitype = $2; } EOS
1657	|	SITUATION SITUATIONTYPE { cur_rmconf->sittype = $2; } EOS
1658	|	CERTIFICATE_TYPE cert_spec
1659	|	PEERS_CERTFILE QUOTEDSTRING
1660		{
1661			yywarn("This directive without certtype will be removed!\n");
1662			yywarn("Please use 'peers_certfile x509 \"%s\";' instead\n", $2->v);
1663			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
1664
1665			if (cur_rmconf->peerscertfile != NULL)
1666				racoon_free(cur_rmconf->peerscertfile);
1667			cur_rmconf->peerscertfile = racoon_strdup($2->v);
1668			STRDUP_FATAL(cur_rmconf->peerscertfile);
1669			vfree($2);
1670		}
1671		EOS
1672	|	CA_TYPE CERT_X509 QUOTEDSTRING
1673		{
1674			cur_rmconf->cacerttype = $2;
1675			cur_rmconf->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
1676			if (cur_rmconf->cacertfile != NULL)
1677				racoon_free(cur_rmconf->cacertfile);
1678			cur_rmconf->cacertfile = racoon_strdup($3->v);
1679			STRDUP_FATAL(cur_rmconf->cacertfile);
1680			vfree($3);
1681		}
1682		EOS
1683	|	PEERS_CERTFILE CERT_X509 QUOTEDSTRING
1684		{
1685			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
1686			if (cur_rmconf->peerscertfile != NULL)
1687				racoon_free(cur_rmconf->peerscertfile);
1688			cur_rmconf->peerscertfile = racoon_strdup($3->v);
1689			STRDUP_FATAL(cur_rmconf->peerscertfile);
1690			vfree($3);
1691		}
1692		EOS
1693	|	PEERS_CERTFILE CERT_PLAINRSA QUOTEDSTRING
1694		{
1695			char path[MAXPATHLEN];
1696			int ret = 0;
1697
1698			getpathname(path, sizeof(path),
1699				LC_PATHTYPE_CERT, $3->v);
1700			vfree($3);
1701
1702			if (cur_rmconf->getcert_method == ISAKMP_GETCERT_DNS) {
1703				yyerror("Different peers_certfile method "
1704					"already defined: %d!\n",
1705					cur_rmconf->getcert_method);
1706				return -1;
1707			}
1708			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
1709			if (rsa_parse_file(cur_rmconf->rsa_public, path, RSA_TYPE_PUBLIC)) {
1710				yyerror("Couldn't parse keyfile.\n", path);
1711				return -1;
1712			}
1713			plog(LLV_DEBUG, LOCATION, NULL, "Public PlainRSA keyfile parsed: %s\n", path);
1714		}
1715		EOS
1716	|	PEERS_CERTFILE DNSSEC
1717		{
1718			if (cur_rmconf->getcert_method) {
1719				yyerror("Different peers_certfile method already defined!\n");
1720				return -1;
1721			}
1722			cur_rmconf->getcert_method = ISAKMP_GETCERT_DNS;
1723			cur_rmconf->peerscertfile = NULL;
1724		}
1725		EOS
1726	|	VERIFY_CERT SWITCH { cur_rmconf->verify_cert = $2; } EOS
1727	|	SEND_CERT SWITCH { cur_rmconf->send_cert = $2; } EOS
1728	|	SEND_CR SWITCH { cur_rmconf->send_cr = $2; } EOS
1729	|	MY_IDENTIFIER IDENTIFIERTYPE identifierstring
1730		{
1731			if (set_identifier(&cur_rmconf->idv, $2, $3) != 0) {
1732				yyerror("failed to set identifer.\n");
1733				return -1;
1734			}
1735			cur_rmconf->idvtype = $2;
1736		}
1737		EOS
1738	|	MY_IDENTIFIER IDENTIFIERTYPE IDENTIFIERQUAL identifierstring
1739		{
1740			if (set_identifier_qual(&cur_rmconf->idv, $2, $4, $3) != 0) {
1741				yyerror("failed to set identifer.\n");
1742				return -1;
1743			}
1744			cur_rmconf->idvtype = $2;
1745		}
1746		EOS
1747	|	XAUTH_LOGIN identifierstring
1748		{
1749#ifdef ENABLE_HYBRID
1750			/* formerly identifier type login */
1751			if (xauth_rmconf_used(&cur_rmconf->xauth) == -1) {
1752				yyerror("failed to allocate xauth state\n");
1753				return -1;
1754			}
1755			if ((cur_rmconf->xauth->login = vdup($2)) == NULL) {
1756				yyerror("failed to set identifer.\n");
1757				return -1;
1758			}
1759#else
1760			yyerror("racoon not configured with --enable-hybrid");
1761#endif
1762		}
1763		EOS
1764	|	PEERS_IDENTIFIER IDENTIFIERTYPE identifierstring
1765		{
1766			struct idspec  *id;
1767			id = newidspec();
1768			if (id == NULL) {
1769				yyerror("failed to allocate idspec");
1770				return -1;
1771			}
1772			if (set_identifier(&id->id, $2, $3) != 0) {
1773				yyerror("failed to set identifer.\n");
1774				racoon_free(id);
1775				return -1;
1776			}
1777			id->idtype = $2;
1778			genlist_append (cur_rmconf->idvl_p, id);
1779		}
1780		EOS
1781	|	PEERS_IDENTIFIER IDENTIFIERTYPE IDENTIFIERQUAL identifierstring
1782		{
1783			struct idspec  *id;
1784			id = newidspec();
1785			if (id == NULL) {
1786				yyerror("failed to allocate idspec");
1787				return -1;
1788			}
1789			if (set_identifier_qual(&id->id, $2, $4, $3) != 0) {
1790				yyerror("failed to set identifer.\n");
1791				racoon_free(id);
1792				return -1;
1793			}
1794			id->idtype = $2;
1795			genlist_append (cur_rmconf->idvl_p, id);
1796		}
1797		EOS
1798	|	VERIFY_IDENTIFIER SWITCH { cur_rmconf->verify_identifier = $2; } EOS
1799	|	NONCE_SIZE NUMBER { cur_rmconf->nonce_size = $2; } EOS
1800	|	DH_GROUP
1801		{
1802			yyerror("dh_group cannot be defined here.");
1803			return -1;
1804		}
1805		dh_group_num EOS
1806	|	PASSIVE SWITCH { cur_rmconf->passive = $2; } EOS
1807	|	IKE_FRAG SWITCH { cur_rmconf->ike_frag = $2; } EOS
1808	|	IKE_FRAG REMOTE_FORCE_LEVEL { cur_rmconf->ike_frag = ISAKMP_FRAG_FORCE; } EOS
1809	|	ESP_FRAG NUMBER {
1810#ifdef SADB_X_EXT_NAT_T_FRAG
1811        		if (libipsec_opt & LIBIPSEC_OPT_FRAG)
1812				cur_rmconf->esp_frag = $2;
1813			else
1814                		yywarn("libipsec lacks IKE frag support");
1815#else
1816			yywarn("Your kernel does not support esp_frag");
1817#endif
1818		} EOS
1819	|	SCRIPT QUOTEDSTRING PHASE1_UP {
1820			if (cur_rmconf->script[SCRIPT_PHASE1_UP] != NULL)
1821				vfree(cur_rmconf->script[SCRIPT_PHASE1_UP]);
1822
1823			cur_rmconf->script[SCRIPT_PHASE1_UP] =
1824			    script_path_add(vdup($2));
1825		} EOS
1826	|	SCRIPT QUOTEDSTRING PHASE1_DOWN {
1827			if (cur_rmconf->script[SCRIPT_PHASE1_DOWN] != NULL)
1828				vfree(cur_rmconf->script[SCRIPT_PHASE1_DOWN]);
1829
1830			cur_rmconf->script[SCRIPT_PHASE1_DOWN] =
1831			    script_path_add(vdup($2));
1832		} EOS
1833	|	MODE_CFG SWITCH { cur_rmconf->mode_cfg = $2; } EOS
1834	|	WEAK_PHASE1_CHECK SWITCH {
1835			cur_rmconf->weak_phase1_check = $2;
1836		} EOS
1837	|	GENERATE_POLICY SWITCH { cur_rmconf->gen_policy = $2; } EOS
1838	|	GENERATE_POLICY GENERATE_LEVEL { cur_rmconf->gen_policy = $2; } EOS
1839	|	SUPPORT_PROXY SWITCH { cur_rmconf->support_proxy = $2; } EOS
1840	|	INITIAL_CONTACT SWITCH { cur_rmconf->ini_contact = $2; } EOS
1841	|	NAT_TRAVERSAL SWITCH
1842		{
1843#ifdef ENABLE_NATT
1844        		if (libipsec_opt & LIBIPSEC_OPT_NATT)
1845				cur_rmconf->nat_traversal = $2;
1846			else
1847                		yyerror("libipsec lacks NAT-T support");
1848#else
1849			yyerror("NAT-T support not compiled in.");
1850#endif
1851		} EOS
1852	|	NAT_TRAVERSAL REMOTE_FORCE_LEVEL
1853		{
1854#ifdef ENABLE_NATT
1855			if (libipsec_opt & LIBIPSEC_OPT_NATT)
1856				cur_rmconf->nat_traversal = NATT_FORCE;
1857			else
1858                		yyerror("libipsec lacks NAT-T support");
1859#else
1860			yyerror("NAT-T support not compiled in.");
1861#endif
1862		} EOS
1863	|	DPD SWITCH
1864		{
1865#ifdef ENABLE_DPD
1866			cur_rmconf->dpd = $2;
1867#else
1868			yyerror("DPD support not compiled in.");
1869#endif
1870		} EOS
1871	|	DPD_DELAY NUMBER
1872		{
1873#ifdef ENABLE_DPD
1874			cur_rmconf->dpd_interval = $2;
1875#else
1876			yyerror("DPD support not compiled in.");
1877#endif
1878		}
1879		EOS
1880	|	DPD_RETRY NUMBER
1881		{
1882#ifdef ENABLE_DPD
1883			cur_rmconf->dpd_retry = $2;
1884#else
1885			yyerror("DPD support not compiled in.");
1886#endif
1887		}
1888		EOS
1889	|	DPD_MAXFAIL NUMBER
1890		{
1891#ifdef ENABLE_DPD
1892			cur_rmconf->dpd_maxfails = $2;
1893#else
1894			yyerror("DPD support not compiled in.");
1895#endif
1896		}
1897		EOS
1898	|	PH1ID NUMBER
1899		{
1900			cur_rmconf->ph1id = $2;
1901		}
1902		EOS
1903	|	LIFETIME LIFETYPE_TIME NUMBER unittype_time
1904		{
1905			cur_rmconf->prhead->lifetime = $3 * $4;
1906		}
1907		EOS
1908	|	PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL { cur_rmconf->pcheck_level = $2; } EOS
1909	|	LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
1910		{
1911#if 1
1912			yyerror("byte lifetime support is deprecated in Phase1");
1913			return -1;
1914#else
1915			yywarn("the lifetime of bytes in phase 1 "
1916				"will be ignored at the moment.");
1917			cur_rmconf->prhead->lifebyte = fix_lifebyte($3 * $4);
1918			if (cur_rmconf->prhead->lifebyte == 0)
1919				return -1;
1920#endif
1921		}
1922		EOS
1923	|	PROPOSAL
1924		{
1925			struct secprotospec *spspec;
1926
1927			spspec = newspspec();
1928			if (spspec == NULL)
1929				return -1;
1930			insspspec(spspec, &cur_rmconf->prhead);
1931		}
1932		BOC isakmpproposal_specs EOC
1933	;
1934exchange_types
1935	:	/* nothing */
1936	|	exchange_types EXCHANGETYPE
1937		{
1938			struct etypes *new;
1939			new = racoon_malloc(sizeof(struct etypes));
1940			if (new == NULL) {
1941				yyerror("failed to allocate etypes");
1942				return -1;
1943			}
1944			new->type = $2;
1945			new->next = NULL;
1946			if (cur_rmconf->etypes == NULL)
1947				cur_rmconf->etypes = new;
1948			else {
1949				struct etypes *p;
1950				for (p = cur_rmconf->etypes;
1951				     p->next != NULL;
1952				     p = p->next)
1953					;
1954				p->next = new;
1955			}
1956		}
1957	;
1958cert_spec
1959	:	CERT_X509 QUOTEDSTRING QUOTEDSTRING
1960		{
1961			cur_rmconf->certtype = $1;
1962			if (cur_rmconf->mycertfile != NULL)
1963				racoon_free(cur_rmconf->mycertfile);
1964			cur_rmconf->mycertfile = racoon_strdup($2->v);
1965			STRDUP_FATAL(cur_rmconf->mycertfile);
1966			vfree($2);
1967			if (cur_rmconf->myprivfile != NULL)
1968				racoon_free(cur_rmconf->myprivfile);
1969			cur_rmconf->myprivfile = racoon_strdup($3->v);
1970			STRDUP_FATAL(cur_rmconf->myprivfile);
1971			vfree($3);
1972		}
1973		EOS
1974	|	CERT_PLAINRSA QUOTEDSTRING
1975		{
1976			char path[MAXPATHLEN];
1977			int ret = 0;
1978
1979			getpathname(path, sizeof(path),
1980				LC_PATHTYPE_CERT, $2->v);
1981			vfree($2);
1982
1983			cur_rmconf->certtype = $1;
1984			cur_rmconf->send_cr = FALSE;
1985			cur_rmconf->send_cert = FALSE;
1986			cur_rmconf->verify_cert = FALSE;
1987			if (rsa_parse_file(cur_rmconf->rsa_private, path, RSA_TYPE_PRIVATE)) {
1988				yyerror("Couldn't parse keyfile.\n", path);
1989				return -1;
1990			}
1991			plog(LLV_DEBUG, LOCATION, NULL, "Private PlainRSA keyfile parsed: %s\n", path);
1992		}
1993		EOS
1994	;
1995dh_group_num
1996	:	ALGORITHMTYPE
1997		{
1998			$$ = algtype2doi(algclass_isakmp_dh, $1);
1999			if ($$ == -1) {
2000				yyerror("must be DH group");
2001				return -1;
2002			}
2003		}
2004	|	NUMBER
2005		{
2006			if (ARRAYLEN(num2dhgroup) > $1 && num2dhgroup[$1] != 0) {
2007				$$ = num2dhgroup[$1];
2008			} else {
2009				yyerror("must be DH group");
2010				$$ = 0;
2011				return -1;
2012			}
2013		}
2014	;
2015identifierstring
2016	:	/* nothing */ { $$ = NULL; }
2017	|	ADDRSTRING { $$ = $1; }
2018	|	QUOTEDSTRING { $$ = $1; }
2019	;
2020isakmpproposal_specs
2021	:	/* nothing */
2022	|	isakmpproposal_specs isakmpproposal_spec
2023	;
2024isakmpproposal_spec
2025	:	STRENGTH
2026		{
2027			yyerror("strength directive is obsoleted.");
2028		} STRENGTHTYPE EOS
2029	|	LIFETIME LIFETYPE_TIME NUMBER unittype_time
2030		{
2031			cur_rmconf->prhead->spspec->lifetime = $3 * $4;
2032		}
2033		EOS
2034	|	LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
2035		{
2036#if 1
2037			yyerror("byte lifetime support is deprecated");
2038			return -1;
2039#else
2040			cur_rmconf->prhead->spspec->lifebyte = fix_lifebyte($3 * $4);
2041			if (cur_rmconf->prhead->spspec->lifebyte == 0)
2042				return -1;
2043#endif
2044		}
2045		EOS
2046	|	DH_GROUP dh_group_num
2047		{
2048			cur_rmconf->prhead->spspec->algclass[algclass_isakmp_dh] = $2;
2049		}
2050		EOS
2051	|	GSS_ID QUOTEDSTRING
2052		{
2053			if (cur_rmconf->prhead->spspec->vendorid != VENDORID_GSSAPI) {
2054				yyerror("wrong Vendor ID for gssapi_id");
2055				return -1;
2056			}
2057			if (cur_rmconf->prhead->spspec->gssid != NULL)
2058				racoon_free(cur_rmconf->prhead->spspec->gssid);
2059			cur_rmconf->prhead->spspec->gssid =
2060			    racoon_strdup($2->v);
2061			STRDUP_FATAL(cur_rmconf->prhead->spspec->gssid);
2062		}
2063		EOS
2064	|	ALGORITHM_CLASS ALGORITHMTYPE keylength
2065		{
2066			int doi;
2067			int defklen;
2068
2069			doi = algtype2doi($1, $2);
2070			if (doi == -1) {
2071				yyerror("algorithm mismatched 1");
2072				return -1;
2073			}
2074
2075			switch ($1) {
2076			case algclass_isakmp_enc:
2077			/* reject suppressed algorithms */
2078#ifndef HAVE_OPENSSL_RC5_H
2079				if ($2 == algtype_rc5) {
2080					yyerror("algorithm %s not supported",
2081					    s_attr_isakmp_enc(doi));
2082					return -1;
2083				}
2084#endif
2085#ifndef HAVE_OPENSSL_IDEA_H
2086				if ($2 == algtype_idea) {
2087					yyerror("algorithm %s not supported",
2088					    s_attr_isakmp_enc(doi));
2089					return -1;
2090				}
2091#endif
2092
2093				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_enc] = doi;
2094				defklen = default_keylen($1, $2);
2095				if (defklen == 0) {
2096					if ($3) {
2097						yyerror("keylen not allowed");
2098						return -1;
2099					}
2100				} else {
2101					if ($3 && check_keylen($1, $2, $3) < 0) {
2102						yyerror("invalid keylen %d", $3);
2103						return -1;
2104					}
2105				}
2106				if ($3)
2107					cur_rmconf->prhead->spspec->encklen = $3;
2108				else
2109					cur_rmconf->prhead->spspec->encklen = defklen;
2110				break;
2111			case algclass_isakmp_hash:
2112				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_hash] = doi;
2113				break;
2114			case algclass_isakmp_ameth:
2115				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_ameth] = doi;
2116				/*
2117				 * We may have to set the Vendor ID for the
2118				 * authentication method we're using.
2119				 */
2120				switch ($2) {
2121				case algtype_gssapikrb:
2122					if (cur_rmconf->prhead->spspec->vendorid !=
2123					    VENDORID_UNKNOWN) {
2124						yyerror("Vendor ID mismatch "
2125						    "for auth method");
2126						return -1;
2127					}
2128					/*
2129					 * For interoperability with Win2k,
2130					 * we set the Vendor ID to "GSSAPI".
2131					 */
2132					cur_rmconf->prhead->spspec->vendorid =
2133					    VENDORID_GSSAPI;
2134					break;
2135				case algtype_rsasig:
2136					if (cur_rmconf->certtype == ISAKMP_CERT_PLAINRSA) {
2137						if (rsa_list_count(cur_rmconf->rsa_private) == 0) {
2138							yyerror ("Private PlainRSA key not set. "
2139								"Use directive 'certificate_type plainrsa ...'\n");
2140							return -1;
2141						}
2142						if (rsa_list_count(cur_rmconf->rsa_public) == 0) {
2143							yyerror ("Public PlainRSA keys not set. "
2144								"Use directive 'peers_certfile plainrsa ...'\n");
2145							return -1;
2146						}
2147					}
2148					break;
2149				default:
2150					break;
2151				}
2152				break;
2153			default:
2154				yyerror("algorithm mismatched 2");
2155				return -1;
2156			}
2157		}
2158		EOS
2159	;
2160
2161unittype_time
2162	:	UNITTYPE_SEC	{ $$ = 1; }
2163	|	UNITTYPE_MIN	{ $$ = 60; }
2164	|	UNITTYPE_HOUR	{ $$ = (60 * 60); }
2165	;
2166unittype_byte
2167	:	UNITTYPE_BYTE	{ $$ = 1; }
2168	|	UNITTYPE_KBYTES	{ $$ = 1024; }
2169	|	UNITTYPE_MBYTES	{ $$ = (1024 * 1024); }
2170	|	UNITTYPE_TBYTES	{ $$ = (1024 * 1024 * 1024); }
2171	;
2172%%
2173
2174static struct proposalspec *
2175newprspec()
2176{
2177	struct proposalspec *new;
2178
2179	new = racoon_calloc(1, sizeof(*new));
2180	if (new == NULL)
2181		yyerror("failed to allocate proposal");
2182
2183	return new;
2184}
2185
2186/*
2187 * insert into head of list.
2188 */
2189static void
2190insprspec(prspec, head)
2191	struct proposalspec *prspec;
2192	struct proposalspec **head;
2193{
2194	if (*head != NULL)
2195		(*head)->prev = prspec;
2196	prspec->next = *head;
2197	*head = prspec;
2198}
2199
2200static struct secprotospec *
2201newspspec()
2202{
2203	struct secprotospec *new;
2204
2205	new = racoon_calloc(1, sizeof(*new));
2206	if (new == NULL) {
2207		yyerror("failed to allocate spproto");
2208		return NULL;
2209	}
2210
2211	new->encklen = 0;	/*XXX*/
2212
2213	/*
2214	 * Default to "uknown" vendor -- we will override this
2215	 * as necessary.  When we send a Vendor ID payload, an
2216	 * "unknown" will be translated to a KAME/racoon ID.
2217	 */
2218	new->vendorid = VENDORID_UNKNOWN;
2219
2220	return new;
2221}
2222
2223/*
2224 * insert into head of list.
2225 */
2226static void
2227insspspec(spspec, head)
2228	struct secprotospec *spspec;
2229	struct proposalspec **head;
2230{
2231	spspec->back = *head;
2232
2233	if ((*head)->spspec != NULL)
2234		(*head)->spspec->prev = spspec;
2235	spspec->next = (*head)->spspec;
2236	(*head)->spspec = spspec;
2237}
2238
2239/* set final acceptable proposal */
2240static int
2241set_isakmp_proposal(rmconf, prspec)
2242	struct remoteconf *rmconf;
2243	struct proposalspec *prspec;
2244{
2245	struct proposalspec *p;
2246	struct secprotospec *s;
2247	int prop_no = 1;
2248	int trns_no = 1;
2249	int32_t types[MAXALGCLASS];
2250
2251	p = prspec;
2252	if (p->next != 0) {
2253		plog(LLV_ERROR, LOCATION, NULL,
2254			"multiple proposal definition.\n");
2255		return -1;
2256	}
2257
2258	/* mandatory check */
2259	if (p->spspec == NULL) {
2260		yyerror("no remote specification found: %s.\n",
2261			saddr2str(rmconf->remote));
2262		return -1;
2263	}
2264	for (s = p->spspec; s != NULL; s = s->next) {
2265		/* XXX need more to check */
2266		if (s->algclass[algclass_isakmp_enc] == 0) {
2267			yyerror("encryption algorithm required.");
2268			return -1;
2269		}
2270		if (s->algclass[algclass_isakmp_hash] == 0) {
2271			yyerror("hash algorithm required.");
2272			return -1;
2273		}
2274		if (s->algclass[algclass_isakmp_dh] == 0) {
2275			yyerror("DH group required.");
2276			return -1;
2277		}
2278		if (s->algclass[algclass_isakmp_ameth] == 0) {
2279			yyerror("authentication method required.");
2280			return -1;
2281		}
2282	}
2283
2284	/* skip to last part */
2285	for (s = p->spspec; s->next != NULL; s = s->next)
2286		;
2287
2288	while (s != NULL) {
2289		plog(LLV_DEBUG2, LOCATION, NULL,
2290			"lifetime = %ld\n", (long)
2291			(s->lifetime ? s->lifetime : p->lifetime));
2292		plog(LLV_DEBUG2, LOCATION, NULL,
2293			"lifebyte = %d\n",
2294			s->lifebyte ? s->lifebyte : p->lifebyte);
2295		plog(LLV_DEBUG2, LOCATION, NULL,
2296			"encklen=%d\n", s->encklen);
2297
2298		memset(types, 0, ARRAYLEN(types));
2299		types[algclass_isakmp_enc] = s->algclass[algclass_isakmp_enc];
2300		types[algclass_isakmp_hash] = s->algclass[algclass_isakmp_hash];
2301		types[algclass_isakmp_dh] = s->algclass[algclass_isakmp_dh];
2302		types[algclass_isakmp_ameth] =
2303		    s->algclass[algclass_isakmp_ameth];
2304
2305		/* expanding spspec */
2306		clean_tmpalgtype();
2307		trns_no = expand_isakmpspec(prop_no, trns_no, types,
2308				algclass_isakmp_enc, algclass_isakmp_ameth + 1,
2309				s->lifetime ? s->lifetime : p->lifetime,
2310				s->lifebyte ? s->lifebyte : p->lifebyte,
2311				s->encklen, s->vendorid, s->gssid,
2312				rmconf);
2313		if (trns_no == -1) {
2314			plog(LLV_ERROR, LOCATION, NULL,
2315				"failed to expand isakmp proposal.\n");
2316			return -1;
2317		}
2318
2319		s = s->prev;
2320	}
2321
2322	if (rmconf->proposal == NULL) {
2323		plog(LLV_ERROR, LOCATION, NULL,
2324			"no proposal found.\n");
2325		return -1;
2326	}
2327
2328	return 0;
2329}
2330
2331static void
2332clean_tmpalgtype()
2333{
2334	int i;
2335	for (i = 0; i < MAXALGCLASS; i++)
2336		tmpalgtype[i] = 0;	/* means algorithm undefined. */
2337}
2338
2339static int
2340expand_isakmpspec(prop_no, trns_no, types,
2341		class, last, lifetime, lifebyte, encklen, vendorid, gssid,
2342		rmconf)
2343	int prop_no, trns_no;
2344	int *types, class, last;
2345	time_t lifetime;
2346	int lifebyte;
2347	int encklen;
2348	int vendorid;
2349	char *gssid;
2350	struct remoteconf *rmconf;
2351{
2352	struct isakmpsa *new;
2353
2354	/* debugging */
2355    {
2356	int j;
2357	char tb[10];
2358	plog(LLV_DEBUG2, LOCATION, NULL,
2359		"p:%d t:%d\n", prop_no, trns_no);
2360	for (j = class; j < MAXALGCLASS; j++) {
2361		snprintf(tb, sizeof(tb), "%d", types[j]);
2362		plog(LLV_DEBUG2, LOCATION, NULL,
2363			"%s%s%s%s\n",
2364			s_algtype(j, types[j]),
2365			types[j] ? "(" : "",
2366			tb[0] == '0' ? "" : tb,
2367			types[j] ? ")" : "");
2368	}
2369	plog(LLV_DEBUG2, LOCATION, NULL, "\n");
2370    }
2371
2372#define TMPALGTYPE2STR(n) \
2373	s_algtype(algclass_isakmp_##n, types[algclass_isakmp_##n])
2374		/* check mandatory values */
2375		if (types[algclass_isakmp_enc] == 0
2376		 || types[algclass_isakmp_ameth] == 0
2377		 || types[algclass_isakmp_hash] == 0
2378		 || types[algclass_isakmp_dh] == 0) {
2379			yyerror("few definition of algorithm "
2380				"enc=%s ameth=%s hash=%s dhgroup=%s.\n",
2381				TMPALGTYPE2STR(enc),
2382				TMPALGTYPE2STR(ameth),
2383				TMPALGTYPE2STR(hash),
2384				TMPALGTYPE2STR(dh));
2385			return -1;
2386		}
2387#undef TMPALGTYPE2STR
2388
2389	/* set new sa */
2390	new = newisakmpsa();
2391	if (new == NULL) {
2392		yyerror("failed to allocate isakmp sa");
2393		return -1;
2394	}
2395	new->prop_no = prop_no;
2396	new->trns_no = trns_no++;
2397	new->lifetime = lifetime;
2398	new->lifebyte = lifebyte;
2399	new->enctype = types[algclass_isakmp_enc];
2400	new->encklen = encklen;
2401	new->authmethod = types[algclass_isakmp_ameth];
2402	new->hashtype = types[algclass_isakmp_hash];
2403	new->dh_group = types[algclass_isakmp_dh];
2404	new->vendorid = vendorid;
2405#ifdef HAVE_GSSAPI
2406	if (new->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
2407		if (gssid != NULL) {
2408			if ((new->gssid = vmalloc(strlen(gssid))) == NULL) {
2409				racoon_free(new);
2410				yyerror("failed to allocate gssid");
2411				return -1;
2412			}
2413			memcpy(new->gssid->v, gssid, new->gssid->l);
2414			racoon_free(gssid);
2415#ifdef ENABLE_HYBRID
2416		} else if (rmconf->xauth == NULL) {
2417#else
2418		} else {
2419#endif
2420			/*
2421			 * Allocate the default ID so that it gets put
2422			 * into a GSS ID attribute during the Phase 1
2423			 * exchange.
2424			 */
2425			new->gssid = gssapi_get_default_gss_id();
2426		}
2427	}
2428#endif
2429	insisakmpsa(new, rmconf);
2430
2431	return trns_no;
2432}
2433
2434static int
2435listen_addr (struct sockaddr *addr, int udp_encap)
2436{
2437	struct myaddrs *p;
2438
2439	p = newmyaddr();
2440	if (p == NULL) {
2441		yyerror("failed to allocate myaddrs");
2442		return -1;
2443	}
2444	p->addr = addr;
2445	if (p->addr == NULL) {
2446		yyerror("failed to copy sockaddr ");
2447		delmyaddr(p);
2448		return -1;
2449	}
2450	p->udp_encap = udp_encap;
2451
2452	insmyaddr(p, &lcconf->myaddrs);
2453
2454	lcconf->autograbaddr = 0;
2455	return 0;
2456}
2457
2458#if 0
2459/*
2460 * fix lifebyte.
2461 * Must be more than 1024B because its unit is kilobytes.
2462 * That is defined RFC2407.
2463 */
2464static int
2465fix_lifebyte(t)
2466	unsigned long t;
2467{
2468	if (t < 1024) {
2469		yyerror("byte size should be more than 1024B.");
2470		return 0;
2471	}
2472
2473	return(t / 1024);
2474}
2475#endif
2476
2477int
2478cfparse()
2479{
2480	int error;
2481
2482	yycf_init_buffer();
2483
2484	if (yycf_switch_buffer(lcconf->racoon_conf) != 0) {
2485		plog(LLV_ERROR, LOCATION, NULL,
2486		    "could not read configuration file \"%s\"\n",
2487		    lcconf->racoon_conf);
2488		return -1;
2489	}
2490
2491	error = yyparse();
2492	if (error != 0) {
2493		if (yyerrorcount) {
2494			plog(LLV_ERROR, LOCATION, NULL,
2495				"fatal parse failure (%d errors)\n",
2496				yyerrorcount);
2497		} else {
2498			plog(LLV_ERROR, LOCATION, NULL,
2499				"fatal parse failure.\n");
2500		}
2501		return -1;
2502	}
2503
2504	if (error == 0 && yyerrorcount) {
2505		plog(LLV_ERROR, LOCATION, NULL,
2506			"parse error is nothing, but yyerrorcount is %d.\n",
2507				yyerrorcount);
2508		exit(1);
2509	}
2510
2511	yycf_clean_buffer();
2512
2513	plog(LLV_DEBUG2, LOCATION, NULL, "parse successed.\n");
2514
2515	return 0;
2516}
2517
2518int
2519cfreparse()
2520{
2521	flushph2();
2522	flushph1();
2523	flushrmconf();
2524	flushsainfo();
2525	clean_tmpalgtype();
2526	return(cfparse());
2527}
2528
2529#ifdef ENABLE_ADMINPORT
2530static void
2531adminsock_conf(path, owner, group, mode_dec)
2532	vchar_t *path;
2533	vchar_t *owner;
2534	vchar_t *group;
2535	int mode_dec;
2536{
2537	struct passwd *pw = NULL;
2538	struct group *gr = NULL;
2539	mode_t mode = 0;
2540	uid_t uid;
2541	gid_t gid;
2542	int isnum;
2543
2544	adminsock_path = path->v;
2545
2546	if (owner == NULL)
2547		return;
2548
2549	errno = 0;
2550	uid = atoi(owner->v);
2551	isnum = !errno;
2552	if (((pw = getpwnam(owner->v)) == NULL) && !isnum)
2553		yyerror("User \"%s\" does not exist", owner->v);
2554
2555	if (pw)
2556		adminsock_owner = pw->pw_uid;
2557	else
2558		adminsock_owner = uid;
2559
2560	if (group == NULL)
2561		return;
2562
2563	errno = 0;
2564	gid = atoi(group->v);
2565	isnum = !errno;
2566	if (((gr = getgrnam(group->v)) == NULL) && !isnum)
2567		yyerror("Group \"%s\" does not exist", group->v);
2568
2569	if (gr)
2570		adminsock_group = gr->gr_gid;
2571	else
2572		adminsock_group = gid;
2573
2574	if (mode_dec == -1)
2575		return;
2576
2577	if (mode_dec > 777)
2578		yyerror("Mode 0%03o is invalid", mode_dec);
2579	if (mode_dec >= 400) { mode += 0400; mode_dec -= 400; }
2580	if (mode_dec >= 200) { mode += 0200; mode_dec -= 200; }
2581	if (mode_dec >= 100) { mode += 0200; mode_dec -= 100; }
2582
2583	if (mode_dec > 77)
2584		yyerror("Mode 0%03o is invalid", mode_dec);
2585	if (mode_dec >= 40) { mode += 040; mode_dec -= 40; }
2586	if (mode_dec >= 20) { mode += 020; mode_dec -= 20; }
2587	if (mode_dec >= 10) { mode += 020; mode_dec -= 10; }
2588
2589	if (mode_dec > 7)
2590		yyerror("Mode 0%03o is invalid", mode_dec);
2591	if (mode_dec >= 4) { mode += 04; mode_dec -= 4; }
2592	if (mode_dec >= 2) { mode += 02; mode_dec -= 2; }
2593	if (mode_dec >= 1) { mode += 02; mode_dec -= 1; }
2594
2595	adminsock_mode = mode;
2596
2597	return;
2598}
2599#endif
2600