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