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