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