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