1/*	$NetBSD: remoteconf.c,v 1.9.4.1 2007/08/01 11:52:22 vanhu 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#ifndef HAVE_NETINET6_IPSEC
46#include <netinet/ipsec.h>
47#else
48#include <netinet6/ipsec.h>
49#endif
50
51#include <stdlib.h>
52#include <stdio.h>
53#include <string.h>
54#include <errno.h>
55
56#include "var.h"
57#include "misc.h"
58#include "vmbuf.h"
59#include "plog.h"
60#include "sockmisc.h"
61#include "genlist.h"
62#include "debug.h"
63
64#include "isakmp_var.h"
65#ifdef ENABLE_HYBRID
66#include "isakmp_xauth.h"
67#endif
68#include "isakmp.h"
69#include "ipsec_doi.h"
70#include "oakley.h"
71#include "remoteconf.h"
72#include "localconf.h"
73#include "grabmyaddr.h"
74#include "policy.h"
75#include "proposal.h"
76#include "vendorid.h"
77#include "gcmalloc.h"
78#include "strnames.h"
79#include "algorithm.h"
80#include "nattraversal.h"
81#include "isakmp_frag.h"
82#include "genlist.h"
83
84static TAILQ_HEAD(_rmtree, remoteconf) rmtree;
85
86
87/*%%%*/
88/*
89 * search remote configuration.
90 * don't use port number to search if its value is either IPSEC_PORT_ANY.
91 * If matching anonymous entry, then new entry is copied from anonymous entry.
92 * If no anonymous entry found, then return NULL.
93 * OUT:	NULL:	NG
94 *	Other:	remote configuration entry.
95 */
96struct remoteconf *
97getrmconf_strict(remote, allow_anon)
98	struct sockaddr_storage *remote;
99	int allow_anon;
100{
101	struct remoteconf *p;
102	struct remoteconf *p_withport_besteffort = NULL;
103	struct remoteconf *p_with_prefix = NULL;
104	struct remoteconf *p_with_prefix_besteffort = NULL;
105    int                last_prefix = 0;
106	struct remoteconf *anon = NULL;
107
108	int withport;
109	char buf[NI_MAXHOST + NI_MAXSERV + 10];
110	char addr[NI_MAXHOST], port[NI_MAXSERV];
111
112	withport = 0;
113
114	/*
115	 * We never have ports set in our remote configurations, but when
116	 * NAT-T is enabled, the kernel can have policies with ports and
117	 * send us an acquire message for a destination that has a port set.
118	 * If we do this port check here, we have to fallback to a best-effort result (without the port).
119	 *
120	 * In an ideal world, we would be able to have remote conf with
121	 * port, and the port could be a wildcard. That test could be used.
122	 */
123	switch (remote->ss_family) {
124	case AF_INET:
125		if (((struct sockaddr_in *)remote)->sin_port != IPSEC_PORT_ANY)
126			withport = 1;
127		break;
128#ifdef INET6
129	case AF_INET6:
130		if (((struct sockaddr_in6 *)remote)->sin6_port != IPSEC_PORT_ANY)
131			withport = 1;
132		break;
133#endif
134	case AF_UNSPEC:
135		break;
136
137	default:
138		plog(ASL_LEVEL_ERR,
139			"invalid ip address family: %d\n", remote->ss_family);
140		return NULL;
141	}
142
143	if (remote->ss_family == AF_UNSPEC)
144		snprintf (buf, sizeof(buf), "%s", "anonymous");
145	else {
146		GETNAMEINFO((struct sockaddr *)remote, addr, port);
147		snprintf(buf, sizeof(buf), "%s%s%s%s", addr,
148			withport ? "[" : "",
149			withport ? port : "",
150			withport ? "]" : "");
151	}
152
153	TAILQ_FOREACH(p, &rmtree, chain) {
154		if (remote->ss_family == AF_UNSPEC
155		     && remote->ss_family == p->remote->ss_family) {
156            plog(ASL_LEVEL_DEBUG, "configuration found for %s.\n", buf);
157			return p;
158        }
159        if (p->remote_prefix == 0) {
160            if ((!withport && cmpsaddrwop(remote, p->remote) == 0)
161                || (withport && cmpsaddrstrict(remote, p->remote) == 0)) {
162                    plog(ASL_LEVEL_DEBUG, "configuration found for %s.\n", buf);
163                    return p;
164                } else if (withport && cmpsaddrwop(remote, p->remote) == 0) {
165                    // for withport: save the pointer for the best-effort search
166                    p_withport_besteffort = p;
167                }
168        } else {
169            if ((!withport && cmpsaddrwop_withprefix(remote, p->remote, p->remote_prefix) == 0)
170                || (withport && cmpsaddrstrict_withprefix(remote, p->remote, p->remote_prefix) == 0)) {
171                if (p->remote_prefix >= last_prefix) {
172                    p_with_prefix = p;
173                    last_prefix = p->remote_prefix;
174                }
175            } else if (withport && cmpsaddrwop_withprefix(remote, p->remote, p->remote_prefix) == 0) {
176                if (p->remote_prefix >= last_prefix) {
177                    p_with_prefix_besteffort = p;
178                    last_prefix = p->remote_prefix;
179                }
180            }
181        }
182
183		/* save the pointer to the anonymous configuration */
184		if (p->remote->ss_family == AF_UNSPEC)
185			anon = p;
186	}
187
188	if (p_withport_besteffort) {
189		plog(ASL_LEVEL_DEBUG, "configuration found for %s.\n", buf);
190		return p_withport_besteffort;
191	}
192    if (p_with_prefix) {
193        plog(ASL_LEVEL_DEBUG, "configuration found for %s.\n", buf);
194        return p_with_prefix;
195    }
196    if (p_with_prefix_besteffort) {
197        plog(ASL_LEVEL_DEBUG, "configuration found for %s.\n", buf);
198        return p_with_prefix_besteffort;
199    }
200	if (allow_anon && anon != NULL) {
201		plog(ASL_LEVEL_DEBUG,
202			"anonymous configuration selected for %s.\n", buf);
203		return anon;
204	}
205
206	plog(ASL_LEVEL_DEBUG,
207		"no remote configuration found.\n");
208
209	return NULL;
210}
211
212int
213no_remote_configs(ignore_anonymous)
214	int ignore_anonymous;
215{
216
217	struct remoteconf *p;
218#if !TARGET_OS_EMBEDDED
219	static const char default_idv[] = "macuser@localhost";
220	static const int default_idv_len = sizeof(default_idv) - 1;
221#endif
222
223	TAILQ_FOREACH(p, &rmtree, chain) {
224		if (ignore_anonymous) {
225			if (p->remote->ss_family == AF_UNSPEC)	/* anonymous */
226				continue;
227		}
228#if !TARGET_OS_EMBEDDED
229		// ignore the default btmm ipv6 config thats always present in racoon.conf
230		if (p->remote->ss_family == AF_INET6 &&
231			p->idvtype == IDTYPE_USERFQDN &&
232			p->idv != NULL &&
233			p->idv->l == default_idv_len &&
234			strncmp(p->idv->v, default_idv, p->idv->l) == 0) {
235			continue;
236		}
237#endif
238		return 0;
239	}
240	return 1;
241}
242
243struct remoteconf *
244getrmconf(remote)
245	struct sockaddr_storage *remote;
246{
247	return getrmconf_strict(remote, 1);
248}
249
250struct remoteconf *
251create_rmconf()
252{
253	struct remoteconf *new;
254
255	new = racoon_calloc(1, sizeof(*new));
256	if (new == NULL)
257		return NULL;
258
259    new->refcount = 1;
260    new->in_list = 0;
261	new->proposal = NULL;
262
263	/* set default */
264	new->doitype = IPSEC_DOI;
265	new->sittype = IPSECDOI_SIT_IDENTITY_ONLY;
266    new->ike_version = ISAKMP_VERSION_NUMBER_IKEV1;
267	new->idvtype = IDTYPE_UNDEFINED;
268	new->idvl_p = genlist_init();
269	new->nonce_size = DEFAULT_NONCE_SIZE;
270	new->passive = FALSE;
271	new->ike_frag = ISAKMP_FRAG_ON;
272	new->esp_frag = IP_MAXPACKET;
273	new->ini_contact = TRUE;
274	new->mode_cfg = FALSE;
275	new->pcheck_level = PROP_CHECK_STRICT;
276	new->verify_identifier = FALSE;
277	new->verify_cert = TRUE;
278	new->getcert_method = ISAKMP_GETCERT_PAYLOAD;
279	new->cacerttype = ISAKMP_CERT_X509SIGN;
280	new->certtype = ISAKMP_CERT_NONE;
281	new->send_cert = TRUE;
282	new->send_cr = TRUE;
283	new->support_proxy = FALSE;
284	new->gen_policy = FALSE;
285	new->retry_counter = lcconf->retry_counter;
286	new->retry_interval = lcconf->retry_interval;
287	new->nat_traversal = NATT_ON;
288	new->natt_multiple_user = FALSE;
289	new->natt_keepalive = TRUE;
290	new->idv = NULL;
291	new->key = NULL;
292
293	new->dpd = TRUE; /* Enable DPD support by default */
294	new->dpd_interval = 0; /* Disable DPD checks by default */
295	new->dpd_retry = 5;
296	new->dpd_maxfails = 5;
297    new->dpd_algo = DPD_ALGO_INBOUND_DETECT;
298    new->idle_timeout = 0;
299
300	new->weak_phase1_check = 0;
301
302#ifdef ENABLE_HYBRID
303	new->xauth = NULL;
304#endif
305	new->initiate_ph1rekey = TRUE;
306	return new;
307}
308
309struct remoteconf *
310copyrmconf(struct sockaddr_storage *remote)
311{
312	struct remoteconf *new, *old;
313
314	old = getrmconf_strict (remote, 0);
315	if (old == NULL) {
316		plog (ASL_LEVEL_ERR,
317		      "Remote configuration for '%s' not found!\n",
318		      saddr2str((struct sockaddr *)remote));
319		return NULL;
320	}
321
322	new = duprmconf (old);
323
324	return new;
325}
326
327void *
328dupidvl(void *entry, void *arg)
329{
330	struct idspec *id;
331	struct idspec *old = (struct idspec *) entry;
332	id = newidspec();
333	if (!id) return (void *) -1;
334
335	if (set_identifier(&id->id, old->idtype, old->id) != 0) {
336		racoon_free(id);
337		return (void *) -1;
338	}
339
340	id->idtype = old->idtype;
341
342	genlist_append(arg, id);
343	return NULL;
344}
345
346struct remoteconf *
347duprmconf (struct remoteconf *rmconf)
348{
349    struct remoteconf *new;
350
351    new = racoon_calloc(1, sizeof(*new));
352    if (new == NULL)
353        return NULL;
354    memcpy (new, rmconf, sizeof (*new));
355    // FIXME: We should duplicate remote, proposal, etc.
356    // This is now handled in the cfparse.y
357    // new->proposal = ...;
358
359    // zero-out pointers
360    new->remote = NULL;
361    new->forced_local = NULL;
362    new->keychainCertRef = NULL;	/* peristant keychain ref for cert */
363    new->shared_secret = NULL;	/* shared secret */
364    new->open_dir_auth_group = NULL;	/* group to be used to authorize user */
365    new->proposal = NULL;
366    new->in_list = 0;
367    new->refcount = 1;
368    new->idv = NULL;
369    new->key = NULL;
370#ifdef ENABLE_HYBRID
371    new->xauth = NULL;
372#endif
373
374	/* duplicate dynamic structures */
375	if (new->etypes)
376		new->etypes=dupetypes(new->etypes);
377	new->idvl_p = genlist_init();
378	genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p);
379
380	return new;
381}
382
383static void
384idspec_free(void *data)
385{
386	vfree (((struct idspec *)data)->id);
387	free (data);
388}
389
390static void
391proposalspec_free(struct proposalspec *head)
392{
393
394	struct proposalspec* next_propsp = head;
395
396	while (next_propsp) {
397		struct proposalspec* curr_propsp;
398		struct secprotospec* next_protosp;
399
400		curr_propsp = next_propsp;
401		next_propsp = next_propsp->next;
402		next_protosp = curr_propsp->spspec;
403		while (next_protosp) {
404			struct secprotospec* curr_protosp;
405
406			curr_protosp = next_protosp;
407			next_protosp = next_protosp->next;
408
409			if (curr_protosp->gssid)
410				free(curr_protosp->gssid);
411			if (curr_protosp->remote)
412				free(curr_protosp->remote);
413			racoon_free(curr_protosp);
414		}
415		racoon_free(curr_propsp);
416	}
417}
418
419void
420delrmconf(struct remoteconf *rmconf)
421{
422	if (rmconf->remote)
423		racoon_free(rmconf->remote);
424	if (rmconf->forced_local)
425		racoon_free(rmconf->forced_local);
426#ifdef ENABLE_HYBRID
427	if (rmconf->xauth)
428		xauth_rmconf_delete(&rmconf->xauth);
429#endif
430	if (rmconf->etypes) {
431		deletypes(rmconf->etypes);
432		rmconf->etypes=NULL;
433	}
434	if (rmconf->idv)
435		vfree(rmconf->idv);
436	if (rmconf->idvl_p)
437		genlist_free(rmconf->idvl_p, idspec_free);
438	if (rmconf->dhgrp)
439		oakley_dhgrp_free(rmconf->dhgrp);
440	if (rmconf->proposal)
441		delisakmpsa(rmconf->proposal);
442	if (rmconf->prhead)
443		proposalspec_free(rmconf->prhead);
444	if (rmconf->shared_secret)
445		vfree(rmconf->shared_secret);
446	if (rmconf->keychainCertRef)
447		vfree(rmconf->keychainCertRef);
448	if (rmconf->open_dir_auth_group)
449		vfree(rmconf->open_dir_auth_group);
450
451	racoon_free(rmconf);
452}
453
454void
455delisakmpsa(struct isakmpsa *sa)
456{
457	if (sa->dhgrp)
458		oakley_dhgrp_free(sa->dhgrp);
459	if (sa->next)
460		delisakmpsa(sa->next);
461	racoon_free(sa);
462}
463
464struct etypes *
465dupetypes(struct etypes *orig)
466{
467	struct etypes *new;
468
469	if (!orig)
470		return NULL;
471
472	new = racoon_malloc(sizeof(struct etypes));
473	if (new == NULL)
474		return NULL;
475
476	new->type = orig->type;
477	new->next = NULL;
478
479	if (orig->next)
480		new->next=dupetypes(orig->next);
481
482	return new;
483}
484
485void
486deletypes(struct etypes *e)
487{
488	if (e->next)
489		deletypes(e->next);
490	racoon_free(e);
491}
492
493/*
494 * insert into head of list.
495 */
496void
497insrmconf(struct remoteconf *new)
498{
499	TAILQ_INSERT_HEAD(&rmtree, new, chain);
500    new->in_list = 1;
501}
502
503void
504remrmconf(struct remoteconf *rmconf)
505{
506	if (rmconf->in_list)
507        TAILQ_REMOVE(&rmtree, rmconf, chain);
508    rmconf->in_list = 0;
509}
510
511void
512retain_rmconf(struct remoteconf *rmconf)
513{
514    (rmconf->refcount)++;
515}
516
517void
518release_rmconf(struct remoteconf *rmconf)
519{
520    if (--(rmconf->refcount) <= 0) {
521        remrmconf(rmconf);
522        delrmconf(rmconf);
523    }
524}
525
526void
527flushrmconf()
528{
529	struct remoteconf *p, *next;
530
531	for (p = TAILQ_FIRST(&rmtree); p; p = next) {
532		next = TAILQ_NEXT(p, chain);
533		remrmconf(p);
534        if (--(p->refcount) <= 0)
535            delrmconf(p);
536	}
537}
538
539void
540initrmconf()
541{
542	TAILQ_INIT(&rmtree);
543}
544
545/* check exchange type to be acceptable */
546struct etypes *
547check_etypeok(struct remoteconf *rmconf, u_int8_t etype)
548{
549	struct etypes *e;
550
551	for (e = rmconf->etypes; e != NULL; e = e->next) {
552		if (e->type == etype)
553			break;
554	}
555
556	return e;
557}
558
559/*%%%*/
560struct isakmpsa *
561newisakmpsa()
562{
563	struct isakmpsa *new;
564
565	new = racoon_calloc(1, sizeof(*new));
566	if (new == NULL)
567		return NULL;
568
569	/*
570	 * Just for sanity, make sure this is initialized.  This is
571	 * filled in for real when the ISAKMP proposal is configured.
572	 */
573	new->vendorid = VENDORID_UNKNOWN;
574
575	new->next = NULL;
576	new->rmconf = NULL;
577
578	return new;
579}
580
581/*
582 * insert into tail of list.
583 */
584void
585insisakmpsa(struct isakmpsa *new, struct remoteconf *rmconf)
586{
587	struct isakmpsa *p;
588
589	new->rmconf = rmconf;
590
591	if (rmconf->proposal == NULL) {
592		rmconf->proposal = new;
593		return;
594	}
595
596	for (p = rmconf->proposal; p->next != NULL; p = p->next)
597		;
598	p->next = new;
599
600	return;
601}
602
603struct remoteconf *
604foreachrmconf(rmconf_func_t rmconf_func, void *data)
605{
606	struct remoteconf *p, *ret = NULL;
607
608	TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
609		ret = (*rmconf_func)(p, data);
610		if (ret)
611			break;
612	}
613
614	return ret;
615}
616
617static void *
618dump_peers_identifiers (void *entry, void *arg)
619{
620	struct idspec *id = (struct idspec*) entry;
621	char buf[1024], *pbuf;
622	pbuf = buf;
623	pbuf += snprintf (pbuf, sizeof(buf) - (pbuf - buf), "\tpeers_identifier %s",
624			 s_idtype (id->idtype));
625	if (id->id)
626		pbuf += snprintf (pbuf, sizeof(buf) - (pbuf - buf), " \"%s\"", id->id->v);
627	plog(ASL_LEVEL_INFO, "%s;\n", buf);
628	return NULL;
629}
630
631static struct remoteconf *
632dump_rmconf_single (struct remoteconf *p, void *data)
633{
634	struct etypes *etype = p->etypes;
635	struct isakmpsa *prop = p->proposal;
636	char buf[1024], *pbuf;
637
638	pbuf = buf;
639    if (p->remote_prefix)
640        pbuf += snprintf(pbuf, sizeof(buf) - (pbuf - buf), "remote %s",
641                         saddr2str_with_prefix((struct sockaddr *)p->remote, p->remote_prefix));
642    else
643        pbuf += snprintf(pbuf, sizeof(buf) - (pbuf - buf), "remote %s", saddr2str((struct sockaddr *)p->remote));
644	if (p->inherited_from)
645		pbuf += snprintf(pbuf, sizeof(buf) - (pbuf - buf), " inherit %s",
646				saddr2str((struct sockaddr *)p->inherited_from->remote));
647	plog(ASL_LEVEL_INFO, "%s {\n", buf);
648	pbuf = buf;
649	pbuf += snprintf(pbuf, sizeof(buf) - (pbuf - buf), "\texchange_type ");
650	while (etype) {
651		pbuf += snprintf (pbuf, sizeof(buf) - (pbuf - buf), "%s%s", s_etype(etype->type),
652				 etype->next != NULL ? ", " : ";\n");
653		etype = etype->next;
654	}
655	plog(ASL_LEVEL_INFO, "%s", buf);
656	plog(ASL_LEVEL_INFO, "\tdoi %s;\n", s_doi(p->doitype));
657	pbuf = buf;
658	pbuf += snprintf(pbuf, sizeof(buf) - (pbuf - buf), "\tmy_identifier %s", s_idtype (p->idvtype));
659	if (p->idvtype == IDTYPE_ASN1DN) {
660		plog(ASL_LEVEL_INFO, "%s;\n", buf);
661		switch (p->getcert_method) {
662		  case 0:
663		  	break;
664		  case ISAKMP_GETCERT_PAYLOAD:
665			plog(ASL_LEVEL_INFO, "\t/* peers certificate from payload */\n");
666			break;
667		  default:
668			plog(ASL_LEVEL_INFO, "\tpeers_certfile *UNKNOWN* (%d)\n", p->getcert_method);
669		}
670	}
671	else {
672		if (p->idv)
673			pbuf += snprintf (pbuf, sizeof(buf) - (pbuf - buf), " \"%s\"", p->idv->v);
674		plog(ASL_LEVEL_INFO, "%s;\n", buf);
675		genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL);
676	}
677
678	plog(ASL_LEVEL_INFO, "\tsend_cert %s;\n",
679		s_switch (p->send_cert));
680	plog(ASL_LEVEL_INFO, "\tsend_cr %s;\n",
681		s_switch (p->send_cr));
682	plog(ASL_LEVEL_INFO, "\tverify_cert %s;\n",
683		s_switch (p->verify_cert));
684	plog(ASL_LEVEL_INFO, "\tverify_identifier %s;\n",
685		s_switch (p->verify_identifier));
686	plog(ASL_LEVEL_INFO, "\tnat_traversal %s;\n",
687		p->nat_traversal == NATT_FORCE ?
688			"force" : s_switch (p->nat_traversal));
689	plog(ASL_LEVEL_INFO, "\tnatt_multiple_user %s;\n",
690		s_switch (p->natt_multiple_user));
691	plog(ASL_LEVEL_INFO, "\tnonce_size %d;\n",
692		p->nonce_size);
693	plog(ASL_LEVEL_INFO, "\tpassive %s;\n",
694		s_switch (p->passive));
695	plog(ASL_LEVEL_INFO, "\tike_frag %s;\n",
696		p->ike_frag == ISAKMP_FRAG_FORCE ?
697			"force" : s_switch (p->ike_frag));
698	plog(ASL_LEVEL_INFO, "\tesp_frag %d;\n", p->esp_frag);
699	plog(ASL_LEVEL_INFO, "\tinitial_contact %s;\n",
700		s_switch (p->ini_contact));
701	plog(ASL_LEVEL_INFO, "\tgenerate_policy %s;\n",
702		s_switch (p->gen_policy));
703	plog(ASL_LEVEL_INFO, "\tsupport_proxy %s;\n",
704		s_switch (p->support_proxy));
705
706	while (prop) {
707		plog(ASL_LEVEL_INFO, "\n");
708		plog(ASL_LEVEL_INFO,
709			"\t/* prop_no=%d, trns_no=%d, rmconf=%s */\n",
710			prop->prop_no, prop->trns_no,
711			saddr2str((struct sockaddr *)prop->rmconf->remote));
712		plog(ASL_LEVEL_INFO, "\tproposal {\n");
713		plog(ASL_LEVEL_INFO, "\t\tlifetime time %lu sec;\n",
714			(long)prop->lifetime);
715		plog(ASL_LEVEL_INFO, "\t\tlifetime bytes %zd;\n",
716			prop->lifebyte);
717		plog(ASL_LEVEL_INFO, "\t\tdh_group %s;\n",
718			alg_oakley_dhdef_name(prop->dh_group));
719		plog(ASL_LEVEL_INFO, "\t\tencryption_algorithm %s;\n",
720			alg_oakley_encdef_name(prop->enctype));
721		plog(ASL_LEVEL_INFO, "\t\thash_algorithm %s;\n",
722			alg_oakley_hashdef_name(prop->hashtype));
723		plog(ASL_LEVEL_INFO, "\t\tprf_algorithm %s;\n",
724			 alg_oakley_hashdef_name(prop->prf));
725		plog(ASL_LEVEL_INFO, "\t\tauthentication_method %s;\n",
726			alg_oakley_authdef_name(prop->authmethod));
727		plog(ASL_LEVEL_INFO, "\t}\n");
728		prop = prop->next;
729	}
730	plog(ASL_LEVEL_INFO, "}\n");
731	plog(ASL_LEVEL_INFO, "\n");
732
733	return NULL;
734}
735
736void
737dumprmconf()
738{
739	foreachrmconf (dump_rmconf_single, NULL);
740}
741
742struct idspec *
743newidspec()
744{
745	struct idspec *new;
746
747	new = racoon_calloc(1, sizeof(*new));
748	if (new == NULL)
749		return NULL;
750	new->idtype = IDTYPE_ADDRESS;
751
752	return new;
753}
754
755
756struct isakmpsa *
757dupisakmpsa(struct isakmpsa *sa)
758{
759	struct isakmpsa *res = NULL;
760
761	if (sa == NULL)
762		return NULL;
763
764	res = newisakmpsa();
765	if(res == NULL)
766		return NULL;
767
768	*res = *sa;
769	res->next=NULL;
770
771	if (sa->dhgrp != NULL)
772		oakley_setdhgroup(sa->dh_group, &(res->dhgrp));
773
774	return res;
775
776}
777
778