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