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