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( struct remoteconf *rmconf, u_int8_t etype)
421{
422	struct etypes *e;
423
424	for (e = rmconf->etypes; e != NULL; e = e->next) {
425		if (e->type == etype)
426			break;
427	}
428
429	return e;
430}
431
432/*%%%*/
433struct isakmpsa *
434newisakmpsa()
435{
436	struct isakmpsa *new;
437
438	new = racoon_calloc(1, sizeof(*new));
439	if (new == NULL)
440		return NULL;
441
442	/*
443	 * Just for sanity, make sure this is initialized.  This is
444	 * filled in for real when the ISAKMP proposal is configured.
445	 */
446	new->vendorid = VENDORID_UNKNOWN;
447
448	new->next = NULL;
449	new->rmconf = NULL;
450#ifdef HAVE_GSSAPI
451	new->gssid = NULL;
452#endif
453
454	return new;
455}
456
457/*
458 * insert into tail of list.
459 */
460void
461insisakmpsa(new, rmconf)
462	struct isakmpsa *new;
463	struct remoteconf *rmconf;
464{
465	struct isakmpsa *p;
466
467	new->rmconf = rmconf;
468
469	if (rmconf->proposal == NULL) {
470		rmconf->proposal = new;
471		return;
472	}
473
474	for (p = rmconf->proposal; p->next != NULL; p = p->next)
475		;
476	p->next = new;
477
478	return;
479}
480
481struct remoteconf *
482foreachrmconf(rmconf_func_t rmconf_func, void *data)
483{
484  struct remoteconf *p, *ret = NULL;
485  RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
486    ret = (*rmconf_func)(p, data);
487    if (ret)
488      break;
489  }
490
491  return ret;
492}
493
494static void *
495dump_peers_identifiers (void *entry, void *arg)
496{
497	struct idspec *id = (struct idspec*) entry;
498	char buf[1024], *pbuf;
499	pbuf = buf;
500	pbuf += sprintf (pbuf, "\tpeers_identifier %s",
501			 s_idtype (id->idtype));
502	if (id->id)
503		pbuf += sprintf (pbuf, " \"%s\"", id->id->v);
504	plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
505	return NULL;
506}
507
508static struct remoteconf *
509dump_rmconf_single (struct remoteconf *p, void *data)
510{
511	struct etypes *etype = p->etypes;
512	struct isakmpsa *prop = p->proposal;
513	char buf[1024], *pbuf;
514
515	pbuf = buf;
516	pbuf += sprintf(pbuf, "remote %s", saddr2str(p->remote));
517	if (p->inherited_from)
518		pbuf += sprintf(pbuf, " inherit %s",
519				saddr2str(p->inherited_from->remote));
520	plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf);
521	pbuf = buf;
522	pbuf += sprintf(pbuf, "\texchange_type ");
523	while (etype) {
524		pbuf += sprintf (pbuf, "%s%s", s_etype(etype->type),
525				 etype->next != NULL ? ", " : ";\n");
526		etype = etype->next;
527	}
528	plog(LLV_INFO, LOCATION, NULL, "%s", buf);
529	plog(LLV_INFO, LOCATION, NULL, "\tdoi %s;\n", s_doi(p->doitype));
530	pbuf = buf;
531	pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype));
532	if (p->idvtype == IDTYPE_ASN1DN) {
533		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
534		plog(LLV_INFO, LOCATION, NULL, "\tcertificate_type %s \"%s\" \"%s\";\n",
535			p->certtype == ISAKMP_CERT_X509SIGN ? "x509" : "*UNKNOWN*",
536			p->mycertfile, p->myprivfile);
537		switch (p->getcert_method) {
538		  case 0:
539		  	break;
540		  case ISAKMP_GETCERT_PAYLOAD:
541			plog(LLV_INFO, LOCATION, NULL, "\t/* peers certificate from payload */\n");
542			break;
543		  case ISAKMP_GETCERT_LOCALFILE:
544			plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile \"%s\";\n", p->peerscertfile);
545			break;
546		  case ISAKMP_GETCERT_DNS:
547			plog(LLV_INFO, LOCATION, NULL, "\tpeer_certfile dnssec;\n");
548			break;
549		  default:
550			plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile *UNKNOWN* (%d)\n", p->getcert_method);
551		}
552	}
553	else {
554		if (p->idv)
555			pbuf += sprintf (pbuf, " \"%s\"", p->idv->v);
556		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
557		genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL);
558	}
559
560	plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n",
561		s_switch (p->send_cert));
562	plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n",
563		s_switch (p->send_cr));
564	plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n",
565		s_switch (p->verify_cert));
566	plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n",
567		s_switch (p->verify_identifier));
568	plog(LLV_INFO, LOCATION, NULL, "\tnat_traversal %s;\n",
569		p->nat_traversal == NATT_FORCE ?
570			"force" : s_switch (p->nat_traversal));
571	plog(LLV_INFO, LOCATION, NULL, "\tnonce_size %d;\n",
572		p->nonce_size);
573	plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n",
574		s_switch (p->passive));
575	plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n",
576		p->ike_frag == ISAKMP_FRAG_FORCE ?
577			"force" : s_switch (p->ike_frag));
578	plog(LLV_INFO, LOCATION, NULL, "\tesp_frag %d;\n", p->esp_frag);
579	plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n",
580		s_switch (p->ini_contact));
581	plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n",
582		s_switch (p->gen_policy));
583	plog(LLV_INFO, LOCATION, NULL, "\tsupport_proxy %s;\n",
584		s_switch (p->support_proxy));
585
586	while (prop) {
587		plog(LLV_INFO, LOCATION, NULL, "\n");
588		plog(LLV_INFO, LOCATION, NULL,
589			"\t/* prop_no=%d, trns_no=%d, rmconf=%s */\n",
590			prop->prop_no, prop->trns_no,
591			saddr2str(prop->rmconf->remote));
592		plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n");
593		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n",
594			(long)prop->lifetime);
595		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime bytes %zd;\n",
596			prop->lifebyte);
597		plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n",
598			alg_oakley_dhdef_name(prop->dh_group));
599		plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n",
600			alg_oakley_encdef_name(prop->enctype));
601		plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n",
602			alg_oakley_hashdef_name(prop->hashtype));
603		plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n",
604			alg_oakley_authdef_name(prop->authmethod));
605		plog(LLV_INFO, LOCATION, NULL, "\t}\n");
606		prop = prop->next;
607	}
608	plog(LLV_INFO, LOCATION, NULL, "}\n");
609	plog(LLV_INFO, LOCATION, NULL, "\n");
610
611	return NULL;
612}
613
614void
615dumprmconf()
616{
617	foreachrmconf (dump_rmconf_single, NULL);
618}
619
620struct idspec *
621newidspec()
622{
623	struct idspec *new;
624
625	new = racoon_calloc(1, sizeof(*new));
626	if (new == NULL)
627		return NULL;
628	new->idtype = IDTYPE_ADDRESS;
629
630	return new;
631}
632
633vchar_t *
634script_path_add(path)
635	vchar_t *path;
636{
637	char *script_dir;
638	vchar_t *new_path;
639	vchar_t *new_storage;
640	vchar_t **sp;
641	size_t len;
642	size_t size;
643
644	script_dir = lcconf->pathinfo[LC_PATHTYPE_SCRIPT];
645
646	/* Try to find the script in the script directory */
647	if ((path->v[0] != '/') && (script_dir != NULL)) {
648		len = strlen(script_dir) + sizeof("/") + path->l + 1;
649
650		if ((new_path = vmalloc(len)) == NULL) {
651			plog(LLV_ERROR, LOCATION, NULL,
652			    "Cannot allocate memory: %s\n", strerror(errno));
653			return NULL;
654		}
655
656		new_path->v[0] = '\0';
657		(void)strlcat(new_path->v, script_dir, len);
658		(void)strlcat(new_path->v, "/", len);
659		(void)strlcat(new_path->v, path->v, len);
660
661		vfree(path);
662		path = new_path;
663	}
664
665	return path;
666}
667
668
669struct isakmpsa *
670dupisakmpsa(struct isakmpsa *sa)
671{
672	struct isakmpsa *res=NULL;
673
674	if(sa == NULL)
675		return NULL;
676
677	res=newisakmpsa();
678	if(res == NULL)
679		return NULL;
680
681	*res=*sa;
682#ifdef HAVE_GSSAPI
683	/* XXX gssid
684	 */
685#endif
686	res->next=NULL;
687
688	if(sa->dhgrp != NULL)
689		oakley_setdhgroup (sa->dh_group, &(res->dhgrp));
690
691	return res;
692
693}
694