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(rmconf,etype)420 check_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 /*%%%*/
435 struct isakmpsa *
newisakmpsa()436 newisakmpsa()
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 */
462 void
insisakmpsa(new,rmconf)463 insisakmpsa(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
483 struct remoteconf *
foreachrmconf(rmconf_func_t rmconf_func,void * data)484 foreachrmconf(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
496 static void *
dump_peers_identifiers(void * entry,void * arg)497 dump_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
510 static struct remoteconf *
dump_rmconf_single(struct remoteconf * p,void * data)511 dump_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
616 void
dumprmconf()617 dumprmconf()
618 {
619 foreachrmconf (dump_rmconf_single, NULL);
620 }
621
622 struct idspec *
newidspec()623 newidspec()
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
635 vchar_t *
script_path_add(path)636 script_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
671 struct isakmpsa *
dupisakmpsa(struct isakmpsa * sa)672 dupisakmpsa(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