config.c revision 1.7
1/* $OpenBSD: config.c,v 1.7 2011/01/21 11:37:02 reyk Exp $ */ 2/* $vantronix: config.c,v 1.30 2010/05/28 15:34:35 reyk Exp $ */ 3 4/* 5 * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/param.h> 21#include <sys/types.h> 22#include <sys/queue.h> 23#include <sys/wait.h> 24#include <sys/socket.h> 25#include <sys/uio.h> 26 27#include <net/if.h> 28#include <netinet/in_systm.h> 29#include <netinet/in.h> 30#include <netinet/ip.h> 31#include <netinet/tcp.h> 32#include <arpa/inet.h> 33 34#include <stdlib.h> 35#include <stdio.h> 36#include <unistd.h> 37#include <string.h> 38#include <getopt.h> 39#include <signal.h> 40#include <errno.h> 41#include <err.h> 42#include <pwd.h> 43#include <event.h> 44 45#include "iked.h" 46#include "ikev2.h" 47 48struct iked_sa * 49config_new_sa(struct iked *env, int initiator) 50{ 51 struct iked_sa *sa; 52 53 if ((sa = calloc(1, sizeof(*sa))) == NULL) 54 return (NULL); 55 56 TAILQ_INIT(&sa->sa_proposals); 57 TAILQ_INIT(&sa->sa_childsas); 58 TAILQ_INIT(&sa->sa_flows); 59 sa->sa_hdr.sh_initiator = initiator; 60 sa->sa_type = IKED_SATYPE_LOCAL; 61 62 if (initiator) 63 sa->sa_hdr.sh_ispi = config_getspi(); 64 else 65 sa->sa_hdr.sh_rspi = config_getspi(); 66 67 gettimeofday(&sa->sa_timecreated, NULL); 68 memcpy(&sa->sa_timeused, &sa->sa_timecreated, sizeof(sa->sa_timeused)); 69 70 return (sa); 71} 72 73u_int64_t 74config_getspi(void) 75{ 76 u_int64_t spi; 77 78 spi = ((u_int64_t)arc4random() << 32) | arc4random(); 79 if (spi == 0) 80 return (config_getspi()); 81 82 return (spi); 83} 84 85void 86config_free_sa(struct iked *env, struct iked_sa *sa) 87{ 88 (void)RB_REMOVE(iked_sas, &env->sc_sas, sa); 89 90 config_free_proposals(&sa->sa_proposals, 0); 91 config_free_childsas(env, &sa->sa_childsas, NULL, NULL); 92 config_free_flows(env, &sa->sa_flows); 93 94 if (sa->sa_policy) { 95 (void)RB_REMOVE(iked_sapeers, &sa->sa_policy->pol_sapeers, sa); 96 policy_unref(env, sa->sa_policy); 97 } 98 99 ibuf_release(sa->sa_inonce); 100 ibuf_release(sa->sa_rnonce); 101 102 if (sa->sa_dhgroup != NULL) 103 group_free(sa->sa_dhgroup); 104 ibuf_release(sa->sa_dhiexchange); 105 ibuf_release(sa->sa_dhrexchange); 106 107 hash_free(sa->sa_prf); 108 hash_free(sa->sa_integr); 109 cipher_free(sa->sa_encr); 110 111 ibuf_release(sa->sa_key_d); 112 ibuf_release(sa->sa_key_iauth); 113 ibuf_release(sa->sa_key_rauth); 114 ibuf_release(sa->sa_key_iencr); 115 ibuf_release(sa->sa_key_rencr); 116 ibuf_release(sa->sa_key_iprf); 117 ibuf_release(sa->sa_key_rprf); 118 119 ibuf_release(sa->sa_1stmsg); 120 ibuf_release(sa->sa_2ndmsg); 121 122 ibuf_release(sa->sa_iid.id_buf); 123 ibuf_release(sa->sa_rid.id_buf); 124 ibuf_release(sa->sa_icert.id_buf); 125 ibuf_release(sa->sa_rcert.id_buf); 126 127 ibuf_release(sa->sa_eap.id_buf); 128 if (sa->sa_eapid != NULL) 129 free(sa->sa_eapid); 130 ibuf_release(sa->sa_eapmsk); 131 132 free(sa); 133} 134 135struct iked_policy * 136config_new_policy(struct iked *env) 137{ 138 struct iked_policy *pol; 139 140 if ((pol = calloc(1, sizeof(*pol))) == NULL) 141 return (NULL); 142 143 TAILQ_INIT(&pol->pol_proposals); 144 RB_INIT(&pol->pol_sapeers); 145 146 if (env != NULL) 147 RB_INSERT(iked_policies, &env->sc_policies, pol); 148 149 return (pol); 150} 151 152void 153config_free_policy(struct iked *env, struct iked_policy *pol) 154{ 155 struct iked_sa *sa; 156 157 if (pol->pol_flags & IKED_POLICY_REFCNT) 158 goto remove; 159 160 (void)RB_REMOVE(iked_policies, &env->sc_policies, pol); 161 162 RB_FOREACH(sa, iked_sapeers, &pol->pol_sapeers) { 163 /* Remove from the policy tree, but keep for existing SAs */ 164 if (sa->sa_policy == pol) 165 policy_ref(env, pol); 166 } 167 168 if (pol->pol_refcnt) 169 return; 170 171 remove: 172 config_free_proposals(&pol->pol_proposals, 0); 173 config_free_flows(env, &pol->pol_flows); 174 free(pol); 175} 176 177struct iked_proposal * 178config_add_proposal(struct iked_proposals *head, u_int id, u_int proto) 179{ 180 struct iked_proposal *pp; 181 182 TAILQ_FOREACH(pp, head, prop_entry) { 183 if (pp->prop_protoid == proto && 184 pp->prop_id == id) 185 return (pp); 186 } 187 188 if ((pp = calloc(1, sizeof(*pp))) == NULL) 189 return (NULL); 190 191 pp->prop_protoid = proto; 192 pp->prop_id = id; 193 194 TAILQ_INSERT_TAIL(head, pp, prop_entry); 195 196 return (pp); 197} 198 199void 200config_free_proposals(struct iked_proposals *head, u_int proto) 201{ 202 struct iked_proposal *prop, *next; 203 204 for (prop = TAILQ_FIRST(head); prop != NULL; prop = next) { 205 next = TAILQ_NEXT(prop, prop_entry); 206 207 /* Free any proposal or only selected SA proto */ 208 if (proto != 0 && prop->prop_protoid != proto) 209 continue; 210 211 log_debug("%s: free %p", __func__, prop); 212 213 TAILQ_REMOVE(head, prop, prop_entry); 214 if (prop->prop_nxforms) 215 free(prop->prop_xforms); 216 free(prop); 217 } 218} 219 220void 221config_free_flows(struct iked *env, struct iked_flows *head) 222{ 223 struct iked_flow *flow, *next; 224 225 for (flow = TAILQ_FIRST(head); flow != NULL; flow = next) { 226 next = TAILQ_NEXT(flow, flow_entry); 227 228 log_debug("%s: free %p", __func__, flow); 229 230 TAILQ_REMOVE(head, flow, flow_entry); 231 (void)pfkey_flow_delete(env->sc_pfkey, flow); 232 flow_free(flow); 233 } 234} 235 236void 237config_free_childsas(struct iked *env, struct iked_childsas *head, 238 struct iked_spi *peerspi, struct iked_spi *localspi) 239{ 240 struct iked_childsa *csa, *nextcsa; 241 242 if (localspi != NULL) 243 bzero(localspi, sizeof(*localspi)); 244 245 for (csa = TAILQ_FIRST(head); csa != NULL; csa = nextcsa) { 246 nextcsa = TAILQ_NEXT(csa, csa_entry); 247 248 if (peerspi != NULL) { 249 /* Only delete matching peer SPIs */ 250 if (peerspi->spi != csa->csa_peerspi) 251 continue; 252 253 /* Store assigned local SPI */ 254 if (localspi != NULL && localspi->spi == 0) 255 memcpy(localspi, &csa->csa_spi, 256 sizeof(*localspi)); 257 } 258 log_debug("%s: free %p", __func__, csa); 259 260 TAILQ_REMOVE(head, csa, csa_entry); 261 if (csa->csa_loaded) { 262 RB_REMOVE(iked_ipsecsas, &env->sc_ipsecsas, csa); 263 (void)pfkey_sa_delete(env->sc_pfkey, csa); 264 } 265 childsa_free(csa); 266 } 267} 268 269struct iked_transform * 270config_add_transform(struct iked_proposal *prop, u_int type, 271 u_int id, u_int length, u_int keylength) 272{ 273 struct iked_transform *xform; 274 struct iked_constmap *map = NULL; 275 int score = 1; 276 u_int i; 277 278 switch (type) { 279 case IKEV2_XFORMTYPE_ENCR: 280 map = ikev2_xformencr_map; 281 break; 282 case IKEV2_XFORMTYPE_PRF: 283 map = ikev2_xformprf_map; 284 break; 285 case IKEV2_XFORMTYPE_INTEGR: 286 map = ikev2_xformauth_map; 287 break; 288 case IKEV2_XFORMTYPE_DH: 289 map = ikev2_xformdh_map; 290 break; 291 case IKEV2_XFORMTYPE_ESN: 292 map = ikev2_xformesn_map; 293 break; 294 default: 295 log_debug("%s: invalid transform type %d", __func__, type); 296 return (NULL); 297 } 298 299 for (i = 0; i < prop->prop_nxforms; i++) { 300 xform = prop->prop_xforms + i; 301 if (xform->xform_type == type && 302 xform->xform_id == id && 303 xform->xform_length == length) 304 return (xform); 305 } 306 307 for (i = 0; i < prop->prop_nxforms; i++) { 308 xform = prop->prop_xforms + i; 309 if (xform->xform_type == type) { 310 switch (type) { 311 case IKEV2_XFORMTYPE_ENCR: 312 case IKEV2_XFORMTYPE_INTEGR: 313 score += 3; 314 break; 315 case IKEV2_XFORMTYPE_DH: 316 score += 2; 317 break; 318 default: 319 score += 1; 320 break; 321 } 322 } 323 } 324 325 if ((xform = realloc(prop->prop_xforms, 326 (prop->prop_nxforms + 1) * sizeof(*xform))) == NULL) { 327 return (NULL); 328 } 329 330 prop->prop_xforms = xform; 331 xform = prop->prop_xforms + prop->prop_nxforms++; 332 bzero(xform, sizeof(*xform)); 333 334 xform->xform_type = type; 335 xform->xform_id = id; 336 xform->xform_length = length; 337 xform->xform_keylength = keylength; 338 xform->xform_score = score; 339 xform->xform_map = map; 340 341 return (xform); 342} 343 344struct iked_transform * 345config_findtransform(struct iked_proposals *props, u_int8_t type) 346{ 347 struct iked_proposal *prop; 348 struct iked_transform *xform; 349 u_int i; 350 351 /* Search of the first transform with the desired type */ 352 TAILQ_FOREACH(prop, props, prop_entry) { 353 for (i = 0; i < prop->prop_nxforms; i++) { 354 xform = prop->prop_xforms + i; 355 if (xform->xform_type == type) 356 return (xform); 357 } 358 } 359 360 return (NULL); 361} 362 363struct iked_user * 364config_new_user(struct iked *env, struct iked_user *new) 365{ 366 struct iked_user *usr, *old; 367 368 if ((usr = calloc(1, sizeof(*usr))) == NULL) 369 return (NULL); 370 371 memcpy(usr, new, sizeof(*usr)); 372 373 if ((old = RB_INSERT(iked_users, &env->sc_users, usr)) != NULL) { 374 /* Update the password of an existing user*/ 375 memcpy(old, new, sizeof(old)); 376 377 log_debug("%s: updating user %s", __func__, usr->usr_name); 378 free(usr); 379 380 return (old); 381 } 382 383 log_debug("%s: inserting new user %s", __func__, usr->usr_name); 384 return (usr); 385} 386 387/* 388 * Inter-process communication of configuration items. 389 */ 390 391int 392config_setcoupled(struct iked *env, u_int couple) 393{ 394 u_int type; 395 396 type = couple ? IMSG_CTL_COUPLE : IMSG_CTL_DECOUPLE; 397 imsg_compose_proc(env, PROC_IKEV1, type, -1, NULL, 0); 398 imsg_compose_proc(env, PROC_IKEV2, type, -1, NULL, 0); 399 400 return (0); 401} 402 403int 404config_getcoupled(struct iked *env, u_int type) 405{ 406 return (pfkey_couple(env->sc_pfkey, &env->sc_sas, 407 type == IMSG_CTL_COUPLE ? 1 : 0)); 408} 409 410int 411config_setmode(struct iked *env, u_int passive) 412{ 413 u_int type; 414 415 type = passive ? IMSG_CTL_PASSIVE : IMSG_CTL_ACTIVE; 416 imsg_compose_proc(env, PROC_IKEV1, type, -1, NULL, 0); 417 imsg_compose_proc(env, PROC_IKEV2, type, -1, NULL, 0); 418 419 return (0); 420} 421 422int 423config_getmode(struct iked *env, u_int type) 424{ 425 u_int8_t old; 426 u_char *mode[] = { "active", "passive" }; 427 428 old = env->sc_passive ? 1 : 0; 429 env->sc_passive = type == IMSG_CTL_PASSIVE ? 1 : 0; 430 431 if (old == env->sc_passive) 432 return (0); 433 434 log_debug("%s: mode %s -> %s", __func__, 435 mode[old], mode[env->sc_passive]); 436 437 return (0); 438} 439 440int 441config_setreset(struct iked *env, u_int mode, enum iked_procid id) 442{ 443 imsg_compose_proc(env, id, IMSG_CTL_RESET, -1, &mode, sizeof(mode)); 444 return (0); 445} 446 447int 448config_getreset(struct iked *env, struct imsg *imsg) 449{ 450 struct iked_policy *pol, *nextpol; 451 struct iked_sa *sa, *nextsa; 452 struct iked_user *usr, *nextusr; 453 u_int mode; 454 455 IMSG_SIZE_CHECK(imsg, &mode); 456 memcpy(&mode, imsg->data, sizeof(mode)); 457 458 if (mode == RESET_ALL || mode == RESET_POLICY) { 459 log_debug("%s: flushing policies", __func__); 460 for (pol = RB_MIN(iked_policies, &env->sc_policies); 461 pol != NULL; pol = nextpol) { 462 nextpol = 463 RB_NEXT(iked_policies, &env->sc_policies, pol); 464 config_free_policy(env, pol); 465 } 466 } 467 468 if (mode == RESET_ALL || mode == RESET_SA) { 469 log_debug("%s: flushing SAs", __func__); 470 for (sa = RB_MIN(iked_sas, &env->sc_sas); 471 sa != NULL; sa = nextsa) { 472 nextsa = RB_NEXT(iked_sas, &env->sc_sas, sa); 473 config_free_sa(env, sa); 474 } 475 } 476 477 if (mode == RESET_ALL || mode == RESET_USER) { 478 log_debug("%s: flushing users", __func__); 479 for (usr = RB_MIN(iked_users, &env->sc_users); 480 usr != NULL; usr = nextusr) { 481 nextusr = RB_NEXT(iked_users, &env->sc_users, usr); 482 RB_REMOVE(iked_users, &env->sc_users, usr); 483 free(usr); 484 } 485 } 486 487 return (0); 488} 489 490int 491config_setsocket(struct iked *env, struct sockaddr_storage *ss, 492 in_port_t port, enum iked_procid id) 493{ 494 int s; 495 496 if ((s = udp_bind((struct sockaddr *)ss, port)) == -1) 497 return (-1); 498 imsg_compose_proc(env, id, IMSG_UDP_SOCKET, s, 499 ss, sizeof(*ss)); 500 return (0); 501} 502 503int 504config_getsocket(struct iked *env, struct imsg *imsg, 505 void (*cb)(int, short, void *)) 506{ 507 struct iked_socket *sock, **sptr; 508 509 log_debug("%s: received socket fd %d", __func__, imsg->fd); 510 511 if ((sock = calloc(1, sizeof(*sock))) == NULL) 512 fatal("config_getsocket: calloc"); 513 514 IMSG_SIZE_CHECK(imsg, &sock->sock_addr); 515 516 memcpy(&sock->sock_addr, imsg->data, sizeof(sock->sock_addr)); 517 sock->sock_fd = imsg->fd; 518 sock->sock_env = env; 519 520 switch (sock->sock_addr.ss_family) { 521 case AF_INET: 522 sptr = &env->sc_sock4; 523 break; 524 case AF_INET6: 525 sptr = &env->sc_sock6; 526 break; 527 default: 528 fatal("config_getsocket: socket af"); 529 /* NOTREACHED */ 530 } 531 if (*sptr == NULL) 532 *sptr = sock; 533 534 event_set(&sock->sock_ev, sock->sock_fd, 535 EV_READ|EV_PERSIST, cb, sock); 536 event_add(&sock->sock_ev, NULL); 537 538 return (0); 539} 540 541int 542config_setpfkey(struct iked *env, enum iked_procid id) 543{ 544 int s; 545 546 if ((s = pfkey_socket()) == -1) 547 return (-1); 548 imsg_compose_proc(env, id, IMSG_PFKEY_SOCKET, s, NULL, 0); 549 return (0); 550} 551 552int 553config_getpfkey(struct iked *env, struct imsg *imsg) 554{ 555 log_debug("%s: received pfkey fd %d", __func__, imsg->fd); 556 pfkey_init(env, imsg->fd); 557 return (0); 558} 559 560int 561config_setuser(struct iked *env, struct iked_user *usr, enum iked_procid id) 562{ 563 if (env->sc_opts & IKED_OPT_NOACTION) { 564 print_user(usr); 565 return (0); 566 } 567 568 imsg_compose_proc(env, id, IMSG_CFG_USER, -1, usr, sizeof(*usr)); 569 return (0); 570} 571 572int 573config_getuser(struct iked *env, struct imsg *imsg) 574{ 575 struct iked_user usr; 576 577 IMSG_SIZE_CHECK(imsg, &usr); 578 memcpy(&usr, imsg->data, sizeof(usr)); 579 580 if (config_new_user(env, &usr) == NULL) 581 return (-1); 582 583 print_user(&usr); 584 585 return (0); 586} 587 588int 589config_setpolicy(struct iked *env, struct iked_policy *pol, 590 enum iked_procid id) 591{ 592 struct iked_proposal *prop; 593 struct iked_flow *flow; 594 struct iked_transform *xform; 595 size_t size, iovcnt, j, c = 0; 596 struct iovec iov[IOV_MAX]; 597 598 iovcnt = 1; 599 size = sizeof(*pol); 600 TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) { 601 size += (prop->prop_nxforms * sizeof(*xform)) + 602 (sizeof(*prop)); 603 iovcnt += prop->prop_nxforms + 1; 604 } 605 606 size += pol->pol_nflows * sizeof(*flow); 607 iovcnt += pol->pol_nflows; 608 609 if (iovcnt > IOV_MAX) { 610 log_warn("%s: too many proposals/flows", __func__); 611 return (-1); 612 } 613 614 iov[c].iov_base = pol; 615 iov[c++].iov_len = sizeof(*pol); 616 617 TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) { 618 iov[c].iov_base = prop; 619 iov[c++].iov_len = sizeof(*prop); 620 621 for (j = 0; j < prop->prop_nxforms; j++) { 622 xform = prop->prop_xforms + j; 623 624 iov[c].iov_base = xform; 625 iov[c++].iov_len = sizeof(*xform); 626 } 627 } 628 629 TAILQ_FOREACH(flow, &pol->pol_flows, flow_entry) { 630 iov[c].iov_base = flow; 631 iov[c++].iov_len = sizeof(*flow); 632 } 633 634 if (env->sc_opts & IKED_OPT_NOACTION) { 635 print_policy(pol); 636 return (0); 637 } 638 639 if (imsg_composev_proc(env, id, IMSG_CFG_POLICY, -1, 640 iov, iovcnt) == -1) 641 return (-1); 642 643 return (0); 644} 645 646int 647config_getpolicy(struct iked *env, struct imsg *imsg) 648{ 649 struct iked_policy *pol, *old; 650 struct iked_proposal pp, *prop; 651 struct iked_transform xf, *xform; 652 struct iked_flow *flow; 653 off_t offset = 0; 654 u_int i, j; 655 u_int8_t *buf = (u_int8_t *)imsg->data; 656 657 IMSG_SIZE_CHECK(imsg, pol); 658 log_debug("%s: received policy", __func__); 659 660 if ((pol = config_new_policy(NULL)) == NULL) 661 fatal("config_getpolicy: new policy"); 662 663 memcpy(pol, buf, sizeof(*pol)); 664 offset += sizeof(*pol); 665 666 TAILQ_INIT(&pol->pol_proposals); 667 TAILQ_INIT(&pol->pol_flows); 668 669 for (i = 0; i < pol->pol_nproposals; i++) { 670 memcpy(&pp, buf + offset, sizeof(pp)); 671 offset += sizeof(pp); 672 673 if ((prop = config_add_proposal(&pol->pol_proposals, 674 pp.prop_id, pp.prop_protoid)) == NULL) 675 fatal("config_getpolicy: add proposal"); 676 677 for (j = 0; j < pp.prop_nxforms; j++) { 678 memcpy(&xf, buf + offset, sizeof(xf)); 679 offset += sizeof(xf); 680 681 if ((xform = config_add_transform(prop, xf.xform_type, 682 xf.xform_id, xf.xform_length, 683 xf.xform_keylength)) == NULL) 684 fatal("config_getpolicy: add transform"); 685 } 686 } 687 688 for (i = 0; i < pol->pol_nflows; i++) { 689 if ((flow = calloc(1, sizeof(*flow))) == NULL) 690 fatal("config_getpolicy: new flow"); 691 692 memcpy(flow, buf + offset, sizeof(*flow)); 693 offset += sizeof(*flow); 694 695 TAILQ_INSERT_TAIL(&pol->pol_flows, flow, flow_entry); 696 } 697 698 if ((old = RB_INSERT(iked_policies, 699 &env->sc_policies, pol)) != NULL) { 700 config_free_policy(env, old); 701 RB_INSERT(iked_policies, &env->sc_policies, pol); 702 } 703 704 if (pol->pol_flags & IKED_POLICY_DEFAULT) 705 env->sc_defaultcon = pol; 706 707 print_policy(pol); 708 709 return (0); 710} 711