1/* 2 * Copyright (c) 2008 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <sys/param.h> 24#include <sys/types.h> 25#include <sys/socket.h> 26#include <string.h> 27 28#include "var.h" 29#include "misc.h" 30#include "vmbuf.h" 31#include "plog.h" 32#include "sockmisc.h" 33#include "debug.h" 34#include "fsm.h" 35 36#include "isakmp_var.h" 37#include "isakmp.h" 38#include "ike_session.h" 39#include "handler.h" 40#include "gcmalloc.h" 41#include "nattraversal.h" 42#include "schedule.h" 43#include "pfkey.h" 44#include "ipsec_doi.h" 45#include "ipsecSessionTracer.h" 46#include "ipsecMessageTracer.h" 47#include "isakmp_inf.h" 48#include "localconf.h" 49#include "remoteconf.h" 50#include "vpn_control.h" 51#include "vpn_control_var.h" 52#include "proposal.h" 53#include "sainfo.h" 54#include "power_mgmt.h" 55 56#define GET_SAMPLE_PERIOD(s,m) do { \ 57 s = m / 20; \ 58 if (s < 3) { \ 59 s = 3; \ 60 if (m < (s * 2)) { \ 61 s = 1; /* bad */\ 62 } \ 63 } \ 64 } while(0); 65 66const char *ike_session_stopped_by_vpn_disconnect = "Stopped by VPN disconnect"; 67const char *ike_session_stopped_by_controller_comm_lost = "Stopped by loss of controller communication"; 68const char *ike_session_stopped_by_flush = "Stopped by Flush"; 69const char *ike_session_stopped_by_idle = "Stopped by Idle"; 70const char *ike_session_stopped_by_xauth_timeout = "Stopped by XAUTH timeout"; 71const char *ike_session_stopped_by_sleepwake = "Stopped by Sleep-Wake"; 72const char *ike_session_stopped_by_assert = "Stopped by Assert"; 73const char *ike_session_stopped_by_peer = "Stopped by Peer"; 74 75LIST_HEAD(_ike_session_tree_, ike_session) ike_session_tree = { NULL }; 76 77static void ike_session_bindph12(phase1_handle_t *, phase2_handle_t *); 78static void ike_session_rebindph12(phase1_handle_t *, phase2_handle_t *); 79static void ike_session_unbind_all_ph2_from_ph1 (phase1_handle_t *); 80static void ike_session_rebind_all_ph12_to_new_ph1 (phase1_handle_t *, phase1_handle_t *); 81 82static ike_session_t * 83new_ike_session (ike_session_id_t *id) 84{ 85 ike_session_t *session; 86 87 if (!id) { 88 plog(ASL_LEVEL_DEBUG, "Invalid parameters in %s.\n", __FUNCTION__); 89 return NULL; 90 } 91 92 session = racoon_calloc(1, sizeof(*session)); 93 if (session) { 94 bzero(session, sizeof(*session)); 95 memcpy(&session->session_id, id, sizeof(*id)); 96 LIST_INIT(&session->ph1tree); 97 LIST_INIT(&session->ph2tree); 98 LIST_INSERT_HEAD(&ike_session_tree, session, chain); 99 IPSECSESSIONTRACERSTART(session); 100 } 101 return session; 102} 103 104static void 105free_ike_session (ike_session_t *session) 106{ 107 int is_failure = TRUE; 108 if (session) { 109 SCHED_KILL(session->traffic_monitor.sc_mon); 110 SCHED_KILL(session->traffic_monitor.sc_idle); 111 SCHED_KILL(session->sc_xauth); 112 if (session->start_timestamp.tv_sec || session->start_timestamp.tv_usec) { 113 if (!(session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec)) { 114 gettimeofday(&session->stop_timestamp, NULL); 115 } 116 if (session->term_reason != ike_session_stopped_by_vpn_disconnect || 117 session->term_reason != ike_session_stopped_by_controller_comm_lost || 118 session->term_reason != ike_session_stopped_by_flush || 119 session->term_reason != ike_session_stopped_by_idle) { 120 is_failure = FALSE; 121 } 122 IPSECSESSIONTRACERSTOP(session, 123 is_failure, 124 session->term_reason); 125 } 126 // do MessageTracer cleanup here 127 plog(ASL_LEVEL_DEBUG, 128 "Freeing IKE-Session to %s.\n", 129 saddr2str((struct sockaddr *)&session->session_id.remote)); 130 LIST_REMOVE(session, chain); 131 racoon_free(session); 132 } 133} 134 135 136void 137ike_session_init (void) 138{ 139 LIST_INIT(&ike_session_tree); 140} 141 142u_int 143ike_session_get_rekey_lifetime (int local_spi_is_higher, u_int expiry_lifetime) 144{ 145 u_int rekey_lifetime = expiry_lifetime / 10; 146 147 if (rekey_lifetime) { 148 if (local_spi_is_higher) { 149 return (rekey_lifetime * 9); 150 } else { 151 return (rekey_lifetime * 8); 152 } 153 } else { 154 if (local_spi_is_higher) { 155 rekey_lifetime = expiry_lifetime - 1; 156 } else { 157 rekey_lifetime = expiry_lifetime - 2; 158 } 159 } 160 if (rekey_lifetime < expiry_lifetime) { 161 return rekey_lifetime; 162 } 163 return 0; 164} 165 166ike_session_t * 167ike_session_create_session (ike_session_id_t *session_id) 168{ 169 if (!session_id) 170 return NULL; 171 172 plog(ASL_LEVEL_DEBUG, "New IKE Session to %s.\n", saddr2str((struct sockaddr *)&session_id->remote)); 173 174 return new_ike_session(session_id); 175} 176 177void 178ike_session_release_session (ike_session_t *session) 179{ 180 while (!LIST_EMPTY(&session->ph2tree)) { 181 phase2_handle_t *phase2 = LIST_FIRST(&session->ph2tree); 182 ike_session_unlink_phase2(phase2); 183 } 184 185 while (!LIST_EMPTY(&session->ph1tree)) { 186 phase1_handle_t *phase1 = LIST_FIRST(&session->ph1tree); 187 ike_session_unlink_phase1(phase1); 188 } 189} 190 191// %%%%%%%%% re-examine this - keep both floated and unfloated port when behind nat 192ike_session_t * 193ike_session_get_session (struct sockaddr_storage *local, 194 struct sockaddr_storage *remote, 195 int alloc_if_absent, 196 isakmp_index *optionalIndex) 197{ 198 ike_session_t *p = NULL; 199 ike_session_id_t id; 200 ike_session_id_t id_default; 201 ike_session_id_t id_floated_default; 202 ike_session_id_t id_wop; 203 ike_session_t *best_match = NULL; 204 u_int16_t remote_port; 205 int is_isakmp_remote_port; 206 207 if (!local || !remote) { 208 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 209 return NULL; 210 } 211 212 remote_port = extract_port(remote); 213 if (remote_port && remote_port != PORT_ISAKMP && remote_port != PORT_ISAKMP_NATT) { 214 is_isakmp_remote_port = 0; 215 } else { 216 is_isakmp_remote_port = 1; 217 } 218 219 /* we will try a couple of matches first: if the exact id isn't found, then we'll try for an id that has zero'd ports */ 220 bzero(&id, sizeof(id)); 221 bzero(&id_default, sizeof(id_default)); 222 bzero(&id_floated_default, sizeof(id_floated_default)); 223 bzero(&id_wop, sizeof(id_wop)); 224 if (local->ss_family == AF_INET) { 225 memcpy(&id.local, local, sizeof(struct sockaddr_in)); 226 memcpy(&id_default.local, local, sizeof(struct sockaddr_in)); 227 memcpy(&id_floated_default.local, local, sizeof(struct sockaddr_in)); 228 memcpy(&id_wop.local, local, sizeof(struct sockaddr_in)); 229 } else if (local->ss_family == AF_INET6) { 230 memcpy(&id.local, local, sizeof(struct sockaddr_in6)); 231 memcpy(&id_default.local, local, sizeof(struct sockaddr_in6)); 232 memcpy(&id_floated_default.local, local, sizeof(struct sockaddr_in6)); 233 memcpy(&id_wop.local, local, sizeof(struct sockaddr_in6)); 234 } 235 set_port(&id_default.local, PORT_ISAKMP); 236 set_port(&id_floated_default.local, PORT_ISAKMP_NATT); 237 set_port(&id_wop.local, 0); 238 if (remote->ss_family == AF_INET) { 239 memcpy(&id.remote, remote, sizeof(struct sockaddr_in)); 240 memcpy(&id_default.remote, remote, sizeof(struct sockaddr_in)); 241 memcpy(&id_floated_default.remote, remote, sizeof(struct sockaddr_in)); 242 memcpy(&id_wop.remote, remote, sizeof(struct sockaddr_in)); 243 } else if (remote->ss_family == AF_INET6) { 244 memcpy(&id.remote, remote, sizeof(struct sockaddr_in6)); 245 memcpy(&id_default.remote, remote, sizeof(struct sockaddr_in6)); 246 memcpy(&id_floated_default.remote, remote, sizeof(struct sockaddr_in6)); 247 memcpy(&id_wop.remote, remote, sizeof(struct sockaddr_in6)); 248 } 249 set_port(&id_default.remote, PORT_ISAKMP); 250 set_port(&id_floated_default.remote, PORT_ISAKMP_NATT); 251 set_port(&id_wop.remote, 0); 252 253 plog(ASL_LEVEL_DEBUG, 254 "start search for IKE-Session. target %s.\n", 255 saddr2str((struct sockaddr *)remote)); 256 257 LIST_FOREACH(p, &ike_session_tree, chain) { 258 plog(ASL_LEVEL_DEBUG, 259 "still search for IKE-Session. this %s.\n", 260 saddr2str((struct sockaddr *)&p->session_id.remote)); 261 262 // for now: ignore any stopped sessions as they will go down 263 if (p->is_dying || p->stopped_by_vpn_controller || p->stop_timestamp.tv_sec || p->stop_timestamp.tv_usec) { 264 plog(ASL_LEVEL_DEBUG, "still searching. skipping... session to %s is already stopped, active ph1 %d ph2 %d.\n", 265 saddr2str((struct sockaddr *)&p->session_id.remote), 266 p->ikev1_state.active_ph1cnt, p->ikev1_state.active_ph2cnt); 267 continue; 268 } 269 270 // Skip if the spi doesn't match 271 if (optionalIndex != NULL && ike_session_getph1byindex(p, optionalIndex) == NULL) { 272 continue; 273 } 274 275 if (memcmp(&p->session_id, &id, sizeof(id)) == 0) { 276 plog(ASL_LEVEL_DEBUG, 277 "Pre-existing IKE-Session to %s. case 1.\n", 278 saddr2str((struct sockaddr *)remote)); 279 return p; 280 } else if (is_isakmp_remote_port && memcmp(&p->session_id, &id_default, sizeof(id_default)) == 0) { 281 plog(ASL_LEVEL_DEBUG, 282 "Pre-existing IKE-Session to %s. case 2.\n", 283 saddr2str((struct sockaddr *)remote)); 284 return p; 285 } else if (is_isakmp_remote_port && p->ports_floated && memcmp(&p->session_id, &id_floated_default, sizeof(id_floated_default)) == 0) { 286 plog(ASL_LEVEL_DEBUG, 287 "Pre-existing IKE-Session to %s. case 3.\n", 288 saddr2str((struct sockaddr *)remote)); 289 return p; 290 } else if (is_isakmp_remote_port && memcmp(&p->session_id, &id_wop, sizeof(id_wop)) == 0) { 291 best_match = p; 292 } else if (optionalIndex != NULL) { 293 // If the SPI did match, this one counts as a best match 294 best_match = p; 295 } 296 } 297 if (best_match) { 298 plog(ASL_LEVEL_DEBUG, 299 "Best-match IKE-Session to %s.\n", 300 saddr2str((struct sockaddr *)&best_match->session_id.remote)); 301 return best_match; 302 } 303 if (alloc_if_absent) { 304 plog(ASL_LEVEL_DEBUG, 305 "New IKE-Session to %s.\n", 306 saddr2str((struct sockaddr *)&id.remote)); 307 return new_ike_session(&id); 308 } else { 309 return NULL; 310 } 311} 312 313void 314ike_session_init_traffic_cop_params (phase1_handle_t *iph1) 315{ 316 if (!iph1 || 317 !iph1->rmconf || 318 (!iph1->rmconf->idle_timeout && !iph1->rmconf->dpd_interval)) { 319 return; 320 } 321 322 if (!iph1->parent_session->traffic_monitor.interv_idle) { 323 iph1->parent_session->traffic_monitor.interv_idle = iph1->rmconf->idle_timeout; 324 } 325 if (!iph1->parent_session->traffic_monitor.dir_idle) { 326 iph1->parent_session->traffic_monitor.dir_idle = iph1->rmconf->idle_timeout_dir; 327 } 328 329 if (!iph1->parent_session->traffic_monitor.interv_mon) { 330 int min_period, max_period, sample_period = 0; 331 332 /* calculate the sampling interval... half the smaller interval */ 333 if (iph1->rmconf->dpd_interval && 334 (iph1->rmconf->dpd_algo == DPD_ALGO_INBOUND_DETECT || 335 iph1->rmconf->dpd_algo == DPD_ALGO_BLACKHOLE_DETECT)) { 336 // when certain types of dpd are enabled 337 min_period = MIN(iph1->rmconf->dpd_interval, iph1->rmconf->idle_timeout); 338 max_period = MAX(iph1->rmconf->dpd_interval, iph1->rmconf->idle_timeout); 339 } else if (iph1->rmconf->idle_timeout) { 340 min_period = max_period = iph1->rmconf->idle_timeout; 341 } else { 342 // DPD_ALGO_DEFAULT is configured and there's no idle timeout... we don't need to monitor traffic 343 return; 344 } 345 if (min_period) { 346 GET_SAMPLE_PERIOD(sample_period, min_period); 347 } else { 348 GET_SAMPLE_PERIOD(sample_period, max_period); 349 } 350 iph1->parent_session->traffic_monitor.interv_mon = sample_period; 351 } 352} 353 354void 355ike_session_update_mode (phase2_handle_t *iph2) 356{ 357 if (!iph2 || !iph2->parent_session) { 358 return; 359 } 360 if (iph2->phase2_type != PHASE2_TYPE_SA) 361 return; 362 363 // exit early if we already detected cisco-ipsec 364 if (iph2->parent_session->is_cisco_ipsec) { 365 return; 366 } 367 368 if (iph2->approval) { 369 if (!ipsecdoi_any_transportmode(iph2->approval)) { 370 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1) 371 iph2->parent_session->is_cisco_ipsec = 0; 372 iph2->parent_session->is_l2tpvpn_ipsec = 0; 373 iph2->parent_session->is_btmm_ipsec = 1; 374 return; 375 } else if (ipsecdoi_transportmode(iph2->approval)) { 376 iph2->parent_session->is_cisco_ipsec = 0; 377 iph2->parent_session->is_l2tpvpn_ipsec = 1; 378 iph2->parent_session->is_btmm_ipsec = 0; 379 return; 380 } 381 } else if (iph2->proposal) { 382 if (!ipsecdoi_any_transportmode(iph2->proposal)) { 383 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1) 384 iph2->parent_session->is_cisco_ipsec = 0; 385 iph2->parent_session->is_l2tpvpn_ipsec = 0; 386 iph2->parent_session->is_btmm_ipsec = 1; 387 return; 388 } else if (ipsecdoi_transportmode(iph2->proposal)) { 389 iph2->parent_session->is_cisco_ipsec = 0; 390 iph2->parent_session->is_l2tpvpn_ipsec = 1; 391 iph2->parent_session->is_btmm_ipsec = 0; 392 return; 393 } 394 } 395} 396 397static void 398ike_session_cleanup_xauth_timeout (void *arg) 399{ 400 ike_session_t *session = (ike_session_t *)arg; 401 402 SCHED_KILL(session->sc_xauth); 403 // if there are no more established ph2s, start a timer to teardown the session 404 if (!ike_session_has_established_ph2(session)) { 405 ike_session_cleanup(session, ike_session_stopped_by_xauth_timeout); 406 } else { 407 session->sc_xauth = sched_new(300 /* 5 mins */, 408 ike_session_cleanup_xauth_timeout, 409 session); 410 } 411} 412 413int 414ike_session_link_phase1 (ike_session_t *session, phase1_handle_t *iph1) 415{ 416 417 if (!session || !iph1) { 418 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 419 return -1; 420 } 421 422 gettimeofday(&session->start_timestamp, NULL); 423 424 if (iph1->started_by_api) { 425 session->is_cisco_ipsec = 1; 426 session->is_l2tpvpn_ipsec = 0; 427 session->is_btmm_ipsec = 0; 428 } 429 iph1->parent_session = session; 430 LIST_INSERT_HEAD(&session->ph1tree, iph1, ph1ofsession_chain); 431 session->ikev1_state.active_ph1cnt++; 432 if ((!session->ikev1_state.ph1cnt && 433 iph1->side == INITIATOR) || 434 iph1->started_by_api) { 435 // client initiates the first phase1 or, is started by controller api 436 session->is_client = 1; 437 } 438 if (session->established && 439 session->ikev1_state.ph1cnt && 440 iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { 441 iph1->is_rekey = 1; 442 } 443 session->ikev1_state.ph1cnt++; 444 ike_session_init_traffic_cop_params(iph1); 445 446 return 0; 447} 448 449int 450ike_session_link_phase2 (ike_session_t *session, phase2_handle_t *iph2) 451{ 452 if (!iph2) { 453 plog(ASL_LEVEL_DEBUG, "Invalid parameters in %s.\n", __FUNCTION__); 454 return -1; 455 } 456 if (iph2->parent_session) { 457 plog(ASL_LEVEL_ERR, "Phase 2 already linked to session %s.\n", __FUNCTION__); 458 } 459 460 iph2->parent_session = session; 461 LIST_INSERT_HEAD(&session->ph2tree, iph2, ph2ofsession_chain); 462 session->ikev1_state.active_ph2cnt++; 463 if (!session->ikev1_state.ph2cnt && 464 iph2->side == INITIATOR) { 465 // client initiates the first phase2 466 session->is_client = 1; 467 } 468 if (iph2->phase2_type == PHASE2_TYPE_SA && 469 session->established && 470 session->ikev1_state.ph2cnt && 471 iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) { 472 iph2->is_rekey = 1; 473 } 474 session->ikev1_state.ph2cnt++; 475 ike_session_update_mode(iph2); 476 477 return 0; 478} 479 480int 481ike_session_link_ph2_to_ph1 (phase1_handle_t *iph1, phase2_handle_t *iph2) 482{ 483 struct sockaddr_storage *local; 484 struct sockaddr_storage *remote; 485 int error = 0; 486 487 if (!iph2) { 488 plog(ASL_LEVEL_DEBUG, "Invalid parameters in %s.\n", __FUNCTION__); 489 return -1; 490 } 491 if (iph2->ph1) { 492 plog(ASL_LEVEL_ERR, "Phase 2 already linked %s.\n", __FUNCTION__); 493 if (iph2->ph1 == iph1) 494 return 0; 495 else 496 return -1; // This shouldn't happen 497 } 498 499 local = iph2->src; 500 remote = iph2->dst; 501 502 if (iph2->parent_session == NULL) 503 if ((error = ike_session_link_phase2(iph1->parent_session, iph2))) 504 return error; 505 506 ike_session_bindph12(iph1, iph2); 507 return 0; 508} 509 510int 511ike_session_unlink_phase1 (phase1_handle_t *iph1) 512{ 513 ike_session_t *session; 514 515 if (!iph1 || !iph1->parent_session) { 516 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 517 return -1; 518 } 519 520 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { 521 if (LIST_FIRST(&iph1->bound_ph2tree)) { 522 // reparent any phase2 that may be hanging on to this phase1 523 ike_session_update_ph1_ph2tree(iph1); 524 } 525 } 526 527 sched_scrub_param(iph1); 528 session = iph1->parent_session; 529 LIST_REMOVE(iph1, ph1ofsession_chain); 530 iph1->parent_session = NULL; 531 session->ikev1_state.active_ph1cnt--; 532 if (session->ikev1_state.active_ph1cnt == 0 && session->ikev1_state.active_ph2cnt == 0) { 533 session->is_dying = 1; 534 free_ike_session(session); 535 } 536 ike_session_delph1(iph1); 537 return 0; 538} 539 540int 541ike_session_unlink_phase2 (phase2_handle_t *iph2) 542{ 543 ike_session_t *session; 544 545 if (!iph2 || !iph2->parent_session) { 546 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 547 return -1; 548 } 549 sched_scrub_param(iph2); 550 ike_session_unbindph12(iph2); 551 552 LIST_REMOVE(iph2, ph2ofsession_chain); 553 session = iph2->parent_session; 554 iph2->parent_session = NULL; 555 session->ikev1_state.active_ph2cnt--; 556 if (session->ikev1_state.active_ph1cnt == 0 && session->ikev1_state.active_ph2cnt == 0) { 557 session->is_dying = 1; 558 free_ike_session(session); 559 } 560 ike_session_delph2(iph2); 561 return 0; 562} 563 564 565phase1_handle_t * 566ike_session_update_ph1_ph2tree (phase1_handle_t *iph1) 567{ 568 phase1_handle_t *new_iph1 = NULL; 569 570 if (!iph1) { 571 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 572 return NULL; 573 } 574 575 if (iph1->parent_session) { 576 new_iph1 = ike_session_get_established_ph1(iph1->parent_session); 577 578 if (!new_iph1) { 579 plog(ASL_LEVEL_DEBUG, "no ph1bind replacement found. NULL ph1.\n"); 580 ike_session_unbind_all_ph2_from_ph1(iph1); 581 } else if (iph1 == new_iph1) { 582 plog(ASL_LEVEL_DEBUG, "no ph1bind replacement found. same ph1.\n"); 583 ike_session_unbind_all_ph2_from_ph1(iph1); 584 } else { 585 ike_session_rebind_all_ph12_to_new_ph1(iph1, new_iph1); 586 } 587 } else { 588 plog(ASL_LEVEL_DEBUG, "invalid parent session in %s.\n", __FUNCTION__); 589 } 590 return new_iph1; 591} 592 593phase1_handle_t * 594ike_session_update_ph2_ph1bind (phase2_handle_t *iph2) 595{ 596 phase1_handle_t *iph1; 597 598 if (!iph2 || iph2->phase2_type != PHASE2_TYPE_SA) { 599 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 600 return NULL; 601 } 602 603 iph1 = ike_session_get_established_ph1(iph2->parent_session); 604 if (iph1 && iph2->ph1 && iph1 != iph2->ph1) { 605 ike_session_rebindph12(iph1, iph2); 606 } else if (iph1 && !iph2->ph1) { 607 ike_session_bindph12(iph1, iph2); 608 } 609 610 return iph1; 611} 612 613phase1_handle_t * 614ike_session_get_established_or_negoing_ph1 (ike_session_t *session) 615{ 616 phase1_handle_t *p, *iph1 = NULL; 617 618 if (!session) { 619 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 620 return NULL; 621 } 622 623 // look for the most mature ph1 under the session 624 LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { 625 if (!p->is_dying && (FSM_STATE_IS_ESTABLISHED(p->status) || FSM_STATE_IS_NEGOTIATING(p->status))) { 626 if (!iph1 || p->status > iph1->status) { 627 iph1 = p; 628 } else if (iph1 && p->status == iph1->status) { 629 // TODO: pick better one based on farthest rekey/expiry remaining 630 } 631 } 632 } 633 634 return iph1; 635} 636 637phase1_handle_t * 638ike_session_get_established_ph1 (ike_session_t *session) 639{ 640 phase1_handle_t *p; 641 642 if (!session) { 643 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 644 return NULL; 645 } 646 647 LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { 648 if (!p->is_dying && FSM_STATE_IS_ESTABLISHED(p->status)) { 649 return p; 650 } 651 } 652 653 return NULL; 654} 655 656 657int 658ike_session_has_other_established_ph1 (ike_session_t *session, phase1_handle_t *iph1) 659{ 660 phase1_handle_t *p; 661 662 if (!session) { 663 return 0; 664 } 665 666 LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { 667 if (iph1 != p && !p->is_dying) { 668 if (FSM_STATE_IS_ESTABLISHED(p->status) && p->sce_rekey) { 669 return 1; 670 } 671 } 672 } 673 674 return 0; 675} 676 677int 678ike_session_has_other_negoing_ph1 (ike_session_t *session, phase1_handle_t *iph1) 679{ 680 phase1_handle_t *p; 681 682 if (!session) { 683 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 684 return 0; 685 } 686 687 LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { 688 if (iph1 != p && !p->is_dying) { 689 if (FSM_STATE_IS_NEGOTIATING(p->status)) { 690 return 1; 691 } 692 } 693 } 694 695 return 0; 696} 697 698int 699ike_session_has_other_established_ph2 (ike_session_t *session, phase2_handle_t *iph2) 700{ 701 phase2_handle_t *p; 702 703 if (!session) { 704 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 705 return 0; 706 } 707 708 LIST_FOREACH(p, &session->ph2tree, ph2ofsession_chain) { 709 if (p->phase2_type == PHASE2_TYPE_SA && iph2 != p && !p->is_dying && iph2->spid == p->spid) { 710 if (FSM_STATE_IS_ESTABLISHED(p->status)) { 711 return 1; 712 } 713 } 714 } 715 716 return 0; 717} 718 719int 720ike_session_has_other_negoing_ph2 (ike_session_t *session, phase2_handle_t *iph2) 721{ 722 phase2_handle_t *p; 723 724 if (!session) { 725 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 726 return 0; 727 } 728 729 LIST_FOREACH(p, &session->ph2tree, ph2ofsession_chain) { 730 plog(ASL_LEVEL_DEBUG, "%s: ph2 sub spid %d, db spid %d\n", __FUNCTION__, iph2->spid, p->spid); 731 if (p->phase2_type == PHASE2_TYPE_SA && iph2 != p && !p->is_dying && iph2->spid == p->spid) { 732 if (FSM_STATE_IS_NEGOTIATING(p->status)) { 733 return 1; 734 } 735 } 736 } 737 738 return 0; 739} 740 741 742void 743ike_session_ikev1_float_ports (phase1_handle_t *iph1) 744{ 745 struct sockaddr_storage *local, *remote; 746 phase2_handle_t *p; 747 748 if (iph1->parent_session) { 749 local = &iph1->parent_session->session_id.local; 750 remote = &iph1->parent_session->session_id.remote; 751 752 set_port(local, extract_port(iph1->local)); 753 set_port(remote, extract_port(iph1->remote)); 754 iph1->parent_session->ports_floated = 1; 755 756 LIST_FOREACH(p, &iph1->parent_session->ph2tree, ph2ofsession_chain) { 757 758 local = p->src; 759 remote = p->dst; 760 761 set_port(local, extract_port(iph1->local)); 762 set_port(remote, extract_port(iph1->remote)); 763 } 764 } else { 765 plog(ASL_LEVEL_DEBUG, "invalid parent session in %s.\n", __FUNCTION__); 766 } 767} 768 769static void 770ike_session_traffic_cop (void *arg) 771{ 772 ike_session_t *session = (__typeof__(session))arg; 773 774 if (session && 775 (session->established && !session->stopped_by_vpn_controller && !session->stop_timestamp.tv_sec && !session->stop_timestamp.tv_usec)) { 776 SCHED_KILL(session->traffic_monitor.sc_mon); 777 /* get traffic query from kernel */ 778 if (pk_sendget_inbound_sastats(session) < 0) { 779 // log message 780 plog(ASL_LEVEL_DEBUG, "pk_sendget_inbound_sastats failed in %s.\n", __FUNCTION__); 781 } 782 if (pk_sendget_outbound_sastats(session) < 0) { 783 // log message 784 plog(ASL_LEVEL_DEBUG, "pk_sendget_outbound_sastats failed in %s.\n", __FUNCTION__); 785 } 786 session->traffic_monitor.sc_mon = sched_new(session->traffic_monitor.interv_mon, 787 ike_session_traffic_cop, 788 session); 789 } else { 790 // log message 791 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 792 } 793} 794 795static void 796ike_session_cleanup_idle (void *arg) 797{ 798 ike_session_cleanup((ike_session_t *)arg, ike_session_stopped_by_idle); 799} 800 801static void 802ike_session_monitor_idle (ike_session_t *session) 803{ 804 if (!session) 805 return; 806 807 if (session->traffic_monitor.dir_idle == IPSEC_DIR_INBOUND || 808 session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) { 809 if (session->peer_sent_data_sc_idle) { 810 plog(ASL_LEVEL_DEBUG, "%s: restart idle-timeout because peer sent data. monitoring dir %d.\n", 811 __FUNCTION__, session->traffic_monitor.dir_idle); 812 SCHED_KILL(session->traffic_monitor.sc_idle); 813 if (session->traffic_monitor.interv_idle) { 814 session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle, 815 ike_session_cleanup_idle, 816 session); 817 } 818 session->peer_sent_data_sc_idle = 0; 819 session->i_sent_data_sc_idle = 0; 820 return; 821 } 822 } 823 if (session->traffic_monitor.dir_idle == IPSEC_DIR_OUTBOUND || 824 session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) { 825 if (session->i_sent_data_sc_idle) { 826 plog(ASL_LEVEL_DEBUG, "%s: restart idle-timeout because i sent data. monitoring dir %d.\n", 827 __FUNCTION__, session->traffic_monitor.dir_idle); 828 SCHED_KILL(session->traffic_monitor.sc_idle); 829 if (session->traffic_monitor.interv_idle) { 830 session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle, 831 ike_session_cleanup_idle, 832 session); 833 } 834 session->peer_sent_data_sc_idle = 0; 835 session->i_sent_data_sc_idle = 0; 836 return; 837 } 838 } 839} 840 841static void 842ike_session_start_traffic_mon (ike_session_t *session) 843{ 844 if (session->traffic_monitor.interv_mon) { 845 session->traffic_monitor.sc_mon = sched_new(session->traffic_monitor.interv_mon, 846 ike_session_traffic_cop, 847 session); 848 } 849 if (session->traffic_monitor.interv_idle) { 850 session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle, 851 ike_session_cleanup_idle, 852 session); 853 } 854} 855 856void 857ike_session_ph2_established (phase2_handle_t *iph2) 858{ 859 if (!iph2->parent_session || iph2->phase2_type != PHASE2_TYPE_SA) { 860 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 861 return; 862 } 863 SCHED_KILL(iph2->parent_session->sc_xauth); 864 if (!iph2->parent_session->established) { 865 gettimeofday(&iph2->parent_session->estab_timestamp, NULL); 866 iph2->parent_session->established = 1; 867 IPSECSESSIONTRACERESTABLISHED(iph2->parent_session); 868 ike_session_start_traffic_mon(iph2->parent_session); 869 } else if (iph2->parent_session->is_asserted) { 870 ike_session_start_traffic_mon(iph2->parent_session); 871 } 872 iph2->parent_session->is_asserted = 0; 873 // nothing happening to this session 874 iph2->parent_session->term_reason = NULL; 875 876 ike_session_update_mode(iph2); 877 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) 878 ike_session_unbindph12(iph2); 879 880#ifdef ENABLE_VPNCONTROL_PORT 881 vpncontrol_notify_peer_resp_ph2(1, iph2); 882#endif /* ENABLE_VPNCONTROL_PORT */ 883 plog(ASL_LEVEL_DEBUG, "%s: ph2 established, spid %d\n", __FUNCTION__, iph2->spid); 884} 885 886void 887ike_session_cleanup_ph1 (phase1_handle_t *iph1) 888{ 889 if (FSM_STATE_IS_EXPIRED(iph1->status)) { 890 // since this got here via ike_session_cleanup_other_established_ph1s, assumes LIST_FIRST(&iph1->ph2tree) == NULL 891 iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1); 892 return; 893 } 894 895 /* send delete information */ 896 if (FSM_STATE_IS_ESTABLISHED(iph1->status)) { 897 isakmp_info_send_d1(iph1); 898 } 899 900 isakmp_ph1expire(iph1); 901} 902 903void 904ike_session_cleanup_ph1_stub (void *p) 905{ 906 907 ike_session_cleanup_ph1((phase1_handle_t *)p); 908} 909 910void 911ike_session_replace_other_ph1 (phase1_handle_t *new_iph1, 912 phase1_handle_t *old_iph1) 913{ 914 char *local, *remote, *index; 915 ike_session_t *session = NULL; 916 917 if (new_iph1) 918 session = new_iph1->parent_session; 919 920 if (!session || !new_iph1 || !old_iph1 || session != old_iph1->parent_session || new_iph1 == old_iph1) { 921 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 922 return; 923 } 924 925 /* 926 * if we are responder, then we should wait until the server sends a delete notification. 927 */ 928 if (session->is_client && 929 new_iph1->side == RESPONDER) { 930 return; 931 } 932 933 SCHED_KILL(old_iph1->sce); 934 SCHED_KILL(old_iph1->sce_rekey); 935 old_iph1->is_dying = 1; 936 937 //log deletion 938 local = racoon_strdup(saddr2str((struct sockaddr *)old_iph1->local)); 939 remote = racoon_strdup(saddr2str((struct sockaddr *)old_iph1->remote)); 940 index = racoon_strdup(isakmp_pindex(&old_iph1->index, 0)); 941 STRDUP_FATAL(local); 942 STRDUP_FATAL(remote); 943 STRDUP_FATAL(index); 944 plog(ASL_LEVEL_DEBUG, "ISAKMP-SA %s-%s (spi:%s) needs to be deleted, replaced by (spi:%s)\n", local, remote, index, isakmp_pindex(&new_iph1->index, 0)); 945 racoon_free(local); 946 racoon_free(remote); 947 racoon_free(index); 948 949 // first rebind the children ph2s of this dying ph1 to the new ph1. 950 ike_session_rebind_all_ph12_to_new_ph1 (old_iph1, new_iph1); 951 952 if (old_iph1->side == INITIATOR) { 953 /* everyone deletes old outbound SA */ 954 old_iph1->sce = sched_new(5, ike_session_cleanup_ph1_stub, old_iph1); 955 } else { 956 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */ 957 old_iph1->sce = sched_new(7, ike_session_cleanup_ph1_stub, old_iph1); 958 } 959} 960 961void 962ike_session_cleanup_other_established_ph1s (ike_session_t *session, 963 phase1_handle_t *new_iph1) 964{ 965 phase1_handle_t *p, *next; 966 char *local, *remote; 967 968 if (!session || !new_iph1 || session != new_iph1->parent_session) { 969 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 970 return; 971 } 972 973 /* 974 * if we are responder, then we should wait until the server sends a delete notification. 975 */ 976 if (session->is_client && 977 new_iph1->side == RESPONDER) { 978 return; 979 } 980 981 LIST_FOREACH_SAFE(p, &session->ph1tree, ph1ofsession_chain, next) { 982 /* 983 * TODO: currently, most recently established SA wins. Need to revisit to see if 984 * alternative selections is better (e.g. largest p->index stays). 985 */ 986 if (p != new_iph1 && !p->is_dying) { 987 SCHED_KILL(p->sce); 988 SCHED_KILL(p->sce_rekey); 989 p->is_dying = 1; 990 991 //log deletion 992 local = racoon_strdup(saddr2str((struct sockaddr *)p->local)); 993 remote = racoon_strdup(saddr2str((struct sockaddr *)p->remote)); 994 STRDUP_FATAL(local); 995 STRDUP_FATAL(remote); 996 plog(ASL_LEVEL_DEBUG, 997 "ISAKMP-SA needs to be deleted %s-%s spi:%s\n", 998 local, remote, isakmp_pindex(&p->index, 0)); 999 racoon_free(local); 1000 racoon_free(remote); 1001 1002 // first rebind the children ph2s of this dying ph1 to the new ph1. 1003 ike_session_rebind_all_ph12_to_new_ph1 (p, new_iph1); 1004 1005 if (p->side == INITIATOR) { 1006 /* everyone deletes old outbound SA */ 1007 p->sce = sched_new(5, ike_session_cleanup_ph1_stub, p); 1008 } else { 1009 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */ 1010 p->sce = sched_new(7, ike_session_cleanup_ph1_stub, p); 1011 } 1012 } 1013 } 1014} 1015 1016void 1017ike_session_cleanup_ph2 (phase2_handle_t *iph2) 1018{ 1019 if (iph2->phase2_type != PHASE2_TYPE_SA) 1020 return; 1021 if (FSM_STATE_IS_EXPIRED(iph2->status)) { 1022 return; 1023 } 1024 1025 SCHED_KILL(iph2->sce); 1026 1027 plog(ASL_LEVEL_ERR, 1028 "about to cleanup ph2: status %d, seq %d dying %d\n", 1029 iph2->status, iph2->seq, iph2->is_dying); 1030 1031 /* send delete information */ 1032 if (FSM_STATE_IS_ESTABLISHED(iph2->status)) { 1033 isakmp_info_send_d2(iph2); 1034 1035 // delete outgoing SAs 1036 if (iph2->approval) { 1037 struct saproto *pr; 1038 1039 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { 1040 if (pr->ok) { 1041 pfkey_send_delete(lcconf->sock_pfkey, 1042 ipsecdoi2pfkey_proto(pr->proto_id), 1043 IPSEC_MODE_ANY, 1044 iph2->src, iph2->dst, pr->spi_p /* pr->reqid_out */); 1045 } 1046 } 1047 } 1048 } 1049 1050 delete_spd(iph2); 1051 ike_session_unlink_phase2(iph2); 1052} 1053 1054void 1055ike_session_cleanup_ph2_stub (void *p) 1056{ 1057 1058 ike_session_cleanup_ph2((phase2_handle_t *)p); 1059} 1060 1061void 1062ike_session_cleanup_other_established_ph2s (ike_session_t *session, 1063 phase2_handle_t *new_iph2) 1064{ 1065 phase2_handle_t *p, *next; 1066 1067 if (!session || !new_iph2 || session != new_iph2->parent_session || new_iph2->phase2_type != PHASE2_TYPE_SA) { 1068 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1069 return; 1070 } 1071 1072 /* 1073 * if we are responder, then we should wait until the server sends a delete notification. 1074 */ 1075 if (session->is_client && new_iph2->side == RESPONDER) { 1076 return; 1077 } 1078 1079 LIST_FOREACH_SAFE(p, &session->ph2tree, ph2ofsession_chain, next) { 1080 /* 1081 * TODO: currently, most recently established SA wins. Need to revisit to see if 1082 * alternative selections is better. 1083 */ 1084 if (p != new_iph2 && p->spid == new_iph2->spid && !p->is_dying) { 1085 SCHED_KILL(p->sce); 1086 p->is_dying = 1; 1087 1088 //log deletion 1089 plog(ASL_LEVEL_DEBUG, 1090 "IPsec-SA needs to be deleted: %s\n", 1091 sadbsecas2str(p->src, p->dst, 1092 p->satype, p->spid, 0)); 1093 1094 if (p->side == INITIATOR) { 1095 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */ 1096 p->sce = sched_new(3, ike_session_cleanup_ph2_stub, p); 1097 } else { 1098 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */ 1099 p->sce = sched_new(5, ike_session_cleanup_ph2_stub, p); 1100 } 1101 } 1102 } 1103} 1104 1105void 1106ike_session_stopped_by_controller (ike_session_t *session, 1107 const char *reason) 1108{ 1109 if (!session) { 1110 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1111 return; 1112 } 1113 if (session->stop_timestamp.tv_sec || 1114 session->stop_timestamp.tv_usec) { 1115 plog(ASL_LEVEL_DEBUG, "already stopped %s.\n", __FUNCTION__); 1116 return; 1117 } 1118 session->stopped_by_vpn_controller = 1; 1119 gettimeofday(&session->stop_timestamp, NULL); 1120 if (!session->term_reason) { 1121 session->term_reason = (__typeof__(session->term_reason))reason; 1122 } 1123} 1124 1125void 1126ike_sessions_stopped_by_controller (struct sockaddr_storage *remote, 1127 int withport, 1128 const char *reason) 1129{ 1130 ike_session_t *p = NULL; 1131 ike_session_t *next_session = NULL; 1132 1133 if (!remote) { 1134 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1135 return; 1136 } 1137 1138 LIST_FOREACH_SAFE(p, &ike_session_tree, chain, next_session) { 1139 if ((withport && cmpsaddrstrict(&p->session_id.remote, remote) == 0) || 1140 (!withport && cmpsaddrwop(&p->session_id.remote, remote) == 0)) { 1141 ike_session_stopped_by_controller(p, reason); 1142 } 1143 } 1144} 1145 1146void 1147ike_session_purge_ph2s_by_ph1 (phase1_handle_t *iph1) 1148{ 1149 phase2_handle_t *p, *next; 1150 1151 if (!iph1 || !iph1->parent_session) { 1152 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1153 return; 1154 } 1155 1156 LIST_FOREACH_SAFE(p, &iph1->parent_session->ph2tree, ph2ofsession_chain, next) { 1157 if (p->is_dying) { 1158 continue; 1159 } 1160 SCHED_KILL(p->sce); 1161 p->is_dying = 1; 1162 1163 //log deletion 1164 plog(ASL_LEVEL_DEBUG, 1165 "IPsec-SA needs to be purged: %s\n", 1166 sadbsecas2str(p->src, p->dst, 1167 p->satype, p->spid, 0)); 1168 1169 ike_session_cleanup_ph2(p); 1170 } 1171} 1172 1173void 1174ike_session_update_ph2_ports (phase2_handle_t *iph2) 1175{ 1176 struct sockaddr_storage *local; 1177 struct sockaddr_storage *remote; 1178 1179 if (iph2->parent_session) { 1180 local = &iph2->parent_session->session_id.local; 1181 remote = &iph2->parent_session->session_id.remote; 1182 1183 set_port(iph2->src, extract_port(local)); 1184 set_port(iph2->dst, extract_port(remote)); 1185 } else { 1186 plog(ASL_LEVEL_DEBUG, "invalid parent session in %s.\n", __FUNCTION__); 1187 } 1188} 1189 1190u_int32_t 1191ike_session_get_sas_for_stats (ike_session_t *session, 1192 u_int8_t dir, 1193 u_int32_t *seq, 1194 struct sastat *stats, 1195 u_int32_t max_stats) 1196{ 1197 int found = 0; 1198 phase2_handle_t *iph2; 1199 1200 if (!session || !seq || !stats || !max_stats || (dir != IPSEC_DIR_INBOUND && dir != IPSEC_DIR_OUTBOUND)) { 1201 plog(ASL_LEVEL_DEBUG, "invalid args in %s.\n", __FUNCTION__); 1202 return found; 1203 } 1204 1205 *seq = 0; 1206 LIST_FOREACH(iph2, &session->ph2tree, ph2ofsession_chain) { 1207 if (iph2->approval) { 1208 struct saproto *pr; 1209 1210 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { 1211 if (pr->ok && pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP) { 1212 if (!*seq) { 1213 *seq = iph2->seq; 1214 } 1215 if (dir == IPSEC_DIR_INBOUND) { 1216 stats[found].spi = pr->spi; 1217 } else { 1218 stats[found].spi = pr->spi_p; 1219 } 1220 if (++found == max_stats) { 1221 return found; 1222 } 1223 } 1224 } 1225 } 1226 } 1227 return found; 1228} 1229 1230void 1231ike_session_update_traffic_idle_status (ike_session_t *session, 1232 u_int32_t dir, 1233 struct sastat *new_stats, 1234 u_int32_t max_stats) 1235{ 1236 int i, j, found = 0, idle = 1; 1237 1238 if (!session || !new_stats || (dir != IPSEC_DIR_INBOUND && dir != IPSEC_DIR_OUTBOUND)) { 1239 plog(ASL_LEVEL_DEBUG, "invalid args in %s.\n", __FUNCTION__); 1240 return; 1241 } 1242 1243 if (!session->established || session->stopped_by_vpn_controller || session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec) { 1244 plog(ASL_LEVEL_DEBUG, "dropping update on invalid session in %s.\n", __FUNCTION__); 1245 return; 1246 } 1247 1248 for (i = 0; i < max_stats; i++) { 1249 if (dir == IPSEC_DIR_INBOUND) { 1250 for (j = 0; j < session->traffic_monitor.num_in_last_poll; j++) { 1251 if (new_stats[i].spi != session->traffic_monitor.in_last_poll[j].spi) { 1252 continue; 1253 } 1254 found = 1; 1255 if (new_stats[i].lft_c.sadb_lifetime_bytes != session->traffic_monitor.in_last_poll[j].lft_c.sadb_lifetime_bytes) { 1256 idle = 0; 1257 } 1258 } 1259 } else { 1260 for (j = 0; j < session->traffic_monitor.num_out_last_poll; j++) { 1261 if (new_stats[i].spi != session->traffic_monitor.out_last_poll[j].spi) { 1262 continue; 1263 } 1264 found = 1; 1265 if (new_stats[i].lft_c.sadb_lifetime_bytes != session->traffic_monitor.out_last_poll[j].lft_c.sadb_lifetime_bytes) { 1266 idle = 0; 1267 } 1268 } 1269 } 1270 // new SA.... check for any activity 1271 if (!found) { 1272 if (new_stats[i].lft_c.sadb_lifetime_bytes) { 1273 plog(ASL_LEVEL_DEBUG, "new SA: dir %d....\n", dir); 1274 idle = 0; 1275 } 1276 } 1277 } 1278 if (dir == IPSEC_DIR_INBOUND) { 1279 // overwrite old stats 1280 bzero(session->traffic_monitor.in_last_poll, sizeof(session->traffic_monitor.in_last_poll)); 1281 bcopy(new_stats, session->traffic_monitor.in_last_poll, (max_stats * sizeof(*new_stats))); 1282 session->traffic_monitor.num_in_last_poll = max_stats; 1283 if (!idle) { 1284 //plog(ASL_LEVEL_DEBUG, "peer sent data....\n"); 1285 session->peer_sent_data_sc_dpd = 1; 1286 session->peer_sent_data_sc_idle = 1; 1287 } 1288 } else { 1289 // overwrite old stats 1290 bzero(session->traffic_monitor.out_last_poll, sizeof(session->traffic_monitor.out_last_poll)); 1291 bcopy(new_stats, session->traffic_monitor.out_last_poll, (max_stats * sizeof(*new_stats))); 1292 session->traffic_monitor.num_out_last_poll = max_stats; 1293 if (!idle) { 1294 //plog(ASL_LEVEL_DEBUG, "i sent data....\n"); 1295 session->i_sent_data_sc_dpd = 1; 1296 session->i_sent_data_sc_idle = 1; 1297 } 1298 } 1299 if (!idle) 1300 session->last_time_data_sc_detected = time(NULL); 1301 1302 ike_session_monitor_idle(session); 1303} 1304 1305void 1306ike_session_cleanup (ike_session_t *session, 1307 const char *reason) 1308{ 1309 phase2_handle_t *iph2 = NULL; 1310 phase2_handle_t *next_iph2 = NULL; 1311 phase1_handle_t *iph1 = NULL; 1312 phase1_handle_t *next_iph1 = NULL; 1313 1314 if (!session) 1315 return; 1316 1317 session->is_dying = 1; 1318 ike_session_stopped_by_controller(session, reason); 1319 1320 SCHED_KILL(session->traffic_monitor.sc_idle); 1321 // do ph2's first... we need the ph1s for notifications 1322 LIST_FOREACH_SAFE(iph2, &session->ph2tree, ph2ofsession_chain, next_iph2) { 1323 if (FSM_STATE_IS_ESTABLISHED(iph2->status)) { 1324 isakmp_info_send_d2(iph2); 1325 } 1326 isakmp_ph2expire(iph2); // iph2 will go down 1 second later. 1327 } 1328 1329 // do the ph1s last. 1330 LIST_FOREACH_SAFE(iph1, &session->ph1tree, ph1ofsession_chain, next_iph1) { 1331 if (FSM_STATE_IS_ESTABLISHED(iph1->status)) { 1332 isakmp_info_send_d1(iph1); 1333 } 1334 isakmp_ph1expire(iph1); 1335 } 1336 1337 // send ipsecManager a notification 1338 if (session->is_cisco_ipsec && reason && reason != ike_session_stopped_by_vpn_disconnect 1339 && reason != ike_session_stopped_by_controller_comm_lost) { 1340 u_int32_t address; 1341 if ((&session->session_id.remote)->ss_family == AF_INET) { 1342 address = ((struct sockaddr_in *)&session->session_id.remote)->sin_addr.s_addr; 1343 } else { 1344 address = 0; 1345 } 1346 // TODO: log 1347 if (reason == ike_session_stopped_by_idle) { 1348 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_IDLE_TIMEOUT, FROM_LOCAL, address, 0, NULL); 1349 } else { 1350 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_INTERNAL_ERROR, FROM_LOCAL, address, 0, NULL); 1351 } 1352 } 1353} 1354 1355int 1356ike_session_has_negoing_ph1 (ike_session_t *session) 1357{ 1358 phase1_handle_t *p; 1359 1360 if (!session) { 1361 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1362 return 0; 1363 } 1364 1365 LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { 1366 if (!p->is_dying && FSM_STATE_IS_NEGOTIATING(p->status)) { 1367 return 1; 1368 } 1369 } 1370 1371 return 0; 1372} 1373 1374int 1375ike_session_has_established_ph1 (ike_session_t *session) 1376{ 1377 phase1_handle_t *p; 1378 1379 if (!session) { 1380 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1381 return 0; 1382 } 1383 1384 LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { 1385 if (!p->is_dying && FSM_STATE_IS_ESTABLISHED(p->status)) { 1386 return 1; 1387 } 1388 } 1389 1390 return 0; 1391} 1392 1393int 1394ike_session_has_negoing_ph2 (ike_session_t *session) 1395{ 1396 phase2_handle_t *p; 1397 1398 if (!session) { 1399 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1400 return 0; 1401 } 1402 1403 LIST_FOREACH(p, &session->ph2tree, ph2ofsession_chain) { 1404 if (!p->is_dying && FSM_STATE_IS_NEGOTIATING(p->status)) { 1405 return 1; 1406 } 1407 } 1408 1409 return 0; 1410} 1411 1412int 1413ike_session_has_established_ph2 (ike_session_t *session) 1414{ 1415 phase2_handle_t *p; 1416 1417 if (!session) { 1418 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1419 return 0; 1420 } 1421 1422 LIST_FOREACH(p, &session->ph2tree, ph2ofsession_chain) { 1423 if (!p->is_dying && FSM_STATE_IS_ESTABLISHED(p->status)) { 1424 return 1; 1425 } 1426 } 1427 1428 return 0; 1429} 1430 1431void 1432ike_session_cleanup_ph1s_by_ph2 (phase2_handle_t *iph2) 1433{ 1434 phase1_handle_t *iph1 = NULL; 1435 phase1_handle_t *next_iph1 = NULL; 1436 1437 if (!iph2 || !iph2->parent_session) { 1438 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1439 return; 1440 } 1441 1442 // phase1 is no longer useful 1443 LIST_FOREACH_SAFE(iph1, &iph2->parent_session->ph1tree, ph1ofsession_chain, next_iph1) { 1444 if (FSM_STATE_IS_ESTABLISHED(iph1->status)) { 1445 isakmp_info_send_d1(iph1); 1446 } 1447 isakmp_ph1expire(iph1); 1448 } 1449} 1450 1451int 1452ike_session_is_client_ph2_rekey (phase2_handle_t *iph2) 1453{ 1454 if (iph2->parent_session && 1455 iph2->parent_session->is_client && 1456 iph2->is_rekey && 1457 iph2->parent_session->is_cisco_ipsec) { 1458 return 1; 1459 } 1460 return 0; 1461} 1462 1463int 1464ike_session_is_client_ph1_rekey (phase1_handle_t *iph1) 1465{ 1466 if (iph1->parent_session && 1467 iph1->parent_session->is_client && 1468 iph1->is_rekey && 1469 iph1->parent_session->is_cisco_ipsec) { 1470 return 1; 1471 } 1472 return 0; 1473} 1474 1475int 1476ike_session_is_client_ph1 (phase1_handle_t *iph1) 1477{ 1478 if (iph1->parent_session && 1479 iph1->parent_session->is_client) { 1480 return 1; 1481 } 1482 return 0; 1483} 1484 1485int 1486ike_session_is_client_ph2 (phase2_handle_t *iph2) 1487{ 1488 if (iph2->parent_session && 1489 iph2->parent_session->is_client) { 1490 return 1; 1491 } 1492 return 0; 1493} 1494 1495void 1496ike_session_start_xauth_timer (phase1_handle_t *iph1) 1497{ 1498 // if there are no more established ph2s, start a timer to teardown the session 1499 if (iph1->parent_session && 1500 iph1->parent_session->is_client && 1501 iph1->parent_session->is_cisco_ipsec && 1502 !iph1->parent_session->sc_xauth) { 1503 iph1->parent_session->sc_xauth = sched_new(300 /* 5 mins */, 1504 ike_session_cleanup_xauth_timeout, 1505 iph1->parent_session); 1506 } 1507} 1508 1509void 1510ike_session_stop_xauth_timer (phase1_handle_t *iph1) 1511{ 1512 if (iph1->parent_session) { 1513 SCHED_KILL(iph1->parent_session->sc_xauth); 1514 } 1515} 1516 1517static int 1518ike_session_is_id_ipany (vchar_t *ext_id) 1519{ 1520 struct id { 1521 u_int8_t type; /* ID Type */ 1522 u_int8_t proto_id; /* Protocol ID */ 1523 u_int16_t port; /* Port */ 1524 u_int32_t addr; /* IPv4 address */ 1525 u_int32_t mask; 1526 } *id_ptr; 1527 1528 /* ignore protocol and port */ 1529 id_ptr = ALIGNED_CAST(struct id *)ext_id->v; 1530 if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR && 1531 id_ptr->addr == 0) { 1532 return 1; 1533 } else if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR_SUBNET && 1534 id_ptr->mask == 0 && 1535 id_ptr->addr == 0) { 1536 return 1; 1537 } 1538 plog(ASL_LEVEL_DEBUG, "not ipany_ids in %s: type %d, addr %x, mask %x.\n", 1539 __FUNCTION__, id_ptr->type, id_ptr->addr, id_ptr->mask); 1540 return 0; 1541} 1542 1543static int 1544ike_session_is_id_portany (vchar_t *ext_id) 1545{ 1546 struct id { 1547 u_int8_t type; /* ID Type */ 1548 u_int8_t proto_id; /* Protocol ID */ 1549 u_int16_t port; /* Port */ 1550 u_int32_t addr; /* IPv4 address */ 1551 u_int32_t mask; 1552 } *id_ptr; 1553 1554 /* ignore addr */ 1555 id_ptr = ALIGNED_CAST(struct id *)ext_id->v; 1556 if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR && 1557 id_ptr->port == 0) { 1558 return 1; 1559 } 1560 plog(ASL_LEVEL_DEBUG, "not portany_ids in %s: type %d, port %x.\n", 1561 __FUNCTION__, id_ptr->type, id_ptr->port); 1562 return 0; 1563} 1564 1565static void 1566ike_session_set_id_portany (vchar_t *ext_id) 1567{ 1568 struct id { 1569 u_int8_t type; /* ID Type */ 1570 u_int8_t proto_id; /* Protocol ID */ 1571 u_int16_t port; /* Port */ 1572 u_int32_t addr; /* IPv4 address */ 1573 u_int32_t mask; 1574 } *id_ptr; 1575 1576 /* ignore addr */ 1577 id_ptr = ALIGNED_CAST(struct id *)ext_id->v; 1578 if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR) { 1579 id_ptr->port = 0; 1580 return; 1581 } 1582} 1583 1584static int 1585ike_session_cmp_ph2_ids_ipany (vchar_t *ext_id, 1586 vchar_t *ext_id_p) 1587{ 1588 if (ike_session_is_id_ipany(ext_id) && 1589 ike_session_is_id_ipany(ext_id_p)) { 1590 return 1; 1591 } 1592 return 0; 1593} 1594 1595/* 1596 * ipsec rekeys for l2tp-over-ipsec fail particularly when client is behind nat because the client's configs and policies don't 1597 * match the server's view of the client's address and port. 1598 * servers behave differently when using this address-port info to generate ids during phase2 rekeys, so try to match the incoming id to 1599 * a variety of info saved in the older phase2. 1600 */ 1601int 1602ike_session_cmp_ph2_ids (phase2_handle_t *iph2, 1603 phase2_handle_t *older_ph2) 1604{ 1605 vchar_t *portany_id = NULL; 1606 vchar_t *portany_id_p = NULL; 1607 1608 if (iph2->id && older_ph2->id && 1609 iph2->id->l == older_ph2->id->l && 1610 memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 && 1611 iph2->id_p && older_ph2->id_p && 1612 iph2->id_p->l == older_ph2->id_p->l && 1613 memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) { 1614 return 0; 1615 } 1616 if (iph2->ext_nat_id && older_ph2->ext_nat_id && 1617 iph2->ext_nat_id->l == older_ph2->ext_nat_id->l && 1618 memcmp(iph2->ext_nat_id->v, older_ph2->ext_nat_id->v, iph2->ext_nat_id->l) == 0 && 1619 iph2->ext_nat_id_p && older_ph2->ext_nat_id_p && 1620 iph2->ext_nat_id_p->l == older_ph2->ext_nat_id_p->l && 1621 memcmp(iph2->ext_nat_id_p->v, older_ph2->ext_nat_id_p->v, iph2->ext_nat_id_p->l) == 0) { 1622 return 0; 1623 } 1624 if (iph2->id && older_ph2->ext_nat_id && 1625 iph2->id->l == older_ph2->ext_nat_id->l && 1626 memcmp(iph2->id->v, older_ph2->ext_nat_id->v, iph2->id->l) == 0 && 1627 iph2->id_p && older_ph2->ext_nat_id_p && 1628 iph2->id_p->l == older_ph2->ext_nat_id_p->l && 1629 memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) { 1630 return 0; 1631 } 1632 if (iph2->id && older_ph2->ext_nat_id && 1633 iph2->id->l == older_ph2->ext_nat_id->l && 1634 memcmp(iph2->id->v, older_ph2->ext_nat_id->v, iph2->id->l) == 0 && 1635 iph2->id_p && older_ph2->id_p && 1636 iph2->id_p->l == older_ph2->id_p->l && 1637 memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) { 1638 return 0; 1639 } 1640 if (iph2->id && older_ph2->id && 1641 iph2->id->l == older_ph2->id->l && 1642 memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 && 1643 iph2->id_p && older_ph2->ext_nat_id_p && 1644 iph2->id_p->l == older_ph2->ext_nat_id_p->l && 1645 memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) { 1646 return 0; 1647 } 1648 1649 /* check if the external id has a wildcard port and compare ids accordingly */ 1650 if ((older_ph2->ext_nat_id && ike_session_is_id_portany(older_ph2->ext_nat_id)) || 1651 (older_ph2->ext_nat_id_p && ike_session_is_id_portany(older_ph2->ext_nat_id_p))) { 1652 // try ignoring ports in iph2->id and iph2->id 1653 if (iph2->id && (portany_id = vdup(iph2->id))) { 1654 ike_session_set_id_portany(portany_id); 1655 } 1656 if (iph2->id_p && (portany_id_p = vdup(iph2->id_p))) { 1657 ike_session_set_id_portany(portany_id_p); 1658 } 1659 if (portany_id && older_ph2->ext_nat_id && 1660 portany_id->l == older_ph2->ext_nat_id->l && 1661 memcmp(portany_id->v, older_ph2->ext_nat_id->v, portany_id->l) == 0 && 1662 portany_id_p && older_ph2->ext_nat_id_p && 1663 portany_id_p->l == older_ph2->ext_nat_id_p->l && 1664 memcmp(portany_id_p->v, older_ph2->ext_nat_id_p->v, portany_id_p->l) == 0) { 1665 if (portany_id) { 1666 vfree(portany_id); 1667 } 1668 if (portany_id_p) { 1669 vfree(portany_id_p); 1670 } 1671 return 0; 1672 } 1673 if (portany_id && iph2->id && older_ph2->ext_nat_id && 1674 iph2->id->l == older_ph2->ext_nat_id->l && 1675 memcmp(portany_id->v, older_ph2->ext_nat_id->v, portany_id->l) == 0 && 1676 iph2->id_p && older_ph2->id_p && 1677 iph2->id_p->l == older_ph2->id_p->l && 1678 memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) { 1679 if (portany_id) { 1680 vfree(portany_id); 1681 } 1682 if (portany_id_p) { 1683 vfree(portany_id_p); 1684 } 1685 return 0; 1686 } 1687 if (portany_id_p && iph2->id && older_ph2->id && 1688 iph2->id->l == older_ph2->id->l && 1689 memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 && 1690 iph2->id_p && older_ph2->ext_nat_id_p && 1691 iph2->id_p->l == older_ph2->ext_nat_id_p->l && 1692 memcmp(portany_id_p->v, older_ph2->ext_nat_id_p->v, portany_id_p->l) == 0) { 1693 if (portany_id) { 1694 vfree(portany_id); 1695 } 1696 if (portany_id_p) { 1697 vfree(portany_id_p); 1698 } 1699 return 0; 1700 } 1701 if (portany_id) { 1702 vfree(portany_id); 1703 } 1704 if (portany_id_p) { 1705 vfree(portany_id_p); 1706 } 1707 } 1708 return -1; 1709} 1710 1711int 1712ike_session_get_sainfo_r (phase2_handle_t *iph2) 1713{ 1714 if (iph2->parent_session && 1715 iph2->parent_session->is_client && 1716 iph2->id && iph2->id_p) { 1717 phase2_handle_t *p; 1718 int ipany_ids = ike_session_cmp_ph2_ids_ipany(iph2->id, iph2->id_p); 1719 plog(ASL_LEVEL_DEBUG, "ipany_ids %d in %s.\n", ipany_ids, __FUNCTION__); 1720 1721 LIST_FOREACH(p, &iph2->parent_session->ph2tree, ph2ofsession_chain) { 1722 if (iph2 != p && !p->is_dying && FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p->status) && p->sainfo) { 1723 plog(ASL_LEVEL_DEBUG, "candidate ph2 found in %s.\n", __FUNCTION__); 1724 if (ipany_ids || 1725 ike_session_cmp_ph2_ids(iph2, p) == 0) { 1726 plog(ASL_LEVEL_DEBUG, "candidate ph2 matched in %s.\n", __FUNCTION__); 1727 iph2->sainfo = p->sainfo; 1728 if (iph2->sainfo) 1729 retain_sainfo(iph2->sainfo); 1730 if (!iph2->spid) { 1731 iph2->spid = p->spid; 1732 } else { 1733 plog(ASL_LEVEL_DEBUG, "%s: pre-assigned spid %d.\n", __FUNCTION__, iph2->spid); 1734 } 1735 if (p->ext_nat_id) { 1736 if (iph2->ext_nat_id) { 1737 vfree(iph2->ext_nat_id); 1738 } 1739 iph2->ext_nat_id = vdup(p->ext_nat_id); 1740 } 1741 if (p->ext_nat_id_p) { 1742 if (iph2->ext_nat_id_p) { 1743 vfree(iph2->ext_nat_id_p); 1744 } 1745 iph2->ext_nat_id_p = vdup(p->ext_nat_id_p); 1746 } 1747 return 0; 1748 } 1749 } 1750 } 1751 } 1752 return -1; 1753} 1754 1755int 1756ike_session_get_proposal_r (phase2_handle_t *iph2) 1757{ 1758 if (iph2->parent_session && 1759 iph2->parent_session->is_client && 1760 iph2->id && iph2->id_p) { 1761 phase2_handle_t *p; 1762 int ipany_ids = ike_session_cmp_ph2_ids_ipany(iph2->id, iph2->id_p); 1763 plog(ASL_LEVEL_DEBUG, "ipany_ids %d in %s.\n", ipany_ids, __FUNCTION__); 1764 1765 LIST_FOREACH(p, &iph2->parent_session->ph2tree, ph2ofsession_chain) { 1766 if (iph2 != p && !p->is_dying && FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p->status) && 1767 p->approval) { 1768 plog(ASL_LEVEL_DEBUG, "candidate ph2 found in %s.\n", __FUNCTION__); 1769 if (ipany_ids || 1770 ike_session_cmp_ph2_ids(iph2, p) == 0) { 1771 plog(ASL_LEVEL_DEBUG, "candidate ph2 matched in %s.\n", __FUNCTION__); 1772 iph2->proposal = dupsaprop(p->approval, 1); 1773 if (!iph2->spid) { 1774 iph2->spid = p->spid; 1775 } else { 1776 plog(ASL_LEVEL_DEBUG, "%s: pre-assigned spid %d.\n", __FUNCTION__, iph2->spid); 1777 } 1778 return 0; 1779 } 1780 } 1781 } 1782 } 1783 return -1; 1784} 1785 1786void 1787ike_session_update_natt_version (phase1_handle_t *iph1) 1788{ 1789 if (iph1->parent_session) { 1790 if (iph1->natt_options) { 1791 iph1->parent_session->natt_version = iph1->natt_options->version; 1792 } else { 1793 iph1->parent_session->natt_version = 0; 1794 } 1795 } 1796} 1797 1798int 1799ike_session_get_natt_version (phase1_handle_t *iph1) 1800{ 1801 if (iph1->parent_session) { 1802 return(iph1->parent_session->natt_version); 1803 } 1804 return 0; 1805} 1806 1807int 1808ike_session_drop_rekey (ike_session_t *session, ike_session_rekey_type_t rekey_type) 1809{ 1810 if (session) { 1811 if (session->is_btmm_ipsec && 1812 session->last_time_data_sc_detected && 1813 session->traffic_monitor.interv_mon && 1814 session->traffic_monitor.interv_idle) { 1815 // for btmm: drop ph1/ph2 rekey if session is idle 1816 time_t now = time(NULL); 1817 1818 if ((now - session->last_time_data_sc_detected) > (session->traffic_monitor.interv_mon << 1)) { 1819 plog(ASL_LEVEL_DEBUG, "btmm session is idle: drop ph%drekey.\n", 1820 rekey_type); 1821 return 1; 1822 } 1823 } else if (!session->is_btmm_ipsec) { 1824 if (rekey_type == IKE_SESSION_REKEY_TYPE_PH1 && 1825 !ike_session_has_negoing_ph2(session) && !ike_session_has_established_ph2(session)) { 1826 // for vpn: only drop ph1 if there are no more ph2s. 1827 plog(ASL_LEVEL_DEBUG, "vpn session is idle: drop ph1 rekey.\n"); 1828 return 1; 1829 } 1830 } 1831 } 1832 return 0; 1833} 1834 1835/* 1836 * this is called after racooon receives a 'kIOMessageSystemHasPoweredOn' 1837 * a lot is done to make sure that we don't sweep a session that's already been asserted. 1838 * however, it'll be too bad if the assertion comes after the session has already been swept. 1839 */ 1840void 1841ike_session_sweep_sleepwake (void) 1842{ 1843 ike_session_t *p = NULL; 1844 ike_session_t *next_session = NULL; 1845 1846 // flag session as dying if all ph1/ph2 are dead/dying 1847 LIST_FOREACH_SAFE(p, &ike_session_tree, chain, next_session) { 1848 if (p->is_dying) { 1849 plog(ASL_LEVEL_DEBUG, "skipping sweep of dying session.\n"); 1850 continue; 1851 } 1852 SCHED_KILL(p->sc_xauth); 1853 if (p->is_asserted) { 1854 // for asserted session, traffic monitors will be restared after phase2 becomes established. 1855 SCHED_KILL(p->traffic_monitor.sc_mon); 1856 SCHED_KILL(p->traffic_monitor.sc_idle); 1857 plog(ASL_LEVEL_DEBUG, "skipping sweep of asserted session.\n"); 1858 continue; 1859 } 1860 1861 // cleanup any stopped sessions as they will go down 1862 if (p->stopped_by_vpn_controller || p->stop_timestamp.tv_sec || p->stop_timestamp.tv_usec) { 1863 plog(ASL_LEVEL_DEBUG, "sweeping stopped session.\n"); 1864 ike_session_cleanup(p, ike_session_stopped_by_sleepwake); 1865 continue; 1866 } 1867 1868 if (!ike_session_has_established_ph1(p) && !ike_session_has_established_ph2(p)) { 1869 plog(ASL_LEVEL_DEBUG, "session died while sleeping.\n"); 1870 ike_session_cleanup(p, ike_session_stopped_by_sleepwake); 1871 continue; 1872 } 1873 if (p->traffic_monitor.sc_mon) { 1874 time_t xtime; 1875 if (sched_get_time(p->traffic_monitor.sc_mon, &xtime)) { 1876 if (xtime <= swept_at) { 1877 SCHED_KILL(p->traffic_monitor.sc_mon); 1878 if (!p->is_dying && p->traffic_monitor.interv_mon) { 1879 p->traffic_monitor.sc_mon = sched_new(p->traffic_monitor.interv_mon, 1880 ike_session_traffic_cop, 1881 p); 1882 } 1883 } 1884 } 1885 } 1886 if (p->traffic_monitor.sc_idle) { 1887 time_t xtime; 1888 if (sched_get_time(p->traffic_monitor.sc_idle, &xtime)) { 1889 if (xtime <= swept_at) { 1890 SCHED_KILL(p->traffic_monitor.sc_idle); 1891 if (!p->is_dying && p->traffic_monitor.interv_idle) { 1892 p->traffic_monitor.sc_idle = sched_new(p->traffic_monitor.interv_idle, 1893 ike_session_cleanup_idle, 1894 p); 1895 } 1896 } 1897 } 1898 } 1899 } 1900} 1901 1902/* 1903 * this is called after racooon receives an assert command from the controller/pppd. 1904 * this is intended to make racoon prepare to rekey both SAs because a network event occurred. 1905 * in the event of a sleepwake, the assert could happen before or after 'ike_session_sweep_sleepwake'. 1906 */ 1907int 1908ike_session_assert_session (ike_session_t *session) 1909{ 1910 phase2_handle_t *iph2 = NULL; 1911 phase2_handle_t *iph2_next = NULL; 1912 phase1_handle_t *iph1 = NULL; 1913 phase1_handle_t *iph1_next = NULL; 1914 1915 if (!session || session->is_dying) { 1916 plog(ASL_LEVEL_DEBUG, "Invalid parameters in %s.\n", __FUNCTION__); 1917 return -1; 1918 } 1919 1920 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase2s 1921 LIST_FOREACH_SAFE(iph2, &session->ph2tree, ph2ofsession_chain, iph2_next) { 1922 if (!iph2->is_dying && !FSM_STATE_IS_EXPIRED(iph2->status)) { 1923 SCHED_KILL(iph2->sce); 1924 iph2->is_dying = 1; 1925 1926 // delete SAs (in the kernel) 1927 if (FSM_STATE_IS_ESTABLISHED(iph2->status) && iph2->approval) { 1928 struct saproto *pr; 1929 1930 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { 1931 if (pr->ok) { 1932 //log deletion 1933 plog(ASL_LEVEL_DEBUG, 1934 "Assert: Phase 2 %s deleted\n", 1935 sadbsecas2str(iph2->src, iph2->dst, iph2->satype, iph2->spid, ipsecdoi2pfkey_mode(pr->encmode))); 1936 1937 pfkey_send_delete(lcconf->sock_pfkey, 1938 ipsecdoi2pfkey_proto(pr->proto_id), 1939 ipsecdoi2pfkey_mode(pr->encmode), 1940 iph2->src, iph2->dst, pr->spi_p); 1941 } 1942 } 1943 } 1944 1945 fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_EXPIRED); // we want to delete SAs without telling the PEER 1946 iph2->sce = sched_new(3, ike_session_cleanup_ph2_stub, iph2); 1947 } 1948 } 1949 1950 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase1s 1951 LIST_FOREACH_SAFE(iph1, &session->ph1tree, ph1ofsession_chain, iph1_next) { 1952 if (!iph1->is_dying && !FSM_STATE_IS_EXPIRED(iph1->status)) { 1953 SCHED_KILL(iph1->sce); 1954 SCHED_KILL(iph1->sce_rekey); 1955 iph1->is_dying = 1; 1956 1957 //log deletion 1958 plog(ASL_LEVEL_DEBUG, 1959 "Assert: Phase 1 %s deleted\n", 1960 isakmp_pindex(&iph1->index, 0)); 1961 1962 ike_session_unbind_all_ph2_from_ph1(iph1); 1963 1964 fsm_set_state(&iph1->status, IKEV1_STATE_PHASE1_EXPIRED); // we want to delete SAs without telling the PEER 1965 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */ 1966 iph1->sce = sched_new(5, ike_session_cleanup_ph1_stub, iph1); 1967 } 1968 } 1969 session->is_asserted = 1; 1970 1971 return 0; 1972} 1973 1974int 1975ike_session_assert (struct sockaddr_storage *local, 1976 struct sockaddr_storage *remote) 1977{ 1978 ike_session_t *sess; 1979 1980 if (!local || !remote) { 1981 plog(ASL_LEVEL_DEBUG, "invalid parameters in %s.\n", __FUNCTION__); 1982 return -1; 1983 } 1984 1985 if ((sess = ike_session_get_session(local, remote, FALSE, NULL))) { 1986 return(ike_session_assert_session(sess)); 1987 } 1988 return -1; 1989} 1990 1991void 1992ike_session_ph2_retransmits (phase2_handle_t *iph2) 1993{ 1994 int num_retransmits; 1995 1996 if (!iph2->is_dying && 1997 iph2->is_rekey && 1998 iph2->ph1 && 1999 iph2->ph1->sce_rekey && !sched_is_dead(iph2->ph1->sce_rekey) && 2000 iph2->side == INITIATOR && 2001 iph2->parent_session && 2002 !iph2->parent_session->is_cisco_ipsec && /* not for Cisco */ 2003 iph2->parent_session->is_client) { 2004 num_retransmits = iph2->ph1->rmconf->retry_counter - iph2->retry_counter; 2005 if (num_retransmits == 3) { 2006 /* 2007 * phase2 negotiation is stalling on retransmits, inspite of a valid ph1. 2008 * one of the following is possible: 2009 * - (0) severe packet loss. 2010 * - (1) the peer is dead. 2011 * - (2) the peer is out of sync hence dropping this phase2 rekey (and perhaps responding with insecure 2012 * invalid-cookie notifications... but those are untrusted and so we can't rekey phase1 off that) 2013 * (2.1) the peer rebooted (or process restarted) and is now alive. 2014 * (2.2) the peer has deleted phase1 without notifying us (or the notification got dropped somehow). 2015 * (2.3) the peer has a policy/bug stopping this phase2 rekey 2016 * 2017 * in all these cases, one sure way to know is to trigger a phase1 rekey early. 2018 */ 2019 plog(ASL_LEVEL_DEBUG, "Many Phase 2 retransmits: try Phase 1 rekey and this Phase 2 to quit earlier.\n"); 2020 isakmp_ph1rekeyexpire(iph2->ph1, TRUE); 2021 iph2->retry_counter = 0; 2022 } 2023 } 2024} 2025 2026void 2027ike_session_ph1_retransmits (phase1_handle_t *iph1) 2028{ 2029 int num_retransmits; 2030 2031 if (!iph1->is_dying && 2032 iph1->is_rekey && 2033 !iph1->sce_rekey && 2034 FSM_STATE_IS_NEGOTIATING(iph1->status) && 2035 iph1->side == INITIATOR && 2036 iph1->parent_session && 2037 iph1->parent_session->is_client && 2038 !ike_session_has_other_negoing_ph1(iph1->parent_session, iph1)) { 2039 num_retransmits = iph1->rmconf->retry_counter - iph1->retry_counter; 2040 if (num_retransmits == 3) { 2041 plog(ASL_LEVEL_DEBUG, "Many Phase 1 retransmits: try quit earlier.\n"); 2042 iph1->retry_counter = 0; 2043 } 2044 } 2045} 2046 2047static void 2048ike_session_bindph12(phase1_handle_t *iph1, phase2_handle_t *iph2) 2049{ 2050 if (iph2->ph1) { 2051 plog(ASL_LEVEL_ERR, "Phase 2 already bound %s.\n", __FUNCTION__); 2052 } 2053 iph2->ph1 = iph1; 2054 LIST_INSERT_HEAD(&iph1->bound_ph2tree, iph2, ph1bind_chain); 2055} 2056 2057void 2058ike_session_unbindph12(phase2_handle_t *iph2) 2059{ 2060 if (iph2->ph1 != NULL) { 2061 iph2->ph1 = NULL; 2062 LIST_REMOVE(iph2, ph1bind_chain); 2063 } 2064} 2065 2066static void 2067ike_session_rebindph12(phase1_handle_t *new_ph1, phase2_handle_t *iph2) 2068{ 2069 if (!new_ph1) { 2070 return; 2071 } 2072 2073 // reconcile the ph1-to-ph2 binding 2074 ike_session_unbindph12(iph2); 2075 ike_session_bindph12(new_ph1, iph2); 2076 // recalculate ivm since ph1 binding has changed 2077 if (iph2->ivm != NULL) { 2078 oakley_delivm(iph2->ivm); 2079 if (FSM_STATE_IS_ESTABLISHED(new_ph1->status)) { 2080 iph2->ivm = oakley_newiv2(new_ph1, iph2->msgid); 2081 plog(ASL_LEVEL_DEBUG, "Phase 1-2 binding changed... recalculated ivm.\n"); 2082 } else { 2083 iph2->ivm = NULL; 2084 } 2085 } 2086} 2087 2088static void 2089ike_session_unbind_all_ph2_from_ph1 (phase1_handle_t *iph1) 2090{ 2091 phase2_handle_t *p = NULL; 2092 phase2_handle_t *next = NULL; 2093 2094 LIST_FOREACH_SAFE(p, &iph1->bound_ph2tree, ph1bind_chain, next) { 2095 ike_session_unbindph12(p); 2096 } 2097} 2098 2099static void 2100ike_session_rebind_all_ph12_to_new_ph1 (phase1_handle_t *old_iph1, 2101 phase1_handle_t *new_iph1) 2102{ 2103 phase2_handle_t *p = NULL; 2104 phase2_handle_t *next = NULL; 2105 2106 if (old_iph1 == new_iph1 || !old_iph1 || !new_iph1) { 2107 plog(ASL_LEVEL_DEBUG, "Invalid parameters in %s.\n", __FUNCTION__); 2108 return; 2109 } 2110 2111 if (old_iph1->parent_session != new_iph1->parent_session) { 2112 plog(ASL_LEVEL_DEBUG, "Invalid parent sessions in %s.\n", __FUNCTION__); 2113 return; 2114 } 2115 2116 LIST_FOREACH_SAFE(p, &old_iph1->bound_ph2tree, ph1bind_chain, next) { 2117 if (p->parent_session != new_iph1->parent_session) { 2118 plog(ASL_LEVEL_ERR, "Mismatched parent session in ph1bind replacement.\n"); 2119 } 2120 if (p->ph1 == new_iph1) { 2121 plog(ASL_LEVEL_ERR, "Same Phase 2 in ph1bind replacement in %s.\n",__FUNCTION__); 2122 } 2123 ike_session_rebindph12(new_iph1, p); 2124 } 2125} 2126 2127