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