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