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
TAILQ_HEAD(_rmtree,remoteconf)80 static TAILQ_HEAD(_rmtree, remoteconf) rmtree, rmtree_save, rmtree_tmp;
81
82 /*
83 * Script hook names and script hook paths
84 */
85 char *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 */
96 struct remoteconf *
getrmconf_strict(remote,allow_anon)97 getrmconf_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
161 struct remoteconf *
getrmconf(remote)162 getrmconf(remote)
163 struct sockaddr *remote;
164 {
165 return getrmconf_strict(remote, 1);
166 }
167
168 struct remoteconf *
newrmconf()169 newrmconf()
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
227 struct remoteconf *
copyrmconf(remote)228 copyrmconf(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
246 void *
dupidvl(entry,arg)247 dupidvl(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
267 struct remoteconf *
duprmconf(rmconf)268 duprmconf (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
290 static void
idspec_free(void * data)291 idspec_free(void *data)
292 {
293 vfree (((struct idspec *)data)->id);
294 free (data);
295 }
296
297 void
delrmconf(rmconf)298 delrmconf(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
318 void
delisakmpsa(sa)319 delisakmpsa(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
333 struct etypes *
dupetypes(orig)334 dupetypes(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
355 void
deletypes(e)356 deletypes(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 */
367 void
insrmconf(new)368 insrmconf(new)
369 struct remoteconf *new;
370 {
371 TAILQ_INSERT_HEAD(&rmtree, new, chain);
372 }
373
374 void
remrmconf(rmconf)375 remrmconf(rmconf)
376 struct remoteconf *rmconf;
377 {
378 TAILQ_REMOVE(&rmtree, rmconf, chain);
379 }
380
381 void
flushrmconf()382 flushrmconf()
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
393 void
initrmconf()394 initrmconf()
395 {
396 TAILQ_INIT(&rmtree);
397 }
398
399 void
save_rmconf()400 save_rmconf()
401 {
402 rmtree_save=rmtree;
403 initrmconf();
404 }
405
406 void
save_rmconf_flush()407 save_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 */
419 struct etypes *
check_etypeok(struct remoteconf * rmconf,u_int8_t etype)420 check_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 /*%%%*/
433 struct isakmpsa *
newisakmpsa()434 newisakmpsa()
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 */
460 void
insisakmpsa(new,rmconf)461 insisakmpsa(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
481 struct remoteconf *
foreachrmconf(rmconf_func_t rmconf_func,void * data)482 foreachrmconf(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
494 static void *
dump_peers_identifiers(void * entry,void * arg)495 dump_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
508 static struct remoteconf *
dump_rmconf_single(struct remoteconf * p,void * data)509 dump_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
614 void
dumprmconf()615 dumprmconf()
616 {
617 foreachrmconf (dump_rmconf_single, NULL);
618 }
619
620 struct idspec *
newidspec()621 newidspec()
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
633 vchar_t *
script_path_add(path)634 script_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
669 struct isakmpsa *
dupisakmpsa(struct isakmpsa * sa)670 dupisakmpsa(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