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