config.c revision 1.15
1/* $OpenBSD: config.c,v 1.15 2012/07/02 13:03:24 mikeb 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 TAILQ_INIT(&sa->sa_requests); 60 TAILQ_INIT(&sa->sa_responses); 61 sa->sa_hdr.sh_initiator = initiator; 62 sa->sa_type = IKED_SATYPE_LOCAL; 63 64 if (initiator) 65 sa->sa_hdr.sh_ispi = config_getspi(); 66 else 67 sa->sa_hdr.sh_rspi = config_getspi(); 68 69 gettimeofday(&sa->sa_timecreated, NULL); 70 memcpy(&sa->sa_timeused, &sa->sa_timecreated, sizeof(sa->sa_timeused)); 71 72 return (sa); 73} 74 75u_int64_t 76config_getspi(void) 77{ 78 u_int64_t spi; 79 80 spi = ((u_int64_t)arc4random() << 32) | arc4random(); 81 if (spi == 0) 82 return (config_getspi()); 83 84 return (spi); 85} 86 87void 88config_free_sa(struct iked *env, struct iked_sa *sa) 89{ 90 (void)RB_REMOVE(iked_sas, &env->sc_sas, sa); 91 92 timer_deregister(env, &sa->sa_timer); 93 94 config_free_proposals(&sa->sa_proposals, 0); 95 config_free_childsas(env, &sa->sa_childsas, NULL, NULL); 96 sa_free_flows(env, &sa->sa_flows); 97 98 if (sa->sa_policy) { 99 (void)RB_REMOVE(iked_sapeers, &sa->sa_policy->pol_sapeers, sa); 100 policy_unref(env, sa->sa_policy); 101 } 102 103 ikev2_msg_flushqueue(env, &sa->sa_requests); 104 ikev2_msg_flushqueue(env, &sa->sa_responses); 105 106 ibuf_release(sa->sa_inonce); 107 ibuf_release(sa->sa_rnonce); 108 109 if (sa->sa_dhgroup != NULL) 110 group_free(sa->sa_dhgroup); 111 ibuf_release(sa->sa_dhiexchange); 112 ibuf_release(sa->sa_dhrexchange); 113 114 hash_free(sa->sa_prf); 115 hash_free(sa->sa_integr); 116 cipher_free(sa->sa_encr); 117 118 ibuf_release(sa->sa_key_d); 119 ibuf_release(sa->sa_key_iauth); 120 ibuf_release(sa->sa_key_rauth); 121 ibuf_release(sa->sa_key_iencr); 122 ibuf_release(sa->sa_key_rencr); 123 ibuf_release(sa->sa_key_iprf); 124 ibuf_release(sa->sa_key_rprf); 125 126 ibuf_release(sa->sa_1stmsg); 127 ibuf_release(sa->sa_2ndmsg); 128 129 ibuf_release(sa->sa_iid.id_buf); 130 ibuf_release(sa->sa_rid.id_buf); 131 ibuf_release(sa->sa_icert.id_buf); 132 ibuf_release(sa->sa_rcert.id_buf); 133 134 ibuf_release(sa->sa_eap.id_buf); 135 if (sa->sa_eapid != NULL) 136 free(sa->sa_eapid); 137 ibuf_release(sa->sa_eapmsk); 138 139 free(sa); 140} 141 142struct iked_policy * 143config_new_policy(struct iked *env) 144{ 145 struct iked_policy *pol; 146 147 if ((pol = calloc(1, sizeof(*pol))) == NULL) 148 return (NULL); 149 150 TAILQ_INIT(&pol->pol_proposals); 151 RB_INIT(&pol->pol_sapeers); 152 153 return (pol); 154} 155 156void 157config_free_policy(struct iked *env, struct iked_policy *pol) 158{ 159 struct iked_sa *sa; 160 161 if (pol->pol_flags & IKED_POLICY_REFCNT) 162 goto remove; 163 164 TAILQ_REMOVE(&env->sc_policies, pol, pol_entry); 165 166 RB_FOREACH(sa, iked_sapeers, &pol->pol_sapeers) { 167 /* Remove from the policy tree, but keep for existing SAs */ 168 if (sa->sa_policy == pol) 169 policy_ref(env, pol); 170 } 171 172 if (pol->pol_refcnt) 173 return; 174 175 remove: 176 config_free_proposals(&pol->pol_proposals, 0); 177 config_free_flows(env, &pol->pol_flows); 178 free(pol); 179} 180 181struct iked_proposal * 182config_add_proposal(struct iked_proposals *head, u_int id, u_int proto) 183{ 184 struct iked_proposal *pp; 185 186 TAILQ_FOREACH(pp, head, prop_entry) { 187 if (pp->prop_protoid == proto && 188 pp->prop_id == id) 189 return (pp); 190 } 191 192 if ((pp = calloc(1, sizeof(*pp))) == NULL) 193 return (NULL); 194 195 pp->prop_protoid = proto; 196 pp->prop_id = id; 197 198 TAILQ_INSERT_TAIL(head, pp, prop_entry); 199 200 return (pp); 201} 202 203void 204config_free_proposals(struct iked_proposals *head, u_int proto) 205{ 206 struct iked_proposal *prop, *next; 207 208 for (prop = TAILQ_FIRST(head); prop != NULL; prop = next) { 209 next = TAILQ_NEXT(prop, prop_entry); 210 211 /* Free any proposal or only selected SA proto */ 212 if (proto != 0 && prop->prop_protoid != proto) 213 continue; 214 215 log_debug("%s: free %p", __func__, prop); 216 217 TAILQ_REMOVE(head, prop, prop_entry); 218 if (prop->prop_nxforms) 219 free(prop->prop_xforms); 220 free(prop); 221 } 222} 223 224void 225config_free_flows(struct iked *env, struct iked_flows *head) 226{ 227 struct iked_flow *flow, *next; 228 229 for (flow = RB_MIN(iked_flows, head); flow != NULL; flow = next) { 230 next = RB_NEXT(iked_flows, head, flow); 231 log_debug("%s: free %p", __func__, flow); 232 RB_REMOVE(iked_flows, head, flow); 233 flow_free(flow); 234 } 235} 236 237void 238config_free_childsas(struct iked *env, struct iked_childsas *head, 239 struct iked_spi *peerspi, struct iked_spi *localspi) 240{ 241 struct iked_childsa *csa, *nextcsa; 242 243 if (localspi != NULL) 244 bzero(localspi, sizeof(*localspi)); 245 246 for (csa = TAILQ_FIRST(head); csa != NULL; csa = nextcsa) { 247 nextcsa = TAILQ_NEXT(csa, csa_entry); 248 249 if (peerspi != NULL) { 250 /* Only delete matching peer SPIs */ 251 if (peerspi->spi != csa->csa_peerspi) 252 continue; 253 254 /* Store assigned local SPI */ 255 if (localspi != NULL && localspi->spi == 0) 256 memcpy(localspi, &csa->csa_spi, 257 sizeof(*localspi)); 258 } 259 log_debug("%s: free %p", __func__, csa); 260 261 TAILQ_REMOVE(head, csa, csa_entry); 262 if (csa->csa_loaded) { 263 RB_REMOVE(iked_activesas, &env->sc_activesas, csa); 264 (void)pfkey_sa_delete(env->sc_pfkey, csa); 265 } 266 childsa_free(csa); 267 } 268} 269 270struct iked_transform * 271config_add_transform(struct iked_proposal *prop, u_int type, 272 u_int id, u_int length, u_int keylength) 273{ 274 struct iked_transform *xform; 275 struct iked_constmap *map = NULL; 276 int score = 1; 277 u_int i; 278 279 switch (type) { 280 case IKEV2_XFORMTYPE_ENCR: 281 map = ikev2_xformencr_map; 282 break; 283 case IKEV2_XFORMTYPE_PRF: 284 map = ikev2_xformprf_map; 285 break; 286 case IKEV2_XFORMTYPE_INTEGR: 287 map = ikev2_xformauth_map; 288 break; 289 case IKEV2_XFORMTYPE_DH: 290 map = ikev2_xformdh_map; 291 break; 292 case IKEV2_XFORMTYPE_ESN: 293 map = ikev2_xformesn_map; 294 break; 295 default: 296 log_debug("%s: invalid transform type %d", __func__, type); 297 return (NULL); 298 } 299 300 for (i = 0; i < prop->prop_nxforms; i++) { 301 xform = prop->prop_xforms + i; 302 if (xform->xform_type == type && 303 xform->xform_id == id && 304 xform->xform_length == length) 305 return (xform); 306 } 307 308 for (i = 0; i < prop->prop_nxforms; i++) { 309 xform = prop->prop_xforms + i; 310 if (xform->xform_type == type) { 311 switch (type) { 312 case IKEV2_XFORMTYPE_ENCR: 313 case IKEV2_XFORMTYPE_INTEGR: 314 score += 3; 315 break; 316 case IKEV2_XFORMTYPE_DH: 317 score += 2; 318 break; 319 default: 320 score += 1; 321 break; 322 } 323 } 324 } 325 326 if ((xform = realloc(prop->prop_xforms, 327 (prop->prop_nxforms + 1) * sizeof(*xform))) == NULL) { 328 return (NULL); 329 } 330 331 prop->prop_xforms = xform; 332 xform = prop->prop_xforms + prop->prop_nxforms++; 333 bzero(xform, sizeof(*xform)); 334 335 xform->xform_type = type; 336 xform->xform_id = id; 337 xform->xform_length = length; 338 xform->xform_keylength = keylength; 339 xform->xform_score = score; 340 xform->xform_map = map; 341 342 return (xform); 343} 344 345struct iked_transform * 346config_findtransform(struct iked_proposals *props, u_int8_t type) 347{ 348 struct iked_proposal *prop; 349 struct iked_transform *xform; 350 u_int i; 351 352 /* Search of the first transform with the desired type */ 353 TAILQ_FOREACH(prop, props, prop_entry) { 354 for (i = 0; i < prop->prop_nxforms; i++) { 355 xform = prop->prop_xforms + i; 356 if (xform->xform_type == type) 357 return (xform); 358 } 359 } 360 361 return (NULL); 362} 363 364struct iked_user * 365config_new_user(struct iked *env, struct iked_user *new) 366{ 367 struct iked_user *usr, *old; 368 369 if ((usr = calloc(1, sizeof(*usr))) == NULL) 370 return (NULL); 371 372 memcpy(usr, new, sizeof(*usr)); 373 374 if ((old = RB_INSERT(iked_users, &env->sc_users, usr)) != NULL) { 375 /* Update the password of an existing user*/ 376 memcpy(old, new, sizeof(*old)); 377 378 log_debug("%s: updating user %s", __func__, usr->usr_name); 379 free(usr); 380 381 return (old); 382 } 383 384 log_debug("%s: inserting new user %s", __func__, usr->usr_name); 385 return (usr); 386} 387 388/* 389 * Inter-process communication of configuration items. 390 */ 391 392int 393config_setcoupled(struct iked *env, u_int couple) 394{ 395 u_int type; 396 397 type = couple ? IMSG_CTL_COUPLE : IMSG_CTL_DECOUPLE; 398 proc_compose_imsg(env, PROC_IKEV1, type, -1, NULL, 0); 399 proc_compose_imsg(env, PROC_IKEV2, type, -1, NULL, 0); 400 401 return (0); 402} 403 404int 405config_getcoupled(struct iked *env, u_int type) 406{ 407 return (pfkey_couple(env->sc_pfkey, &env->sc_sas, 408 type == IMSG_CTL_COUPLE ? 1 : 0)); 409} 410 411int 412config_setmode(struct iked *env, u_int passive) 413{ 414 u_int type; 415 416 type = passive ? IMSG_CTL_PASSIVE : IMSG_CTL_ACTIVE; 417 proc_compose_imsg(env, PROC_IKEV1, type, -1, NULL, 0); 418 proc_compose_imsg(env, PROC_IKEV2, type, -1, NULL, 0); 419 420 return (0); 421} 422 423int 424config_getmode(struct iked *env, u_int type) 425{ 426 u_int8_t old; 427 u_char *mode[] = { "active", "passive" }; 428 429 old = env->sc_passive ? 1 : 0; 430 env->sc_passive = type == IMSG_CTL_PASSIVE ? 1 : 0; 431 432 if (old == env->sc_passive) 433 return (0); 434 435 log_debug("%s: mode %s -> %s", __func__, 436 mode[old], mode[env->sc_passive]); 437 438 return (0); 439} 440 441int 442config_setreset(struct iked *env, u_int mode, enum privsep_procid id) 443{ 444 proc_compose_imsg(env, id, IMSG_CTL_RESET, -1, &mode, sizeof(mode)); 445 return (0); 446} 447 448int 449config_getreset(struct iked *env, struct imsg *imsg) 450{ 451 struct iked_policy *pol, *nextpol; 452 struct iked_sa *sa, *nextsa; 453 struct iked_user *usr, *nextusr; 454 u_int mode; 455 456 IMSG_SIZE_CHECK(imsg, &mode); 457 memcpy(&mode, imsg->data, sizeof(mode)); 458 459 if (mode == RESET_ALL || mode == RESET_POLICY) { 460 log_debug("%s: flushing policies", __func__); 461 for (pol = TAILQ_FIRST(&env->sc_policies); 462 pol != NULL; pol = nextpol) { 463 nextpol = TAILQ_NEXT(pol, pol_entry); 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 privsep_procid id) 493{ 494 int s; 495 496 if ((s = udp_bind((struct sockaddr *)ss, port)) == -1) 497 return (-1); 498 proc_compose_imsg(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 privsep_procid id) 543{ 544 int s; 545 546 if ((s = pfkey_socket()) == -1) 547 return (-1); 548 proc_compose_imsg(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 privsep_procid id) 562{ 563 if (env->sc_opts & IKED_OPT_NOACTION) { 564 print_user(usr); 565 return (0); 566 } 567 568 proc_compose_imsg(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 privsep_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 RB_FOREACH(flow, iked_flows, &pol->pol_flows) { 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 (proc_composev_imsg(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; 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 RB_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 RB_INSERT(iked_flows, &pol->pol_flows, flow); 696 } 697 698 TAILQ_INSERT_TAIL(&env->sc_policies, pol, pol_entry); 699 700 if (pol->pol_flags & IKED_POLICY_DEFAULT) { 701 /* Only one default policy, just free/unref the old one */ 702 if (env->sc_defaultcon != NULL) 703 config_free_policy(env, env->sc_defaultcon); 704 env->sc_defaultcon = pol; 705 } 706 707 print_policy(pol); 708 709 return (0); 710} 711 712int 713config_setcompile(struct iked *env, enum privsep_procid id) 714{ 715 if (env->sc_opts & IKED_OPT_NOACTION) 716 return (0); 717 718 proc_compose_imsg(env, id, IMSG_COMPILE, -1, NULL, 0); 719 return (0); 720} 721 722int 723config_getcompile(struct iked *env, struct imsg *imsg) 724{ 725 /* 726 * Do any necessary steps after configuration, for now we 727 * only need to compile the skip steps. 728 */ 729 policy_calc_skip_steps(&env->sc_policies); 730 731 log_debug("%s: compilation done", __func__); 732 return (0); 733} 734