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