1/*	$NetBSD: remoteconf.c,v 1.9.4.2 2008/06/18 07:30:19 mgrooms 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 "oakley.h"
67#include "remoteconf.h"
68#include "localconf.h"
69#include "grabmyaddr.h"
70#include "policy.h"
71#include "proposal.h"
72#include "vendorid.h"
73#include "gcmalloc.h"
74#include "strnames.h"
75#include "algorithm.h"
76#include "nattraversal.h"
77#include "isakmp_frag.h"
78#include "genlist.h"
79
80static TAILQ_HEAD(_rmtree, remoteconf) rmtree, rmtree_save, rmtree_tmp;
81
82/*
83 * Script hook names and script hook paths
84 */
85char *script_names[SCRIPT_MAX + 1] = { "phase1_up", "phase1_down" };
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 *remote;
99	int allow_anon;
100{
101	struct remoteconf *p;
102	struct remoteconf *anon = NULL;
103	int withport;
104	char buf[NI_MAXHOST + NI_MAXSERV + 10];
105	char addr[NI_MAXHOST], port[NI_MAXSERV];
106
107	withport = 0;
108
109#ifndef ENABLE_NATT
110	/*
111	 * We never have ports set in our remote configurations, but when
112	 * NAT-T is enabled, the kernel can have policies with ports and
113	 * send us an acquire message for a destination that has a port set.
114	 * If we do this port check here, we don't find the remote config.
115	 *
116	 * In an ideal world, we would be able to have remote conf with
117	 * port, and the port could be a wildcard. That test could be used.
118	 */
119	if (remote->sa_family != AF_UNSPEC &&
120	    extract_port(remote) != IPSEC_PORT_ANY)
121		withport = 1;
122#endif /* ENABLE_NATT */
123
124	if (remote->sa_family == AF_UNSPEC)
125		snprintf (buf, sizeof(buf), "%s", "anonymous");
126	else {
127		GETNAMEINFO(remote, addr, port);
128		snprintf(buf, sizeof(buf), "%s%s%s%s", addr,
129			withport ? "[" : "",
130			withport ? port : "",
131			withport ? "]" : "");
132	}
133
134	TAILQ_FOREACH(p, &rmtree, chain) {
135		if ((remote->sa_family == AF_UNSPEC
136		     && remote->sa_family == p->remote->sa_family)
137		 || (!withport && cmpsaddrwop(remote, p->remote) == 0)
138		 || (withport && cmpsaddrstrict(remote, p->remote) == 0)) {
139			plog(LLV_DEBUG, LOCATION, NULL,
140				"configuration found for %s.\n", buf);
141			return p;
142		}
143
144		/* save the pointer to the anonymous configuration */
145		if (p->remote->sa_family == AF_UNSPEC)
146			anon = p;
147	}
148
149	if (allow_anon && anon != NULL) {
150		plog(LLV_DEBUG, LOCATION, NULL,
151			"anonymous configuration selected for %s.\n", buf);
152		return anon;
153	}
154
155	plog(LLV_DEBUG, LOCATION, NULL,
156		"no remote configuration found.\n");
157
158	return NULL;
159}
160
161struct remoteconf *
162getrmconf(remote)
163	struct sockaddr *remote;
164{
165	return getrmconf_strict(remote, 1);
166}
167
168struct remoteconf *
169newrmconf()
170{
171	struct remoteconf *new;
172	int i;
173
174	new = racoon_calloc(1, sizeof(*new));
175	if (new == NULL)
176		return NULL;
177
178	new->proposal = NULL;
179
180	/* set default */
181	new->doitype = IPSEC_DOI;
182	new->sittype = IPSECDOI_SIT_IDENTITY_ONLY;
183	new->idvtype = IDTYPE_UNDEFINED;
184	new->idvl_p = genlist_init();
185	new->nonce_size = DEFAULT_NONCE_SIZE;
186	new->passive = FALSE;
187	new->ike_frag = FALSE;
188	new->esp_frag = IP_MAXPACKET;
189	new->ini_contact = TRUE;
190	new->mode_cfg = FALSE;
191	new->pcheck_level = PROP_CHECK_STRICT;
192	new->verify_identifier = FALSE;
193	new->verify_cert = TRUE;
194	new->getcert_method = ISAKMP_GETCERT_PAYLOAD;
195	new->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
196	new->cacerttype = ISAKMP_CERT_X509SIGN;
197	new->certtype = ISAKMP_CERT_NONE;
198	new->cacertfile = NULL;
199	new->send_cert = TRUE;
200	new->send_cr = TRUE;
201	new->support_proxy = FALSE;
202	for (i = 0; i <= SCRIPT_MAX; i++)
203		new->script[i] = NULL;
204	new->gen_policy = FALSE;
205	new->retry_counter = lcconf->retry_counter;
206	new->retry_interval = lcconf->retry_interval;
207	new->nat_traversal = FALSE;
208	new->rsa_private = genlist_init();
209	new->rsa_public = genlist_init();
210	new->idv = NULL;
211	new->key = NULL;
212
213	new->dpd = TRUE; /* Enable DPD support by default */
214	new->dpd_interval = 0; /* Disable DPD checks by default */
215	new->dpd_retry = 5;
216	new->dpd_maxfails = 5;
217
218	new->weak_phase1_check = 0;
219
220#ifdef ENABLE_HYBRID
221	new->xauth = NULL;
222#endif
223
224	return new;
225}
226
227struct remoteconf *
228copyrmconf(remote)
229	struct sockaddr *remote;
230{
231	struct remoteconf *new, *old;
232
233	old = getrmconf_strict (remote, 0);
234	if (old == NULL) {
235		plog (LLV_ERROR, LOCATION, NULL,
236		      "Remote configuration for '%s' not found!\n",
237		      saddr2str (remote));
238		return NULL;
239	}
240
241	new = duprmconf (old);
242
243	return new;
244}
245
246void *
247dupidvl(entry, arg)
248	void *entry;
249	void *arg;
250{
251	struct idspec *id;
252	struct idspec *old = (struct idspec *) entry;
253	id = newidspec();
254	if (!id) return (void *) -1;
255
256	if (set_identifier(&id->id, old->idtype, old->id) != 0) {
257		racoon_free(id);
258		return (void *) -1;
259	}
260
261	id->idtype = old->idtype;
262
263	genlist_append(arg, id);
264	return NULL;
265}
266
267struct remoteconf *
268duprmconf (rmconf)
269	struct remoteconf *rmconf;
270{
271	struct remoteconf *new;
272
273	new = racoon_calloc(1, sizeof(*new));
274	if (new == NULL)
275		return NULL;
276	memcpy (new, rmconf, sizeof (*new));
277	// FIXME: We should duplicate the proposal as well.
278	// This is now handled in the cfparse.y
279	// new->proposal = ...;
280
281	/* duplicate dynamic structures */
282	if (new->etypes)
283		new->etypes=dupetypes(new->etypes);
284	new->idvl_p = genlist_init();
285	genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p);
286
287	return new;
288}
289
290static void
291idspec_free(void *data)
292{
293	vfree (((struct idspec *)data)->id);
294	free (data);
295}
296
297void
298delrmconf(rmconf)
299	struct remoteconf *rmconf;
300{
301#ifdef ENABLE_HYBRID
302	if (rmconf->xauth)
303		xauth_rmconf_delete(&rmconf->xauth);
304#endif
305	if (rmconf->etypes){
306		deletypes(rmconf->etypes);
307		rmconf->etypes=NULL;
308	}
309	if (rmconf->idvl_p)
310		genlist_free(rmconf->idvl_p, idspec_free);
311	if (rmconf->dhgrp)
312		oakley_dhgrp_free(rmconf->dhgrp);
313	if (rmconf->proposal)
314		delisakmpsa(rmconf->proposal);
315	racoon_free(rmconf);
316}
317
318void
319delisakmpsa(sa)
320	struct isakmpsa *sa;
321{
322	if (sa->dhgrp)
323		oakley_dhgrp_free(sa->dhgrp);
324	if (sa->next)
325		delisakmpsa(sa->next);
326#ifdef HAVE_GSSAPI
327	if (sa->gssid)
328		vfree(sa->gssid);
329#endif
330	racoon_free(sa);
331}
332
333struct etypes *
334dupetypes(orig)
335	struct etypes *orig;
336{
337	struct etypes *new;
338
339	if (!orig)
340		return NULL;
341
342	new = racoon_malloc(sizeof(struct etypes));
343	if (new == NULL)
344		return NULL;
345
346	new->type = orig->type;
347	new->next = NULL;
348
349	if (orig->next)
350		new->next=dupetypes(orig->next);
351
352	return new;
353}
354
355void
356deletypes(e)
357	struct etypes *e;
358{
359	if (e->next)
360		deletypes(e->next);
361	racoon_free(e);
362}
363
364/*
365 * insert into head of list.
366 */
367void
368insrmconf(new)
369	struct remoteconf *new;
370{
371	TAILQ_INSERT_HEAD(&rmtree, new, chain);
372}
373
374void
375remrmconf(rmconf)
376	struct remoteconf *rmconf;
377{
378	TAILQ_REMOVE(&rmtree, rmconf, chain);
379}
380
381void
382flushrmconf()
383{
384	struct remoteconf *p, *next;
385
386	for (p = TAILQ_FIRST(&rmtree); p; p = next) {
387		next = TAILQ_NEXT(p, chain);
388		remrmconf(p);
389		delrmconf(p);
390	}
391}
392
393void
394initrmconf()
395{
396	TAILQ_INIT(&rmtree);
397}
398
399void
400save_rmconf()
401{
402	rmtree_save=rmtree;
403	initrmconf();
404}
405
406void
407save_rmconf_flush()
408{
409	rmtree_tmp=rmtree;
410	rmtree=rmtree_save;
411	flushrmconf();
412	initrmconf();
413	rmtree=rmtree_tmp;
414}
415
416
417
418/* check exchange type to be acceptable */
419struct etypes *
420check_etypeok(rmconf, etype)
421	struct remoteconf *rmconf;
422	u_int8_t etype;
423{
424	struct etypes *e;
425
426	for (e = rmconf->etypes; e != NULL; e = e->next) {
427		if (e->type == etype)
428			break;
429	}
430
431	return e;
432}
433
434/*%%%*/
435struct isakmpsa *
436newisakmpsa()
437{
438	struct isakmpsa *new;
439
440	new = racoon_calloc(1, sizeof(*new));
441	if (new == NULL)
442		return NULL;
443
444	/*
445	 * Just for sanity, make sure this is initialized.  This is
446	 * filled in for real when the ISAKMP proposal is configured.
447	 */
448	new->vendorid = VENDORID_UNKNOWN;
449
450	new->next = NULL;
451	new->rmconf = NULL;
452#ifdef HAVE_GSSAPI
453	new->gssid = NULL;
454#endif
455
456	return new;
457}
458
459/*
460 * insert into tail of list.
461 */
462void
463insisakmpsa(new, rmconf)
464	struct isakmpsa *new;
465	struct remoteconf *rmconf;
466{
467	struct isakmpsa *p;
468
469	new->rmconf = rmconf;
470
471	if (rmconf->proposal == NULL) {
472		rmconf->proposal = new;
473		return;
474	}
475
476	for (p = rmconf->proposal; p->next != NULL; p = p->next)
477		;
478	p->next = new;
479
480	return;
481}
482
483struct remoteconf *
484foreachrmconf(rmconf_func_t rmconf_func, void *data)
485{
486  struct remoteconf *p, *ret = NULL;
487  RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
488    ret = (*rmconf_func)(p, data);
489    if (ret)
490      break;
491  }
492
493  return ret;
494}
495
496static void *
497dump_peers_identifiers (void *entry, void *arg)
498{
499	struct idspec *id = (struct idspec*) entry;
500	char buf[1024], *pbuf;
501	pbuf = buf;
502	pbuf += sprintf (pbuf, "\tpeers_identifier %s",
503			 s_idtype (id->idtype));
504	if (id->id)
505		pbuf += sprintf (pbuf, " \"%s\"", id->id->v);
506	plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
507	return NULL;
508}
509
510static struct remoteconf *
511dump_rmconf_single (struct remoteconf *p, void *data)
512{
513	struct etypes *etype = p->etypes;
514	struct isakmpsa *prop = p->proposal;
515	char buf[1024], *pbuf;
516
517	pbuf = buf;
518	pbuf += sprintf(pbuf, "remote %s", saddr2str(p->remote));
519	if (p->inherited_from)
520		pbuf += sprintf(pbuf, " inherit %s",
521				saddr2str(p->inherited_from->remote));
522	plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf);
523	pbuf = buf;
524	pbuf += sprintf(pbuf, "\texchange_type ");
525	while (etype) {
526		pbuf += sprintf (pbuf, "%s%s", s_etype(etype->type),
527				 etype->next != NULL ? ", " : ";\n");
528		etype = etype->next;
529	}
530	plog(LLV_INFO, LOCATION, NULL, "%s", buf);
531	plog(LLV_INFO, LOCATION, NULL, "\tdoi %s;\n", s_doi(p->doitype));
532	pbuf = buf;
533	pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype));
534	if (p->idvtype == IDTYPE_ASN1DN) {
535		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
536		plog(LLV_INFO, LOCATION, NULL, "\tcertificate_type %s \"%s\" \"%s\";\n",
537			p->certtype == ISAKMP_CERT_X509SIGN ? "x509" : "*UNKNOWN*",
538			p->mycertfile, p->myprivfile);
539		switch (p->getcert_method) {
540		  case 0:
541		  	break;
542		  case ISAKMP_GETCERT_PAYLOAD:
543			plog(LLV_INFO, LOCATION, NULL, "\t/* peers certificate from payload */\n");
544			break;
545		  case ISAKMP_GETCERT_LOCALFILE:
546			plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile \"%s\";\n", p->peerscertfile);
547			break;
548		  case ISAKMP_GETCERT_DNS:
549			plog(LLV_INFO, LOCATION, NULL, "\tpeer_certfile dnssec;\n");
550			break;
551		  default:
552			plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile *UNKNOWN* (%d)\n", p->getcert_method);
553		}
554	}
555	else {
556		if (p->idv)
557			pbuf += sprintf (pbuf, " \"%s\"", p->idv->v);
558		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
559		genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL);
560	}
561
562	plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n",
563		s_switch (p->send_cert));
564	plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n",
565		s_switch (p->send_cr));
566	plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n",
567		s_switch (p->verify_cert));
568	plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n",
569		s_switch (p->verify_identifier));
570	plog(LLV_INFO, LOCATION, NULL, "\tnat_traversal %s;\n",
571		p->nat_traversal == NATT_FORCE ?
572			"force" : s_switch (p->nat_traversal));
573	plog(LLV_INFO, LOCATION, NULL, "\tnonce_size %d;\n",
574		p->nonce_size);
575	plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n",
576		s_switch (p->passive));
577	plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n",
578		p->ike_frag == ISAKMP_FRAG_FORCE ?
579			"force" : s_switch (p->ike_frag));
580	plog(LLV_INFO, LOCATION, NULL, "\tesp_frag %d;\n", p->esp_frag);
581	plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n",
582		s_switch (p->ini_contact));
583	plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n",
584		s_switch (p->gen_policy));
585	plog(LLV_INFO, LOCATION, NULL, "\tsupport_proxy %s;\n",
586		s_switch (p->support_proxy));
587
588	while (prop) {
589		plog(LLV_INFO, LOCATION, NULL, "\n");
590		plog(LLV_INFO, LOCATION, NULL,
591			"\t/* prop_no=%d, trns_no=%d, rmconf=%s */\n",
592			prop->prop_no, prop->trns_no,
593			saddr2str(prop->rmconf->remote));
594		plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n");
595		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n",
596			(long)prop->lifetime);
597		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime bytes %zd;\n",
598			prop->lifebyte);
599		plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n",
600			alg_oakley_dhdef_name(prop->dh_group));
601		plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n",
602			alg_oakley_encdef_name(prop->enctype));
603		plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n",
604			alg_oakley_hashdef_name(prop->hashtype));
605		plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n",
606			alg_oakley_authdef_name(prop->authmethod));
607		plog(LLV_INFO, LOCATION, NULL, "\t}\n");
608		prop = prop->next;
609	}
610	plog(LLV_INFO, LOCATION, NULL, "}\n");
611	plog(LLV_INFO, LOCATION, NULL, "\n");
612
613	return NULL;
614}
615
616void
617dumprmconf()
618{
619	foreachrmconf (dump_rmconf_single, NULL);
620}
621
622struct idspec *
623newidspec()
624{
625	struct idspec *new;
626
627	new = racoon_calloc(1, sizeof(*new));
628	if (new == NULL)
629		return NULL;
630	new->idtype = IDTYPE_ADDRESS;
631
632	return new;
633}
634
635vchar_t *
636script_path_add(path)
637	vchar_t *path;
638{
639	char *script_dir;
640	vchar_t *new_path;
641	vchar_t *new_storage;
642	vchar_t **sp;
643	size_t len;
644	size_t size;
645
646	script_dir = lcconf->pathinfo[LC_PATHTYPE_SCRIPT];
647
648	/* Try to find the script in the script directory */
649	if ((path->v[0] != '/') && (script_dir != NULL)) {
650		len = strlen(script_dir) + sizeof("/") + path->l + 1;
651
652		if ((new_path = vmalloc(len)) == NULL) {
653			plog(LLV_ERROR, LOCATION, NULL,
654			    "Cannot allocate memory: %s\n", strerror(errno));
655			return NULL;
656		}
657
658		new_path->v[0] = '\0';
659		(void)strlcat(new_path->v, script_dir, len);
660		(void)strlcat(new_path->v, "/", len);
661		(void)strlcat(new_path->v, path->v, len);
662
663		vfree(path);
664		path = new_path;
665	}
666
667	return path;
668}
669
670
671struct isakmpsa *
672dupisakmpsa(struct isakmpsa *sa)
673{
674	struct isakmpsa *res=NULL;
675
676	if(sa == NULL)
677		return NULL;
678
679	res=newisakmpsa();
680	if(res == NULL)
681		return NULL;
682
683	*res=*sa;
684#ifdef HAVE_GSSAPI
685	/* XXX gssid
686	 */
687#endif
688	res->next=NULL;
689
690	if(sa->dhgrp != NULL)
691		oakley_setdhgroup (sa->dh_group, &(res->dhgrp));
692
693	return res;
694
695}
696