1/*	$NetBSD: remoteconf.c,v 1.27 2012/01/01 15:29:28 tteras Exp $	*/
2
3/* Id: remoteconf.c,v 1.38 2006/05/06 15:52:44 manubsd Exp */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/socket.h>
39#include <sys/queue.h>
40
41#include <netinet/in.h>
42#include <netinet/in_systm.h>
43#include <netinet/ip.h>
44
45#include PATH_IPSEC_H
46
47#include <stdlib.h>
48#include <stdio.h>
49#include <string.h>
50#include <errno.h>
51
52#include "var.h"
53#include "misc.h"
54#include "vmbuf.h"
55#include "plog.h"
56#include "sockmisc.h"
57#include "genlist.h"
58#include "debug.h"
59
60#include "isakmp_var.h"
61#ifdef ENABLE_HYBRID
62#include "isakmp_xauth.h"
63#endif
64#include "isakmp.h"
65#include "ipsec_doi.h"
66#include "crypto_openssl.h"
67#include "oakley.h"
68#include "remoteconf.h"
69#include "localconf.h"
70#include "grabmyaddr.h"
71#include "policy.h"
72#include "proposal.h"
73#include "vendorid.h"
74#include "gcmalloc.h"
75#include "strnames.h"
76#include "algorithm.h"
77#include "nattraversal.h"
78#include "isakmp_frag.h"
79#include "handler.h"
80#include "genlist.h"
81#include "rsalist.h"
82
83typedef TAILQ_HEAD(_rmtree, remoteconf) remoteconf_tailq_head_t;
84static remoteconf_tailq_head_t rmtree, rmtree_save;
85
86/*
87 * Script hook names and script hook paths
88 */
89char *script_names[SCRIPT_MAX + 1] = {
90	"phase1_up", "phase1_down", "phase1_dead" };
91
92/*%%%*/
93
94int
95rmconf_match_identity(rmconf, id_p)
96	struct remoteconf *rmconf;
97	vchar_t *id_p;
98{
99	struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *) id_p->v;
100	struct sockaddr *sa;
101	caddr_t sa1, sa2;
102	vchar_t ident;
103	struct idspec *id;
104	struct genlist_entry *gpb;
105
106	/* compare with the ID if specified. */
107	if (!genlist_next(rmconf->idvl_p, 0))
108		return 0;
109
110	for (id = genlist_next(rmconf->idvl_p, &gpb); id; id = genlist_next(0, &gpb)) {
111		/* No ID specified in configuration, so it is ok */
112		if (id->id == 0)
113			return 0;
114
115		/* check the type of both IDs */
116		if (id->idtype != doi2idtype(id_b->type))
117			continue;  /* ID type mismatch */
118
119		/* compare defined ID with the ID sent by peer. */
120		switch (id->idtype) {
121		case IDTYPE_ASN1DN:
122			ident.v = id_p->v + sizeof(*id_b);
123			ident.l = id_p->l - sizeof(*id_b);
124			if (eay_cmp_asn1dn(id->id, &ident) == 0)
125				return 0;
126			break;
127		case IDTYPE_ADDRESS:
128			sa = (struct sockaddr *)id->id->v;
129			sa2 = (caddr_t)(id_b + 1);
130			switch (sa->sa_family) {
131			case AF_INET:
132				if (id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
133					continue;  /* ID value mismatch */
134				sa1 = (caddr_t) &((struct sockaddr_in *)sa)->sin_addr;
135				if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
136					return 0;
137				break;
138#ifdef INET6
139			case AF_INET6:
140				if (id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
141					continue;  /* ID value mismatch */
142				sa1 = (caddr_t) &((struct sockaddr_in6 *)sa)->sin6_addr;
143				if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
144					return 0;
145				break;
146#endif
147			default:
148				break;
149			}
150			break;
151		default:
152			if (memcmp(id->id->v, id_b + 1, id->id->l) == 0)
153				return 0;
154			break;
155		}
156	}
157
158	plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
159	if (rmconf->verify_identifier)
160		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
161
162	return 0;
163}
164
165static int
166rmconf_match_etype_and_approval(rmconf, etype, approval)
167	struct remoteconf *rmconf;
168	int etype;
169	struct isakmpsa *approval;
170{
171	struct isakmpsa *p;
172
173	if (check_etypeok(rmconf, (void *) (intptr_t) etype) == 0)
174		return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
175
176	if (approval == NULL)
177		return 0;
178
179	if (etype == ISAKMP_ETYPE_AGG &&
180	    approval->dh_group != rmconf->dh_group)
181		return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
182
183	if (checkisakmpsa(rmconf->pcheck_level, approval,
184			  rmconf->proposal) == NULL)
185		return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
186
187	return 0;
188}
189
190enum rmconf_match_t {
191	MATCH_NONE		= 0,
192	MATCH_BASIC		= 0x0000001,
193	MATCH_ADDRESS		= 0x0000002,
194	MATCH_SA		= 0x0000004,
195	MATCH_IDENTITY		= 0x0000008,
196	MATCH_AUTH_IDENTITY	= 0x0000010,
197};
198
199static int
200rmconf_match_type(rmsel, rmconf)
201	struct rmconfselector *rmsel;
202	struct remoteconf *rmconf;
203{
204	int ret = MATCH_NONE, tmp;
205
206	/* No match at all: unwanted anonymous */
207	if ((rmsel->flags & GETRMCONF_F_NO_ANONYMOUS) &&
208	    rmconf->remote->sa_family == AF_UNSPEC){
209		plog(LLV_DEBUG2, LOCATION, rmsel->remote,
210		     "Not matched: Anonymous conf.\n");
211		return MATCH_NONE;
212	}
213
214	if ((rmsel->flags & GETRMCONF_F_NO_PASSIVE) && rmconf->passive){
215		plog(LLV_DEBUG2, LOCATION, rmsel->remote,
216		     "Not matched: passive conf.\n");
217		return MATCH_NONE;
218	}
219
220	ret |= MATCH_BASIC;
221
222	/* Check address */
223	if (rmsel->remote != NULL) {
224		if (rmconf->remote->sa_family != AF_UNSPEC) {
225			if (cmpsaddr(rmsel->remote, rmconf->remote) == CMPSADDR_MISMATCH){
226				plog(LLV_DEBUG2, LOCATION, rmsel->remote,
227				     "Not matched: address mismatch.\n");
228				return MATCH_NONE;
229			}
230
231			/* Address matched */
232			ret |= MATCH_ADDRESS;
233		}
234	}
235
236	/* Check etype and approval */
237	if (rmsel->etype != ISAKMP_ETYPE_NONE) {
238		tmp=rmconf_match_etype_and_approval(rmconf, rmsel->etype,
239						    rmsel->approval);
240		if (tmp != 0){
241			plog(LLV_DEBUG2, LOCATION, rmsel->remote,
242			     "Not matched: etype (%d)/approval mismatch (%d).\n", rmsel->etype, tmp);
243			return MATCH_NONE;
244		}
245		ret |= MATCH_SA;
246	}
247
248	/* Check identity */
249	if (rmsel->identity != NULL && rmconf->verify_identifier) {
250		if (rmconf_match_identity(rmconf, rmsel->identity) != 0){
251			plog(LLV_DEBUG2, LOCATION, rmsel->remote,
252			     "Not matched: identity mismatch.\n");
253			return MATCH_NONE;
254		}
255		ret |= MATCH_IDENTITY;
256	}
257
258	/* Check certificate request */
259	if (rmsel->certificate_request != NULL) {
260		if (oakley_get_certtype(rmsel->certificate_request) !=
261		    oakley_get_certtype(rmconf->mycert)){
262			plog(LLV_DEBUG2, LOCATION, rmsel->remote,
263			     "Not matched: cert type mismatch.\n");
264			return MATCH_NONE;
265		}
266
267		if (rmsel->certificate_request->l > 1) {
268			vchar_t *issuer;
269
270			issuer = eay_get_x509asn1issuername(rmconf->mycert);
271			if (rmsel->certificate_request->l - 1 != issuer->l ||
272			    memcmp(rmsel->certificate_request->v + 1,
273				   issuer->v, issuer->l) != 0) {
274				vfree(issuer);
275				plog(LLV_DEBUG2, LOCATION, rmsel->remote,
276				     "Not matched: cert issuer mismatch.\n");
277				return MATCH_NONE;
278			}
279			vfree(issuer);
280		} else {
281			if (!rmconf->match_empty_cr){
282				plog(LLV_DEBUG2, LOCATION, rmsel->remote,
283				     "Not matched: empty certificate request.\n");
284				return MATCH_NONE;
285			}
286		}
287
288		ret |= MATCH_AUTH_IDENTITY;
289	}
290
291	return ret;
292}
293
294void rmconf_selector_from_ph1(rmsel, iph1)
295	struct rmconfselector *rmsel;
296	struct ph1handle *iph1;
297{
298	memset(rmsel, 0, sizeof(*rmsel));
299	rmsel->flags = 0;
300	rmsel->remote = iph1->remote;
301	rmsel->etype = iph1->etype;
302	rmsel->approval = iph1->approval;
303	rmsel->identity = iph1->id_p;
304	rmsel->certificate_request = iph1->cr_p;
305}
306
307int
308enumrmconf(rmsel, enum_func, enum_arg)
309	struct rmconfselector *rmsel;
310	int (* enum_func)(struct remoteconf *rmconf, void *arg);
311	void *enum_arg;
312{
313	struct remoteconf *p;
314	int ret = 0;
315
316	RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
317		plog(LLV_DEBUG2, LOCATION, rmsel->remote,
318		     "Checking remote conf \"%s\" %s.\n", p->name,
319		     p->remote->sa_family == AF_UNSPEC ?
320		     "anonymous" : saddr2str(p->remote));
321
322		if (rmsel != NULL) {
323			if (rmconf_match_type(rmsel, p) == MATCH_NONE){
324				plog(LLV_DEBUG2, LOCATION, rmsel->remote,
325				     "Not matched.\n");
326				continue;
327			}
328		}
329
330		plog(LLV_DEBUG2, LOCATION, NULL,
331		     "enumrmconf: \"%s\" matches.\n", p->name);
332
333		ret = (*enum_func)(p, enum_arg);
334		if (ret)
335			break;
336	}
337
338	return ret;
339}
340
341struct rmconf_find_context {
342	struct rmconfselector sel;
343
344	struct remoteconf *rmconf;
345	int match_type;
346	int num_found;
347};
348
349static int
350rmconf_find(rmconf, ctx)
351	struct remoteconf *rmconf;
352	void *ctx;
353{
354	struct rmconf_find_context *fctx = (struct rmconf_find_context *) ctx;
355	int match_type;
356
357	/* First matching remote conf? */
358	match_type = rmconf_match_type(&fctx->sel, rmconf);
359
360	if (fctx->rmconf != NULL) {
361		/* More ambiguous matches are ignored. */
362		if (match_type < fctx->match_type)
363			return 0;
364
365		if (match_type == fctx->match_type) {
366			/* Ambiguous match */
367			fctx->num_found++;
368			return 0;
369		}
370	}
371
372	/* More exact match found */
373	fctx->match_type = match_type;
374	fctx->num_found = 1;
375	fctx->rmconf = rmconf;
376
377	return 0;
378}
379
380/*
381 * search remote configuration.
382 * don't use port number to search if its value is either IPSEC_PORT_ANY.
383 * If matching anonymous entry, then new entry is copied from anonymous entry.
384 * If no anonymous entry found, then return NULL.
385 * OUT:	NULL:	NG
386 *	Other:	remote configuration entry.
387 */
388
389struct remoteconf *
390getrmconf(remote, flags)
391	struct sockaddr *remote;
392	int flags;
393{
394	struct rmconf_find_context ctx;
395	int n = 0;
396
397	memset(&ctx, 0, sizeof(ctx));
398	ctx.sel.flags = flags;
399	ctx.sel.remote = remote;
400
401	if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
402		plog(LLV_ERROR, LOCATION, remote,
403		     "multiple exact configurations.\n");
404		return NULL;
405	}
406
407	if (ctx.rmconf == NULL) {
408		plog(LLV_DEBUG, LOCATION, remote,
409		     "no remote configuration found.\n");
410		return NULL;
411	}
412
413	if (ctx.num_found != 1) {
414		plog(LLV_DEBUG, LOCATION, remote,
415		     "multiple non-exact configurations found.\n");
416		return NULL;
417	}
418
419	plog(LLV_DEBUG, LOCATION, remote,
420	     "configuration \"%s\" selected.\n",
421	     ctx.rmconf->name);
422
423	return ctx.rmconf;
424}
425
426struct remoteconf *
427getrmconf_by_ph1(iph1)
428	struct ph1handle *iph1;
429{
430	struct rmconf_find_context ctx;
431
432	memset(&ctx, 0, sizeof(ctx));
433	rmconf_selector_from_ph1(&ctx.sel, iph1);
434	if (loglevel >= LLV_DEBUG) {
435		char *idstr = NULL;
436
437		if (iph1->id_p != NULL)
438			idstr = ipsecdoi_id2str(iph1->id_p);
439
440		plog(LLV_DEBUG, LOCATION, iph1->remote,
441			"getrmconf_by_ph1: remote %s, identity %s.\n",
442			saddr2str(iph1->remote), idstr ? idstr : "<any>");
443
444		if (idstr)
445			racoon_free(idstr);
446	}
447
448	if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
449		plog(LLV_ERROR, LOCATION, iph1->remote,
450		     "multiple exact configurations.\n");
451		return RMCONF_ERR_MULTIPLE;
452	}
453
454	if (ctx.rmconf == NULL) {
455		plog(LLV_DEBUG, LOCATION, iph1->remote,
456		     "no remote configuration found\n");
457		return NULL;
458	}
459
460	if (ctx.num_found != 1) {
461		plog(LLV_DEBUG, LOCATION, iph1->remote,
462		     "multiple non-exact configurations found.\n");
463		return RMCONF_ERR_MULTIPLE;
464	}
465
466	plog(LLV_DEBUG, LOCATION, iph1->remote,
467	     "configuration \"%s\" selected.\n",
468	     ctx.rmconf->name);
469
470	return ctx.rmconf;
471}
472
473struct remoteconf *
474getrmconf_by_name(name)
475	const char *name;
476{
477	struct remoteconf *p;
478
479	plog(LLV_DEBUG, LOCATION, NULL,
480	     "getrmconf_by_name: remote \"%s\".\n",
481	     name);
482
483	RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
484		if (p->name == NULL)
485			continue;
486
487		if (strcmp(name, p->name) == 0)
488			return p;
489	}
490
491	return NULL;
492}
493
494struct remoteconf *
495newrmconf()
496{
497	struct remoteconf *new;
498	int i;
499
500	new = racoon_calloc(1, sizeof(*new));
501	if (new == NULL)
502		return NULL;
503
504	new->proposal = NULL;
505
506	/* set default */
507	new->doitype = IPSEC_DOI;
508	new->sittype = IPSECDOI_SIT_IDENTITY_ONLY;
509	new->idvtype = IDTYPE_UNDEFINED;
510	new->idvl_p = genlist_init();
511	new->nonce_size = DEFAULT_NONCE_SIZE;
512	new->passive = FALSE;
513	new->ike_frag = FALSE;
514	new->esp_frag = IP_MAXPACKET;
515	new->ini_contact = TRUE;
516	new->mode_cfg = FALSE;
517	new->pcheck_level = PROP_CHECK_STRICT;
518	new->verify_identifier = FALSE;
519	new->verify_cert = TRUE;
520	new->cacertfile = NULL;
521	new->send_cert = TRUE;
522	new->send_cr = TRUE;
523	new->match_empty_cr = FALSE;
524	new->support_proxy = FALSE;
525	for (i = 0; i <= SCRIPT_MAX; i++)
526		new->script[i] = NULL;
527	new->gen_policy = FALSE;
528	new->nat_traversal = FALSE;
529	new->rsa_private = genlist_init();
530	new->rsa_public = genlist_init();
531	new->idv = NULL;
532	new->key = NULL;
533
534	new->dpd = TRUE; /* Enable DPD support by default */
535	new->dpd_interval = 0; /* Disable DPD checks by default */
536	new->dpd_retry = 5;
537	new->dpd_maxfails = 5;
538
539	new->rekey = REKEY_ON;
540
541	new->weak_phase1_check = 0;
542
543#ifdef ENABLE_HYBRID
544	new->xauth = NULL;
545#endif
546
547	new->lifetime = oakley_get_defaultlifetime();
548
549	return new;
550}
551
552void *
553dupidvl(entry, arg)
554	void *entry;
555	void *arg;
556{
557	struct idspec *id;
558	struct idspec *old = (struct idspec *) entry;
559	id = newidspec();
560	if (!id) return (void *) -1;
561
562	if (set_identifier(&id->id, old->idtype, old->id) != 0) {
563		racoon_free(id);
564		return (void *) -1;
565	}
566
567	id->idtype = old->idtype;
568
569	genlist_append(arg, id);
570	return NULL;
571}
572
573void *
574duprsa(entry, arg)
575	void *entry;
576	void *arg;
577{
578	struct rsa_key *new;
579
580	new = rsa_key_dup((struct rsa_key *)entry);
581	if (new == NULL)
582		return (void *) -1;
583	genlist_append(arg, new);
584
585	/* keep genlist_foreach going */
586	return NULL;
587}
588
589/* Creates shallow copy of a remote config. Used for "inherit" keyword. */
590struct remoteconf *
591duprmconf_shallow (rmconf)
592	struct remoteconf *rmconf;
593{
594	struct remoteconf *new;
595	struct proposalspec *prspec;
596
597	new = racoon_calloc(1, sizeof(*new));
598	if (new == NULL)
599		return NULL;
600
601	memcpy(new, rmconf, sizeof(*new));
602	new->name = NULL;
603	new->inherited_from = rmconf;
604
605	new->proposal = NULL; /* will be filled by set_isakmp_proposal() */
606
607	/* Better to set remote to NULL to avoid that the destination
608	 * rmconf uses the same allocated memory as the source rmconf.
609	 */
610	new->remote = NULL;
611
612	return new;
613}
614
615/* Copies pointer structures of an inherited remote config.
616 * Used by "inherit" mechanism in a two step copy method, necessary to
617 * prevent both double free() and memory leak during config reload.
618 */
619int
620duprmconf_finish (new)
621	struct remoteconf *new;
622{
623	struct remoteconf *rmconf;
624	int i;
625
626	if (new->inherited_from == NULL)
627		return 0; /* nothing todo, no inheritance */
628
629	rmconf = new->inherited_from;
630
631	/* duplicate dynamic structures unless value overridden */
632	if (new->etypes != NULL && new->etypes == rmconf->etypes)
633		new->etypes = dupetypes(new->etypes);
634	if (new->idvl_p == rmconf->idvl_p) {
635		new->idvl_p = genlist_init();
636		genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p);
637	}
638
639	if (new->rsa_private == rmconf->rsa_private) {
640		new->rsa_private = genlist_init();
641		genlist_foreach(rmconf->rsa_private, duprsa, new->rsa_private);
642	}
643	if (new->rsa_public == rmconf->rsa_public) {
644		new->rsa_public = genlist_init();
645		genlist_foreach(rmconf->rsa_public, duprsa, new->rsa_public);
646	}
647	if (new->remote != NULL && new->remote == rmconf->remote) {
648		new->remote = racoon_malloc(sizeof(*new->remote));
649		if (new->remote == NULL) {
650			plog(LLV_ERROR, LOCATION, NULL,
651			    "duprmconf_finish: malloc failed (remote)\n");
652			exit(1);
653		}
654		memcpy(new->remote, rmconf->remote, sizeof(*new->remote));
655	}
656	if (new->spspec != NULL && new->spspec == rmconf->spspec) {
657		dupspspec_list(new, rmconf);
658	}
659
660	/* proposal has been deep copied already from spspec's, see
661	 * cfparse.y:set_isakmp_proposal, which in turn calls
662	 * cfparse.y:expand_isakmpspec where the copying happens.
663	 */
664
665#ifdef ENABLE_HYBRID
666	if (new->xauth != NULL && new->xauth == rmconf->xauth) {
667		new->xauth = xauth_rmconf_dup(new->xauth);
668		if (new->xauth == NULL)
669			exit(1);
670	}
671#endif
672
673        /* duplicate strings unless value overridden */
674	if (new->mycertfile != NULL && new->mycertfile == rmconf->mycertfile) {
675		new->mycertfile = racoon_strdup(new->mycertfile);
676		STRDUP_FATAL(new->mycertfile);
677	}
678	if (new->myprivfile != NULL && new->myprivfile == rmconf->myprivfile) {
679		new->myprivfile = racoon_strdup(new->myprivfile);
680		STRDUP_FATAL(new->myprivfile);
681	}
682	if (new->peerscertfile != NULL && new->peerscertfile == rmconf->peerscertfile) {
683		new->peerscertfile = racoon_strdup(new->peerscertfile);
684		STRDUP_FATAL(new->peerscertfile);
685	}
686	if (new->cacertfile != NULL && new->cacertfile == rmconf->cacertfile) {
687		new->cacertfile = racoon_strdup(new->cacertfile);
688		STRDUP_FATAL(new->cacertfile);
689	}
690	if (new->idv != NULL && new->idv == rmconf->idv) {
691		new->idv = vdup(new->idv);
692		STRDUP_FATAL(new->idv);
693	}
694	if (new->key != NULL && new->key == rmconf->key) {
695		new->key = vdup(new->key);
696		STRDUP_FATAL(new->key);
697	}
698	if (new->mycert != NULL && new->mycert == rmconf->mycert) {
699		new->mycert = vdup(new->mycert);
700		STRDUP_FATAL(new->mycert);
701	}
702	if (new->peerscert != NULL && new->peerscert == rmconf->peerscert) {
703		new->peerscert = vdup(new->peerscert);
704		STRDUP_FATAL(new->peerscert);
705	}
706	if (new->cacert != NULL && new->cacert == rmconf->cacert) {
707		new->cacert = vdup(new->cacert);
708		STRDUP_FATAL(new->cacert);
709	}
710	for (i = 0; i <= SCRIPT_MAX; i++)
711		if (new->script[i] != NULL && new->script[i] == rmconf->script[i]) {
712			new->script[i] = vdup(new->script[i]);
713			STRDUP_FATAL(new->script[i]);
714		}
715
716	return 0;
717}
718
719static void
720idspec_free(void *data)
721{
722	vfree (((struct idspec *)data)->id);
723	free (data);
724}
725
726void
727delrmconf(rmconf)
728	struct remoteconf *rmconf;
729{
730	int i;
731
732	if (rmconf == NULL)
733		return;
734
735#ifdef ENABLE_HYBRID
736	if (rmconf->xauth)
737		xauth_rmconf_delete(&rmconf->xauth);
738#endif
739	if (rmconf->etypes){
740		deletypes(rmconf->etypes);
741		rmconf->etypes=NULL;
742	}
743	if (rmconf->idv)
744		vfree(rmconf->idv);
745	if (rmconf->key)
746		vfree(rmconf->key);
747	if (rmconf->idvl_p)
748		genlist_free(rmconf->idvl_p, idspec_free);
749	if (rmconf->dhgrp)
750		oakley_dhgrp_free(rmconf->dhgrp);
751	if (rmconf->proposal)
752		delisakmpsa(rmconf->proposal);
753	flushspspec(rmconf);
754	if (rmconf->mycert)
755		vfree(rmconf->mycert);
756	if (rmconf->mycertfile)
757		racoon_free(rmconf->mycertfile);
758	if (rmconf->myprivfile)
759		racoon_free(rmconf->myprivfile);
760	if (rmconf->peerscert)
761		vfree(rmconf->peerscert);
762	if (rmconf->peerscertfile)
763		racoon_free(rmconf->peerscertfile);
764	if (rmconf->cacert)
765		vfree(rmconf->cacert);
766	if (rmconf->cacertfile)
767		racoon_free(rmconf->cacertfile);
768	if (rmconf->rsa_private)
769		genlist_free(rmconf->rsa_private, rsa_key_free);
770	if (rmconf->rsa_public)
771		genlist_free(rmconf->rsa_public, rsa_key_free);
772	if (rmconf->name)
773		racoon_free(rmconf->name);
774	if (rmconf->remote)
775		racoon_free(rmconf->remote);
776	for (i = 0; i <= SCRIPT_MAX; i++)
777		if (rmconf->script[i])
778			vfree(rmconf->script[i]);
779
780	racoon_free(rmconf);
781}
782
783void
784delisakmpsa(sa)
785	struct isakmpsa *sa;
786{
787	if (sa->dhgrp)
788		oakley_dhgrp_free(sa->dhgrp);
789	if (sa->next)
790		delisakmpsa(sa->next);
791#ifdef HAVE_GSSAPI
792	if (sa->gssid)
793		vfree(sa->gssid);
794#endif
795	racoon_free(sa);
796}
797
798struct etypes *
799dupetypes(orig)
800	struct etypes *orig;
801{
802	struct etypes *new;
803
804	if (!orig)
805		return NULL;
806
807	new = racoon_malloc(sizeof(struct etypes));
808	if (new == NULL)
809		return NULL;
810
811	new->type = orig->type;
812	new->next = NULL;
813
814	if (orig->next)
815		new->next=dupetypes(orig->next);
816
817	return new;
818}
819
820void
821deletypes(e)
822	struct etypes *e;
823{
824	if (e->next)
825		deletypes(e->next);
826	racoon_free(e);
827}
828
829/*
830 * insert into head of list.
831 */
832void
833insrmconf(new)
834	struct remoteconf *new;
835{
836	if (new->name == NULL) {
837		new->name = racoon_strdup(saddr2str(new->remote));
838	}
839	if (new->remote == NULL) {
840		new->remote = newsaddr(sizeof(struct sockaddr));
841		new->remote->sa_family = AF_UNSPEC;
842	}
843
844	TAILQ_INSERT_HEAD(&rmtree, new, chain);
845}
846
847void
848remrmconf(rmconf)
849	struct remoteconf *rmconf;
850{
851	TAILQ_REMOVE(&rmtree, rmconf, chain);
852}
853
854void
855flushrmconf()
856{
857	struct remoteconf *p, *next;
858
859	for (p = TAILQ_FIRST(&rmtree); p; p = next) {
860		next = TAILQ_NEXT(p, chain);
861		remrmconf(p);
862		delrmconf(p);
863	}
864}
865
866void
867initrmconf()
868{
869	TAILQ_INIT(&rmtree);
870}
871
872void
873rmconf_start_reload()
874{
875	rmtree_save=rmtree;
876	initrmconf();
877}
878
879void
880rmconf_finish_reload()
881{
882	remoteconf_tailq_head_t rmtree_tmp;
883
884	rmtree_tmp=rmtree;
885	rmtree=rmtree_save;
886	flushrmconf();
887	initrmconf();
888	rmtree=rmtree_tmp;
889}
890
891
892
893/* check exchange type to be acceptable */
894int
895check_etypeok(rmconf, ctx)
896	struct remoteconf *rmconf;
897	void *ctx;
898{
899	u_int8_t etype = (u_int8_t) (intptr_t) ctx;
900	struct etypes *e;
901
902	for (e = rmconf->etypes; e != NULL; e = e->next) {
903		if (e->type == etype)
904			return 1;
905		plog(LLV_DEBUG2, LOCATION, NULL,
906		     "Etype mismatch: got %d, expected %d.\n", e->type, etype);
907	}
908
909	return 0;
910}
911
912/*%%%*/
913struct isakmpsa *
914newisakmpsa()
915{
916	struct isakmpsa *new;
917
918	new = racoon_calloc(1, sizeof(*new));
919	if (new == NULL)
920		return NULL;
921
922	/*
923	 * Just for sanity, make sure this is initialized.  This is
924	 * filled in for real when the ISAKMP proposal is configured.
925	 */
926	new->vendorid = VENDORID_UNKNOWN;
927
928	new->next = NULL;
929#ifdef HAVE_GSSAPI
930	new->gssid = NULL;
931#endif
932
933	return new;
934}
935
936/*
937 * insert into tail of list.
938 */
939void
940insisakmpsa(new, rmconf)
941	struct isakmpsa *new;
942	struct remoteconf *rmconf;
943{
944	struct isakmpsa *p;
945
946	if (rmconf->proposal == NULL) {
947		rmconf->proposal = new;
948		return;
949	}
950
951	for (p = rmconf->proposal; p->next != NULL; p = p->next)
952		;
953	p->next = new;
954}
955
956static void *
957dump_peers_identifiers (void *entry, void *arg)
958{
959	struct idspec *id = (struct idspec*) entry;
960	char buf[1024], *pbuf;
961	pbuf = buf;
962	pbuf += sprintf (pbuf, "\tpeers_identifier %s",
963			 s_idtype (id->idtype));
964	if (id->id)
965		pbuf += sprintf (pbuf, " \"%s\"", id->id->v);
966	plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
967	return NULL;
968}
969
970static int
971dump_rmconf_single (struct remoteconf *p, void *data)
972{
973	struct etypes *etype = p->etypes;
974	struct isakmpsa *prop = p->proposal;
975	char buf[1024], *pbuf;
976
977	pbuf = buf;
978
979	pbuf += sprintf(pbuf, "remote \"%s\"", p->name);
980	if (p->inherited_from)
981		pbuf += sprintf(pbuf, " inherit \"%s\"",
982				p->inherited_from->name);
983	plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf);
984	pbuf = buf;
985	pbuf += sprintf(pbuf, "\texchange_type ");
986	while (etype) {
987		pbuf += sprintf (pbuf, "%s%s", s_etype(etype->type),
988				 etype->next != NULL ? ", " : ";\n");
989		etype = etype->next;
990	}
991	plog(LLV_INFO, LOCATION, NULL, "%s", buf);
992	plog(LLV_INFO, LOCATION, NULL, "\tdoi %s;\n", s_doi(p->doitype));
993	pbuf = buf;
994	pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype));
995	if (p->idvtype == IDTYPE_ASN1DN) {
996		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
997		plog(LLV_INFO, LOCATION, NULL,
998		     "\tcertificate_type %s \"%s\" \"%s\";\n",
999		     oakley_get_certtype(p->mycert) == ISAKMP_CERT_X509SIGN
1000		       ? "x509" : "*UNKNOWN*",
1001		     p->mycertfile, p->myprivfile);
1002
1003		switch (oakley_get_certtype(p->peerscert)) {
1004		case ISAKMP_CERT_NONE:
1005			plog(LLV_INFO, LOCATION, NULL,
1006			     "\t/* peers certificate from payload */\n");
1007			break;
1008		case ISAKMP_CERT_X509SIGN:
1009			plog(LLV_INFO, LOCATION, NULL,
1010			     "\tpeers_certfile \"%s\";\n", p->peerscertfile);
1011			break;
1012		case ISAKMP_CERT_DNS:
1013			plog(LLV_INFO, LOCATION, NULL,
1014			     "\tpeers_certfile dnssec;\n");
1015			break;
1016		default:
1017			plog(LLV_INFO, LOCATION, NULL,
1018			     "\tpeers_certfile *UNKNOWN* (%d)\n",
1019			     oakley_get_certtype(p->peerscert));
1020			break;
1021		}
1022	}
1023	else {
1024		if (p->idv)
1025			pbuf += sprintf (pbuf, " \"%s\"", p->idv->v);
1026		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
1027		genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL);
1028	}
1029
1030	plog(LLV_INFO, LOCATION, NULL, "\trekey %s;\n",
1031		p->rekey == REKEY_FORCE ? "force" : s_switch (p->rekey));
1032	plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n",
1033		s_switch (p->send_cert));
1034	plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n",
1035		s_switch (p->send_cr));
1036	plog(LLV_INFO, LOCATION, NULL, "\tmatch_empty_cr %s;\n",
1037		s_switch (p->match_empty_cr));
1038	plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n",
1039		s_switch (p->verify_cert));
1040	plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n",
1041		s_switch (p->verify_identifier));
1042	plog(LLV_INFO, LOCATION, NULL, "\tnat_traversal %s;\n",
1043		p->nat_traversal == NATT_FORCE ?
1044			"force" : s_switch (p->nat_traversal));
1045	plog(LLV_INFO, LOCATION, NULL, "\tnonce_size %d;\n",
1046		p->nonce_size);
1047	plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n",
1048		s_switch (p->passive));
1049	plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n",
1050		p->ike_frag == ISAKMP_FRAG_FORCE ?
1051			"force" : s_switch (p->ike_frag));
1052	plog(LLV_INFO, LOCATION, NULL, "\tesp_frag %d;\n", p->esp_frag);
1053	plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n",
1054		s_switch (p->ini_contact));
1055	plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n",
1056		s_switch (p->gen_policy));
1057	plog(LLV_INFO, LOCATION, NULL, "\tsupport_proxy %s;\n",
1058		s_switch (p->support_proxy));
1059
1060	while (prop) {
1061		plog(LLV_INFO, LOCATION, NULL, "\n");
1062		plog(LLV_INFO, LOCATION, NULL,
1063			"\t/* prop_no=%d, trns_no=%d */\n",
1064			prop->prop_no, prop->trns_no);
1065		plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n");
1066		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n",
1067			(long)prop->lifetime);
1068		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime bytes %zd;\n",
1069			prop->lifebyte);
1070		plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n",
1071			alg_oakley_dhdef_name(prop->dh_group));
1072		plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n",
1073			alg_oakley_encdef_name(prop->enctype));
1074		plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n",
1075			alg_oakley_hashdef_name(prop->hashtype));
1076		plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n",
1077			alg_oakley_authdef_name(prop->authmethod));
1078		plog(LLV_INFO, LOCATION, NULL, "\t}\n");
1079		prop = prop->next;
1080	}
1081	plog(LLV_INFO, LOCATION, NULL, "}\n");
1082	plog(LLV_INFO, LOCATION, NULL, "\n");
1083
1084	return 0;
1085}
1086
1087void
1088dumprmconf()
1089{
1090	enumrmconf(NULL, dump_rmconf_single, NULL);
1091}
1092
1093struct idspec *
1094newidspec()
1095{
1096	struct idspec *new;
1097
1098	new = racoon_calloc(1, sizeof(*new));
1099	if (new == NULL)
1100		return NULL;
1101	new->idtype = IDTYPE_ADDRESS;
1102	new->id = NULL;
1103	return new;
1104}
1105
1106vchar_t *
1107script_path_add(path)
1108	vchar_t *path;
1109{
1110	char *script_dir;
1111	vchar_t *new_path;
1112	vchar_t *new_storage;
1113	vchar_t **sp;
1114	size_t len;
1115	size_t size;
1116
1117	script_dir = lcconf->pathinfo[LC_PATHTYPE_SCRIPT];
1118
1119	/* Try to find the script in the script directory */
1120	if ((path->v[0] != '/') && (script_dir != NULL)) {
1121		len = strlen(script_dir) + sizeof("/") + path->l + 1;
1122
1123		if ((new_path = vmalloc(len)) == NULL) {
1124			plog(LLV_ERROR, LOCATION, NULL,
1125			    "Cannot allocate memory: %s\n", strerror(errno));
1126			return NULL;
1127		}
1128
1129		new_path->v[0] = '\0';
1130		(void)strlcat(new_path->v, script_dir, len);
1131		(void)strlcat(new_path->v, "/", len);
1132		(void)strlcat(new_path->v, path->v, len);
1133
1134		vfree(path);
1135		path = new_path;
1136	}
1137
1138	return path;
1139}
1140
1141
1142struct isakmpsa *
1143dupisakmpsa(struct isakmpsa *sa)
1144{
1145	struct isakmpsa *res = NULL;
1146
1147	if(sa == NULL)
1148		return NULL;
1149
1150	res = newisakmpsa();
1151	if(res == NULL)
1152		return NULL;
1153
1154	*res = *sa;
1155#ifdef HAVE_GSSAPI
1156	if (sa->gssid != NULL)
1157		res->gssid = vdup(sa->gssid);
1158#endif
1159	res->next = NULL;
1160
1161	if(sa->dhgrp != NULL)
1162		oakley_setdhgroup(sa->dh_group, &res->dhgrp);
1163
1164	return res;
1165
1166}
1167
1168#ifdef ENABLE_HYBRID
1169int
1170isakmpsa_switch_authmethod(authmethod)
1171	int authmethod;
1172{
1173	switch(authmethod) {
1174	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1175		authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
1176		break;
1177	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1178		authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
1179		break;
1180	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1181		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
1182		break;
1183	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1184		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
1185		break;
1186	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1187		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
1188		break;
1189	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1190		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
1191		break;
1192	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1193		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
1194		break;
1195	default:
1196		break;
1197	}
1198
1199	return authmethod;
1200}
1201#endif
1202
1203/*
1204 * Given a proposed ISAKMP SA, and a list of acceptable
1205 * ISAKMP SAs, it compares using pcheck_level policy and
1206 * returns first match (if any).
1207 */
1208struct isakmpsa *
1209checkisakmpsa(pcheck_level, proposal, acceptable)
1210	int pcheck_level;
1211	struct isakmpsa *proposal, *acceptable;
1212{
1213	struct isakmpsa *p;
1214
1215	for (p = acceptable; p != NULL; p = p->next){
1216		plog(LLV_DEBUG2, LOCATION, NULL,
1217		     "checkisakmpsa:\nauthmethod: %d / %d\n",
1218		     isakmpsa_switch_authmethod(proposal->authmethod), isakmpsa_switch_authmethod(p->authmethod));
1219		if (isakmpsa_switch_authmethod(proposal->authmethod) != isakmpsa_switch_authmethod(p->authmethod) ||
1220		    proposal->enctype != p->enctype ||
1221                    proposal->dh_group != p->dh_group ||
1222		    proposal->hashtype != p->hashtype)
1223			continue;
1224
1225		switch (pcheck_level) {
1226		case PROP_CHECK_OBEY:
1227			break;
1228
1229		case PROP_CHECK_CLAIM:
1230		case PROP_CHECK_STRICT:
1231			if (proposal->encklen < p->encklen ||
1232#if 0
1233			    proposal->lifebyte > p->lifebyte ||
1234#endif
1235			    proposal->lifetime > p->lifetime)
1236				continue;
1237			break;
1238
1239		case PROP_CHECK_EXACT:
1240			if (proposal->encklen != p->encklen ||
1241#if 0
1242                            proposal->lifebyte != p->lifebyte ||
1243#endif
1244			    proposal->lifetime != p->lifetime)
1245				continue;
1246			break;
1247
1248		default:
1249			continue;
1250		}
1251
1252		return p;
1253	}
1254
1255	return NULL;
1256}
1257