2 * Copyright (c) 2008 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
35 #include "isakmp_var.h"
37 #include "ike_session.h"
40 #include "nattraversal.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"
53 const char *ike_session_stopped_by_vpn_disconnect
= "Stopped by VPN disconnect";
54 const char *ike_session_stopped_by_flush
= "Stopped by Flush";
55 const char *ike_session_stopped_by_idle
= "Stopped by Idle";
56 const char *ike_session_stopped_by_xauth_timeout
= "Stopped by XAUTH timeout";
58 static LIST_HEAD(_ike_session_tree_
, ike_session
) ike_session_tree
= { NULL
};
60 static ike_session_t
*
61 new_ike_session (ike_session_id_t
*id
)
63 ike_session_t
*session
;
66 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
70 plog(LLV_DEBUG
, LOCATION
, NULL
, "new parent session.\n");
71 session
= racoon_calloc(1, sizeof(*session
));
73 bzero(session
, sizeof(*session
));
74 memcpy(&session
->session_id
, id
, sizeof(*id
));
75 LIST_INIT(&session
->ikev1_state
.ph1tree
);
76 LIST_INIT(&session
->ikev1_state
.ph2tree
);
77 LIST_INSERT_HEAD(&ike_session_tree
, session
, chain
);
78 session
->version
= IKE_VERSION_1
; // hard-coded for now
79 IPSECSESSIONTRACERSTART(session
);
85 free_ike_session (ike_session_t
*session
)
87 int is_failure
= TRUE
;
89 SCHED_KILL(session
->traffic_monitor
.sc_mon
);
90 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
91 SCHED_KILL(session
->sc_xauth
);
92 if (session
->start_timestamp
.tv_sec
|| session
->start_timestamp
.tv_usec
) {
93 if (!(session
->stop_timestamp
.tv_sec
|| session
->stop_timestamp
.tv_usec
)) {
94 gettimeofday(&session
->stop_timestamp
, NULL
);
96 if (session
->term_reason
!= ike_session_stopped_by_vpn_disconnect
||
97 session
->term_reason
!= ike_session_stopped_by_flush
||
98 session
->term_reason
!= ike_session_stopped_by_idle
) {
101 IPSECSESSIONTRACERSTOP(session
,
103 session
->term_reason
);
105 // do MessageTracer cleanup here
106 plog(LLV_DEBUG
, LOCATION
, NULL
,
107 "Freeing IKE-Session to %s.\n",
108 saddr2str((struct sockaddr
*)&session
->session_id
.remote
));
109 LIST_REMOVE(session
, chain
);
110 racoon_free(session
);
115 ike_session_get_established_or_negoing_ph1 (ike_session_t
*session
)
117 struct ph1handle
*p
, *iph1
= NULL
;
120 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
124 // look for the most mature ph1 under the session
125 for (p
= LIST_FIRST(&session
->ikev1_state
.ph1tree
); p
; p
= LIST_NEXT(p
, ph1ofsession_chain
)) {
126 if (!p
->is_dying
&& p
->status
>= PHASE1ST_START
&& p
->status
<= PHASE1ST_ESTABLISHED
) {
127 if (!iph1
|| p
->status
> iph1
->status
) {
129 } else if (iph1
&& p
->status
== iph1
->status
) {
130 // TODO: pick better one based on farthest rekey/expiry remaining
139 ike_session_get_established_ph1 (ike_session_t
*session
)
144 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
148 for (p
= LIST_FIRST(&session
->ikev1_state
.ph1tree
); p
; p
= LIST_NEXT(p
, ph1ofsession_chain
)) {
149 if (!p
->is_dying
&& p
->status
== PHASE1ST_ESTABLISHED
) {
158 ike_session_init (void)
160 LIST_INIT(&ike_session_tree
);
164 ike_session_get_rekey_lifetime (int local_spi_is_higher
, u_int expiry_lifetime
)
166 u_int rekey_lifetime
= expiry_lifetime
/ 10;
168 if (rekey_lifetime
) {
169 if (local_spi_is_higher
) {
170 return (rekey_lifetime
* 9);
172 return (rekey_lifetime
* 8);
175 if (local_spi_is_higher
) {
176 rekey_lifetime
= expiry_lifetime
- 1;
178 rekey_lifetime
= expiry_lifetime
- 2;
181 if (rekey_lifetime
< expiry_lifetime
) {
182 return (rekey_lifetime
);
187 // TODO: optimize this mess later
189 ike_session_get_session (struct sockaddr
*local
,
190 struct sockaddr
*remote
,
195 ike_session_id_t id_default
;
196 ike_session_id_t id_floated_default
;
197 ike_session_id_t id_wop
;
198 ike_session_t
*best_match
= NULL
;
199 u_int16_t remote_port
;
200 int is_isakmp_remote_port
;
202 if (!local
|| !remote
) {
203 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
207 remote_port
= extract_port(remote
);
208 if (remote_port
&& remote_port
!= PORT_ISAKMP
&& remote_port
!= PORT_ISAKMP_NATT
) {
209 is_isakmp_remote_port
= 0;
211 is_isakmp_remote_port
= 1;
214 /* 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 */
215 bzero(&id
, sizeof(id
));
216 bzero(&id_default
, sizeof(id_default
));
217 bzero(&id_floated_default
, sizeof(id_floated_default
));
218 bzero(&id_wop
, sizeof(id_wop
));
219 if (local
->sa_family
== AF_INET
) {
220 memcpy(&id
.local
, local
, sizeof(struct sockaddr_in
));
221 memcpy(&id_default
.local
, local
, sizeof(struct sockaddr_in
));
222 memcpy(&id_floated_default
.local
, local
, sizeof(struct sockaddr_in
));
223 memcpy(&id_wop
.local
, local
, sizeof(struct sockaddr_in
));
224 } else if (local
->sa_family
== AF_INET6
) {
225 memcpy(&id
.local
, local
, sizeof(struct sockaddr_in6
));
226 memcpy(&id_default
.local
, local
, sizeof(struct sockaddr_in6
));
227 memcpy(&id_floated_default
.local
, local
, sizeof(struct sockaddr_in6
));
228 memcpy(&id_wop
.local
, local
, sizeof(struct sockaddr_in6
));
230 set_port((struct sockaddr
*)&id_default
.local
, PORT_ISAKMP
);
231 set_port((struct sockaddr
*)&id_floated_default
.local
, PORT_ISAKMP_NATT
);
232 set_port((struct sockaddr
*)&id_wop
.local
, 0);
233 if (remote
->sa_family
== AF_INET
) {
234 memcpy(&id
.remote
, remote
, sizeof(struct sockaddr_in
));
235 memcpy(&id_default
.remote
, remote
, sizeof(struct sockaddr_in
));
236 memcpy(&id_floated_default
.remote
, remote
, sizeof(struct sockaddr_in
));
237 memcpy(&id_wop
.remote
, remote
, sizeof(struct sockaddr_in
));
238 } else if (remote
->sa_family
== AF_INET6
) {
239 memcpy(&id
.remote
, remote
, sizeof(struct sockaddr_in6
));
240 memcpy(&id_default
.remote
, remote
, sizeof(struct sockaddr_in6
));
241 memcpy(&id_floated_default
.remote
, remote
, sizeof(struct sockaddr_in6
));
242 memcpy(&id_wop
.remote
, remote
, sizeof(struct sockaddr_in6
));
244 set_port((struct sockaddr
*)&id_default
.remote
, PORT_ISAKMP
);
245 set_port((struct sockaddr
*)&id_floated_default
.remote
, PORT_ISAKMP_NATT
);
246 set_port((struct sockaddr
*)&id_wop
.remote
, 0);
248 plog(LLV_DEBUG
, LOCATION
, local
,
249 "start search for IKE-Session. target %s.\n",
252 for (p
= LIST_FIRST(&ike_session_tree
); p
; p
= LIST_NEXT(p
, chain
)) {
253 plog(LLV_DEBUG
, LOCATION
, local
,
254 "still search for IKE-Session. this %s.\n",
255 saddr2str((struct sockaddr
*)&p
->session_id
.remote
));
257 if (memcmp(&p
->session_id
, &id
, sizeof(id
)) == 0) {
258 plog(LLV_DEBUG
, LOCATION
, local
,
259 "Pre-existing IKE-Session to %s. case 1.\n",
262 } else if (is_isakmp_remote_port
&& memcmp(&p
->session_id
, &id_default
, sizeof(id_default
)) == 0) {
263 plog(LLV_DEBUG
, LOCATION
, local
,
264 "Pre-existing IKE-Session to %s. case 2.\n",
267 } else if (is_isakmp_remote_port
&& p
->ports_floated
&& memcmp(&p
->session_id
, &id_floated_default
, sizeof(id_floated_default
)) == 0) {
268 plog(LLV_DEBUG
, LOCATION
, local
,
269 "Pre-existing IKE-Session to %s. case 3.\n",
272 } else if (is_isakmp_remote_port
&& memcmp(&p
->session_id
, &id_wop
, sizeof(id_wop
)) == 0) {
277 plog(LLV_DEBUG
, LOCATION
, local
,
278 "Best-match IKE-Session to %s.\n",
279 saddr2str((struct sockaddr
*)&best_match
->session_id
.remote
));
282 if (alloc_if_absent
) {
283 plog(LLV_DEBUG
, LOCATION
, local
,
284 "New IKE-Session to %s.\n",
285 saddr2str((struct sockaddr
*)&id
.remote
));
286 return new_ike_session(&id
);
293 ike_session_init_traffic_cop_params (struct ph1handle
*iph1
)
297 (!iph1
->rmconf
->idle_timeout
&& !iph1
->rmconf
->dpd_interval
)) {
301 if (!iph1
->parent_session
->traffic_monitor
.interv_idle
) {
302 iph1
->parent_session
->traffic_monitor
.interv_idle
= iph1
->rmconf
->idle_timeout
;
304 if (!iph1
->parent_session
->traffic_monitor
.dir_idle
) {
305 iph1
->parent_session
->traffic_monitor
.dir_idle
= iph1
->rmconf
->idle_timeout_dir
;
308 if (!iph1
->parent_session
->traffic_monitor
.interv_mon
) {
309 int min_period
, max_period
, sample_period
= 0;
311 /* calculate the sampling interval... half the smaller interval */
312 if (iph1
->rmconf
->dpd_interval
&&
313 (iph1
->rmconf
->dpd_algo
== DPD_ALGO_INBOUND_DETECT
||
314 iph1
->rmconf
->dpd_algo
== DPD_ALGO_BLACKHOLE_DETECT
)) {
315 // when certain types of dpd are enabled
316 min_period
= MIN(iph1
->rmconf
->dpd_interval
, iph1
->rmconf
->idle_timeout
);
317 max_period
= MAX(iph1
->rmconf
->dpd_interval
, iph1
->rmconf
->idle_timeout
);
318 } else if (iph1
->rmconf
->idle_timeout
) {
319 min_period
= max_period
= iph1
->rmconf
->idle_timeout
;
321 // DPD_ALGO_DEFAULT is configured and there's no idle timeout... we don't need to monitor traffic
325 sample_period
= min_period
/ 20;
327 sample_period
= 1; // bad
329 sample_period
= max_period
/ 20;
331 sample_period
= 1; // bad
333 iph1
->parent_session
->traffic_monitor
.interv_mon
= sample_period
;
338 ike_session_link_ph1_to_session (struct ph1handle
*iph1
)
340 ike_session_t
*session
;
343 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
347 session
= ike_session_get_session(iph1
->local
, iph1
->remote
, TRUE
);
349 plog(LLV_DEBUG2
, LOCATION
, NULL
, "failed to get session in %s.\n", __FUNCTION__
);
354 if (iph1
->parent_session
) {
355 if (session
== iph1
->parent_session
) {
358 // undo previous session
359 if (ike_session_unlink_ph1_from_session(iph1
) == 0) {
360 plog(LLV_DEBUG2
, LOCATION
, NULL
, "failed to unlink ph1 in %s.\n", __FUNCTION__
);
361 free_ike_session(session
);
365 gettimeofday(&session
->start_timestamp
, NULL
);
369 if (iph1
->started_by_api
) {
370 session
->is_cisco_ipsec
= 1;
371 session
->is_l2tpvpn_ipsec
= 0;
372 session
->is_btmm_ipsec
= 0;
374 iph1
->parent_session
= session
;
375 LIST_INSERT_HEAD(&session
->ikev1_state
.ph1tree
, iph1
, ph1ofsession_chain
);
376 session
->ikev1_state
.active_ph1cnt
++;
377 if ((!session
->ikev1_state
.ph1cnt
&&
378 iph1
->side
== INITIATOR
) ||
379 iph1
->started_by_api
) {
380 // client initiates the first phase1 or, is started by controller api
381 session
->is_client
= 1;
383 if (session
->established
&&
384 session
->ikev1_state
.ph1cnt
) {
387 session
->ikev1_state
.ph1cnt
++;
388 ike_session_init_traffic_cop_params(iph1
);
394 ike_session_update_mode (struct ph2handle
*iph2
)
396 if (!iph2
|| !iph2
->parent_session
) {
400 // exit early if we already detected cisco-ipsec
401 if (iph2
->parent_session
->is_cisco_ipsec
) {
405 if (iph2
->approval
) {
406 if (!ipsecdoi_any_transportmode(iph2
->approval
)) {
407 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
408 iph2
->parent_session
->is_cisco_ipsec
= 0;
409 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
410 iph2
->parent_session
->is_btmm_ipsec
= 1;
412 } else if (ipsecdoi_transportmode(iph2
->approval
)) {
413 iph2
->parent_session
->is_cisco_ipsec
= 0;
414 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
415 iph2
->parent_session
->is_btmm_ipsec
= 0;
418 } else if (iph2
->proposal
) {
419 if (!ipsecdoi_any_transportmode(iph2
->proposal
)) {
420 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
421 iph2
->parent_session
->is_cisco_ipsec
= 0;
422 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
423 iph2
->parent_session
->is_btmm_ipsec
= 1;
425 } else if (ipsecdoi_transportmode(iph2
->proposal
)) {
426 iph2
->parent_session
->is_cisco_ipsec
= 0;
427 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
428 iph2
->parent_session
->is_btmm_ipsec
= 0;
435 ike_session_cleanup_xauth_timeout (void *arg
)
437 ike_session_t
*session
= (ike_session_t
*)arg
;
439 SCHED_KILL(session
->sc_xauth
);
440 // if there are no more established ph2s, start a timer to teardown the session
441 if (!ike_session_has_established_ph2(session
)) {
442 ike_session_cleanup(session
, ike_session_stopped_by_xauth_timeout
);
444 session
->sc_xauth
= sched_new(300 /* 5 mins */,
445 ike_session_cleanup_xauth_timeout
,
451 ike_session_link_ph2_to_session (struct ph2handle
*iph2
)
453 struct sockaddr
*local
;
454 struct sockaddr
*remote
;
455 ike_session_t
*session
;
458 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
465 session
= ike_session_get_session(local
, remote
, TRUE
);
467 plog(LLV_DEBUG2
, LOCATION
, NULL
, "failed to get session in %s.\n", __FUNCTION__
);
472 if (iph2
->parent_session
) {
473 if (session
== iph2
->parent_session
) {
476 // undo previous session
477 if (ike_session_unlink_ph2_from_session(iph2
) == 0) {
478 plog(LLV_DEBUG2
, LOCATION
, NULL
, "failed to unlink ph2 in %s.\n", __FUNCTION__
);
479 free_ike_session(session
);
484 iph2
->parent_session
= session
;
485 LIST_INSERT_HEAD(&session
->ikev1_state
.ph2tree
, iph2
, ph2ofsession_chain
);
486 session
->ikev1_state
.active_ph2cnt
++;
487 if (!session
->ikev1_state
.ph2cnt
&&
488 iph2
->side
== INITIATOR
) {
489 // client initiates the first phase2
490 session
->is_client
= 1;
492 if (session
->established
&&
493 session
->ikev1_state
.ph2cnt
) {
496 session
->ikev1_state
.ph2cnt
++;
498 ike_session_update_mode(iph2
);
504 ike_session_unlink_ph1_from_session (struct ph1handle
*iph1
)
506 ike_session_t
*session
;
508 if (!iph1
|| !iph1
->parent_session
) {
509 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
513 if (LIST_FIRST(&iph1
->ph2tree
)) {
514 // reparent any phase2 that may be hanging on to this phase1
515 ike_session_update_ph1_ph2tree(iph1
);
518 session
= iph1
->parent_session
;
519 LIST_REMOVE(iph1
, ph1ofsession_chain
);
520 iph1
->parent_session
= NULL
;
521 session
->ikev1_state
.active_ph1cnt
--;
522 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
523 free_ike_session(session
);
530 ike_session_unlink_ph2_from_session (struct ph2handle
*iph2
)
532 ike_session_t
*session
;
534 if (!iph2
|| !iph2
->parent_session
) {
535 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
539 LIST_REMOVE(iph2
, ph2ofsession_chain
);
540 session
= iph2
->parent_session
;
541 iph2
->parent_session
= NULL
;
542 session
->ikev1_state
.active_ph2cnt
--;
543 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
544 free_ike_session(session
);
551 ike_session_has_other_established_ph1 (ike_session_t
*session
, struct ph1handle
*iph1
)
559 for (p
= LIST_FIRST(&session
->ikev1_state
.ph1tree
); p
; p
= LIST_NEXT(p
, ph1ofsession_chain
)) {
560 if (iph1
!= p
&& !p
->is_dying
) {
561 if (p
->status
== PHASE1ST_ESTABLISHED
&& p
->sce_rekey
) {
571 ike_session_has_other_negoing_ph1 (ike_session_t
*session
, struct ph1handle
*iph1
)
576 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
580 for (p
= LIST_FIRST(&session
->ikev1_state
.ph1tree
); p
; p
= LIST_NEXT(p
, ph1ofsession_chain
)) {
581 if (iph1
!= p
&& !p
->is_dying
) {
582 if (p
->status
>= PHASE1ST_START
&& p
->status
<= PHASE1ST_ESTABLISHED
) {
592 ike_session_has_other_established_ph2 (ike_session_t
*session
, struct ph2handle
*iph2
)
597 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
601 for (p
= LIST_FIRST(&session
->ikev1_state
.ph2tree
); p
; p
= LIST_NEXT(p
, ph2ofsession_chain
)) {
602 if (iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
603 if (p
->status
== PHASE2ST_ESTABLISHED
) {
613 ike_session_has_other_negoing_ph2 (ike_session_t
*session
, struct ph2handle
*iph2
)
618 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
622 for (p
= LIST_FIRST(&session
->ikev1_state
.ph2tree
); p
; p
= LIST_NEXT(p
, ph2ofsession_chain
)) {
623 if (iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
624 if (p
->status
>= PHASE2ST_START
&& p
->status
< PHASE2ST_ESTABLISHED
) {
634 ike_session_unbindph12_from_ph1 (struct ph1handle
*iph1
)
636 struct ph2handle
*p
, *next
;
638 for (p
= LIST_FIRST(&iph1
->ph2tree
); p
; p
= next
) {
639 // take next pointer now, since unbind and rebind may change the underlying ph2tree list
640 next
= LIST_NEXT(p
, ph1bind
);
646 ike_session_rebindph12_from_old_ph1_to_new_ph1 (struct ph1handle
*old_iph1
,
647 struct ph1handle
*new_iph1
)
649 struct ph2handle
*p
, *next
;
651 if (old_iph1
== new_iph1
|| !old_iph1
|| !new_iph1
) {
652 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
656 if (old_iph1
->parent_session
!= new_iph1
->parent_session
) {
657 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parent sessions in %s.\n", __FUNCTION__
);
661 for (p
= LIST_FIRST(&old_iph1
->ph2tree
); p
; p
= next
) {
662 // take next pointer now, since rebind may change the underlying ph2tree list
663 next
= LIST_NEXT(p
, ph1bind
);
664 if (p
->parent_session
!= new_iph1
->parent_session
) {
665 plog(LLV_ERROR
, LOCATION
, NULL
, "mismatched parent session in ph1bind replacement.\n");
667 if (p
->ph1
== new_iph1
) {
668 plog(LLV_ERROR
, LOCATION
, NULL
, "same phase1 in ph1bind replacement in %s.\n",__FUNCTION__
);
670 rebindph12(new_iph1
, p
);
675 ike_session_verify_ph2_parent_session (struct ph2handle
*iph2
)
678 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
682 if (!iph2
->parent_session
) {
683 plog(LLV_DEBUG
, LOCATION
, NULL
, "NULL parent session.\n");
684 if (ike_session_link_ph2_to_session(iph2
)) {
685 plog(LLV_DEBUG
, LOCATION
, NULL
, "NULL parent session... still failed to link to session.\n");
686 // failed to bind ph2 to session
694 ike_session_update_ph1_ph2tree (struct ph1handle
*iph1
)
696 struct ph1handle
*new_iph1
= NULL
;
699 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
703 if (iph1
->parent_session
) {
704 new_iph1
= ike_session_get_established_ph1(iph1
->parent_session
);
707 plog(LLV_DEBUG2
, LOCATION
, NULL
, "no ph1bind replacement found. NULL ph1.\n");
708 ike_session_unbindph12_from_ph1(iph1
);
709 } else if (iph1
== new_iph1
) {
710 plog(LLV_DEBUG2
, LOCATION
, NULL
, "no ph1bind replacement found. same ph1.\n");
711 ike_session_unbindph12_from_ph1(iph1
);
713 ike_session_rebindph12_from_old_ph1_to_new_ph1(iph1
, new_iph1
);
716 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parent session in %s.\n", __FUNCTION__
);
722 ike_session_update_ph2_ph1bind (struct ph2handle
*iph2
)
724 struct ph1handle
*iph1
;
727 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
731 iph1
= ike_session_get_established_ph1(iph2
->parent_session
);
732 if (iph1
&& iph2
->ph1
&& iph1
!= iph2
->ph1
) {
733 rebindph12(iph1
, iph2
);
734 } else if (iph1
&& !iph2
->ph1
) {
735 bindph12(iph1
, iph2
);
742 ike_session_ikev1_float_ports (struct ph1handle
*iph1
)
744 struct sockaddr
*local
, *remote
;
747 if (iph1
->parent_session
) {
748 local
= (struct sockaddr
*)&iph1
->parent_session
->session_id
.local
;
749 remote
= (struct sockaddr
*)&iph1
->parent_session
->session_id
.remote
;
751 set_port(local
, extract_port(iph1
->local
));
752 set_port(remote
, extract_port(iph1
->remote
));
753 iph1
->parent_session
->ports_floated
= 1;
755 for (p
= LIST_FIRST(&iph1
->parent_session
->ikev1_state
.ph2tree
); p
; p
= LIST_NEXT(p
, ph2ofsession_chain
)) {
760 set_port(local
, extract_port(iph1
->local
));
761 set_port(remote
, extract_port(iph1
->remote
));
764 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parent session in %s.\n", __FUNCTION__
);
769 ike_session_traffic_cop (void *arg
)
771 ike_session_t
*session
= (__typeof__(session
))arg
;
774 SCHED_KILL(session
->traffic_monitor
.sc_mon
);
775 /* get traffic query from kernel */
776 if (pk_sendget_inbound_sastats(session
) < 0) {
778 plog(LLV_DEBUG2
, LOCATION
, NULL
, "pk_sendget_inbound_sastats failed in %s.\n", __FUNCTION__
);
780 if (pk_sendget_outbound_sastats(session
) < 0) {
782 plog(LLV_DEBUG2
, LOCATION
, NULL
, "pk_sendget_outbound_sastats failed in %s.\n", __FUNCTION__
);
784 session
->traffic_monitor
.sc_mon
= sched_new(session
->traffic_monitor
.interv_mon
,
785 ike_session_traffic_cop
,
789 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
794 ike_session_cleanup_idle (void *arg
)
796 ike_session_cleanup((ike_session_t
*)arg
, ike_session_stopped_by_idle
);
800 ike_session_monitor_idle (ike_session_t
*session
)
805 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_INBOUND
||
806 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
807 if (session
->peer_sent_data_sc_idle
) {
808 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
809 if (session
->traffic_monitor
.interv_idle
) {
810 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
811 ike_session_cleanup_idle
,
814 session
->peer_sent_data_sc_idle
= 0;
815 session
->i_sent_data_sc_idle
= 0;
819 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_OUTBOUND
||
820 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
821 if (session
->i_sent_data_sc_idle
) {
822 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
823 if (session
->traffic_monitor
.interv_idle
) {
824 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
825 ike_session_cleanup_idle
,
828 session
->peer_sent_data_sc_idle
= 0;
829 session
->i_sent_data_sc_idle
= 0;
836 ike_session_ph2_established (struct ph2handle
*iph2
)
838 if (!iph2
->parent_session
) {
839 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
842 SCHED_KILL(iph2
->parent_session
->sc_xauth
);
843 if (!iph2
->parent_session
->established
) {
844 gettimeofday(&iph2
->parent_session
->estab_timestamp
, NULL
);
845 iph2
->parent_session
->established
= 1;
846 IPSECSESSIONTRACERESTABLISHED(iph2
->parent_session
);
847 if (iph2
->parent_session
->traffic_monitor
.interv_mon
) {
848 iph2
->parent_session
->traffic_monitor
.sc_mon
= sched_new(iph2
->parent_session
->traffic_monitor
.interv_mon
,
849 ike_session_traffic_cop
,
850 iph2
->parent_session
);
852 if (iph2
->parent_session
->traffic_monitor
.interv_idle
) {
853 iph2
->parent_session
->traffic_monitor
.sc_idle
= sched_new(iph2
->parent_session
->traffic_monitor
.interv_idle
,
854 ike_session_cleanup_idle
,
855 iph2
->parent_session
);
858 // nothing happening to this session
859 iph2
->parent_session
->term_reason
= NULL
;
861 ike_session_update_mode(iph2
);
865 ike_session_cleanup_ph1 (struct ph1handle
*iph1
)
867 if (iph1
->status
== PHASE1ST_EXPIRED
) {
868 // since this got here via ike_session_cleanup_other_established_ph1s, assumes LIST_FIRST(&iph1->ph2tree) == NULL
869 iph1
->sce
= sched_new(1, isakmp_ph1delete_stub
, iph1
);
873 /* send delete information */
874 if (iph1
->status
== PHASE1ST_ESTABLISHED
) {
875 isakmp_info_send_d1(iph1
);
878 isakmp_ph1expire(iph1
);
882 ike_session_cleanup_ph1_stub (void *p
)
885 ike_session_cleanup_ph1((struct ph1handle
*)p
);
889 ike_session_cleanup_other_established_ph1s (ike_session_t
*session
,
890 struct ph1handle
*new_iph1
)
892 struct ph1handle
*p
, *next
;
893 char *local
, *remote
;
895 if (!session
|| !new_iph1
|| session
!= new_iph1
->parent_session
) {
896 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
900 for (p
= LIST_FIRST(&session
->ikev1_state
.ph1tree
); p
; p
= next
) {
901 // take next pointer now, since delete change the underlying ph1tree list
902 next
= LIST_NEXT(p
, ph1ofsession_chain
);
904 * TODO: currently, most recently established SA wins. Need to revisit to see if
905 * alternative selections is better (e.g. largest p->index stays).
907 if (p
!= new_iph1
&& !p
->is_dying
) {
909 SCHED_KILL(p
->sce_rekey
);
913 local
= racoon_strdup(saddr2str(p
->local
));
914 remote
= racoon_strdup(saddr2str(p
->remote
));
916 STRDUP_FATAL(remote
);
917 plog(LLV_DEBUG
, LOCATION
, NULL
,
918 "ISAKMP-SA needs to be deleted %s-%s spi:%s\n",
919 local
, remote
, isakmp_pindex(&p
->index
, 0));
923 // first rebind the children ph2s of this dying ph1 to the new ph1.
924 ike_session_rebindph12_from_old_ph1_to_new_ph1 (p
, new_iph1
);
926 if (p
->side
== INITIATOR
) {
927 /* everyone deletes old outbound SA */
928 p
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, p
);
930 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
931 p
->sce
= sched_new(7, ike_session_cleanup_ph1_stub
, p
);
938 ike_session_cleanup_ph2 (struct ph2handle
*iph2
)
940 if (iph2
->status
== PHASE2ST_EXPIRED
) {
944 SCHED_KILL(iph2
->sce
);
946 plog(LLV_ERROR
, LOCATION
, NULL
,
947 "about to cleanup ph2: status %d, seq %d dying %d\n",
948 iph2
->status
, iph2
->seq
, iph2
->is_dying
);
950 /* send delete information */
951 if (iph2
->status
== PHASE2ST_ESTABLISHED
) {
952 isakmp_info_send_d2(iph2
);
955 // delete outgoing SAs
956 if (iph2
->approval
) {
959 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
961 pfkey_send_delete(lcconf
->sock_pfkey
,
962 ipsecdoi2pfkey_proto(pr
->proto_id
),
964 iph2
->src
, iph2
->dst
, pr
->spi_p
/* pr->reqid_out */);
976 ike_session_cleanup_ph2_stub (void *p
)
979 ike_session_cleanup_ph2((struct ph2handle
*)p
);
983 ike_session_cleanup_other_established_ph2s (ike_session_t
*session
,
984 struct ph2handle
*new_iph2
)
986 struct ph2handle
*p
, *next
;
988 if (!session
|| !new_iph2
|| session
!= new_iph2
->parent_session
) {
989 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
993 for (p
= LIST_FIRST(&session
->ikev1_state
.ph2tree
); p
; p
= next
) {
994 // take next pointer now, since delete change the underlying ph2tree list
995 next
= LIST_NEXT(p
, ph2ofsession_chain
);
997 * TODO: currently, most recently established SA wins. Need to revisit to see if
998 * alternative selections is better.
1000 if (p
!= new_iph2
&& p
->spid
== new_iph2
->spid
&& !p
->is_dying
) {
1005 plog(LLV_DEBUG
, LOCATION
, NULL
,
1006 "IPsec-SA needs to be deleted: %s\n",
1007 sadbsecas2str(p
->src
, p
->dst
,
1008 p
->satype
, p
->spid
, 0));
1010 if (p
->side
== INITIATOR
) {
1011 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1012 p
->sce
= sched_new(3, ike_session_cleanup_ph2_stub
, p
);
1014 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1015 p
->sce
= sched_new(5, ike_session_cleanup_ph2_stub
, p
);
1022 ike_session_stopped_by_controller (ike_session_t
*session
,
1026 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
1029 if (session
->stop_timestamp
.tv_sec
||
1030 session
->stop_timestamp
.tv_usec
) {
1031 plog(LLV_DEBUG2
, LOCATION
, NULL
, "already stopped %s.\n", __FUNCTION__
);
1034 session
->stopped_by_vpn_controller
= 1;
1035 gettimeofday(&session
->stop_timestamp
, NULL
);
1036 if (!session
->term_reason
) {
1037 session
->term_reason
= reason
;
1042 ike_sessions_stopped_by_controller (struct sockaddr
*remote
,
1046 ike_session_t
*p
= NULL
;
1049 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
1053 for (p
= LIST_FIRST(&ike_session_tree
); p
; p
= LIST_NEXT(p
, chain
)) {
1054 if (withport
&& cmpsaddrstrict(&p
->session_id
.remote
, remote
) == 0 ||
1055 !withport
&& cmpsaddrwop(&p
->session_id
.remote
, remote
) == 0) {
1056 ike_session_stopped_by_controller(p
, reason
);
1062 ike_session_purge_ph2s_by_ph1 (struct ph1handle
*iph1
)
1064 struct ph2handle
*p
, *next
;
1066 if (!iph1
|| !iph1
->parent_session
) {
1067 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
1071 for (p
= LIST_FIRST(&iph1
->parent_session
->ikev1_state
.ph2tree
); p
; p
= next
) {
1072 // take next pointer now, since delete change the underlying ph2tree list
1073 next
= LIST_NEXT(p
, ph2ofsession_chain
);
1081 plog(LLV_DEBUG
, LOCATION
, NULL
,
1082 "IPsec-SA needs to be purged: %s\n",
1083 sadbsecas2str(p
->src
, p
->dst
,
1084 p
->satype
, p
->spid
, 0));
1086 ike_session_cleanup_ph2(p
);
1091 ike_session_update_ph2_ports (struct ph2handle
*iph2
)
1093 struct sockaddr
*local
;
1094 struct sockaddr
*remote
;
1096 if (iph2
->parent_session
) {
1097 local
= (struct sockaddr
*)&iph2
->parent_session
->session_id
.local
;
1098 remote
= (struct sockaddr
*)&iph2
->parent_session
->session_id
.remote
;
1100 set_port(iph2
->src
, extract_port(local
));
1101 set_port(iph2
->dst
, extract_port(remote
));
1103 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parent session in %s.\n", __FUNCTION__
);
1108 ike_session_get_sas_for_stats (ike_session_t
*session
,
1111 struct sastat
*stats
,
1112 u_int32_t max_stats
)
1115 struct ph2handle
*iph2
;
1117 if (!session
|| !seq
|| !stats
|| !max_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1118 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid args in %s.\n", __FUNCTION__
);
1123 for (iph2
= LIST_FIRST(&session
->ikev1_state
.ph2tree
); iph2
; iph2
= LIST_NEXT(iph2
, ph2ofsession_chain
)) {
1125 if (iph2
->approval
) {
1128 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1129 if (pr
->ok
&& pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
) {
1133 if (dir
== IPSEC_DIR_INBOUND
) {
1134 stats
[found
].spi
= pr
->spi
;
1136 stats
[found
].spi
= pr
->spi_p
;
1138 if (++found
== max_stats
) {
1149 ike_session_update_traffic_idle_status (ike_session_t
*session
,
1151 struct sastat
*new_stats
,
1152 u_int32_t max_stats
)
1154 int i
, j
, found
= 0, idle
= 1;
1156 if (!session
|| !new_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1157 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid args in %s.\n", __FUNCTION__
);
1161 if (!session
->established
|| session
->stopped_by_vpn_controller
|| session
->stop_timestamp
.tv_sec
|| session
->stop_timestamp
.tv_usec
) {
1162 plog(LLV_DEBUG2
, LOCATION
, NULL
, "dropping update on invalid session.\n", __FUNCTION__
);
1166 for (i
= 0; i
< max_stats
; i
++) {
1167 if (dir
== IPSEC_DIR_INBOUND
) {
1168 for (j
= 0; j
< session
->traffic_monitor
.num_in_last_poll
; j
++) {
1169 if (new_stats
[i
].spi
!= session
->traffic_monitor
.in_last_poll
[j
].spi
) {
1173 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.in_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1178 for (j
= 0; j
< session
->traffic_monitor
.num_out_last_poll
; j
++) {
1179 if (new_stats
[i
].spi
!= session
->traffic_monitor
.out_last_poll
[j
].spi
) {
1183 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.out_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1188 // new SA.... check for any activity
1190 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
) {
1191 plog(LLV_DEBUG
, LOCATION
, NULL
, "new SA: dir %d....\n", dir
);
1196 if (dir
== IPSEC_DIR_INBOUND
) {
1197 // overwrite old stats
1198 bzero(session
->traffic_monitor
.in_last_poll
, sizeof(session
->traffic_monitor
.in_last_poll
));
1199 bcopy(new_stats
, session
->traffic_monitor
.in_last_poll
, (max_stats
* sizeof(*new_stats
)));
1200 session
->traffic_monitor
.num_in_last_poll
= max_stats
;
1202 plog(LLV_DEBUG
, LOCATION
, NULL
, "peer sent data....\n");
1203 session
->peer_sent_data_sc_dpd
= 1;
1204 session
->peer_sent_data_sc_idle
= 1;
1207 // overwrite old stats
1208 bzero(session
->traffic_monitor
.out_last_poll
, sizeof(session
->traffic_monitor
.out_last_poll
));
1209 bcopy(new_stats
, session
->traffic_monitor
.out_last_poll
, (max_stats
* sizeof(*new_stats
)));
1210 session
->traffic_monitor
.num_out_last_poll
= max_stats
;
1212 plog(LLV_DEBUG
, LOCATION
, NULL
, "i sent data....\n");
1213 session
->i_sent_data_sc_dpd
= 1;
1214 session
->i_sent_data_sc_idle
= 1;
1218 session
->last_time_data_sc_detected
= time(NULL
);
1220 ike_session_monitor_idle(session
);
1224 ike_session_cleanup (ike_session_t
*session
,
1227 struct ph2handle
*iph2
;
1228 struct ph1handle
*iph1
;
1233 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
1234 // do ph2's first... we need the ph1s for notifications
1235 for (iph2
= LIST_FIRST(&session
->ikev1_state
.ph2tree
); iph2
; iph2
= LIST_NEXT(iph2
, ph2ofsession_chain
)) {
1236 if (iph2
->status
== PHASE2ST_ESTABLISHED
) {
1237 isakmp_info_send_d2(iph2
);
1239 isakmp_ph2expire(iph2
); // iph2 will go down 1 second later.
1240 ike_session_stopped_by_controller(session
, reason
);
1243 // do the ph1s last.
1244 for (iph1
= LIST_FIRST(&session
->ikev1_state
.ph1tree
); iph1
; iph1
= LIST_NEXT(iph1
, ph1ofsession_chain
)) {
1245 if (iph1
->status
== PHASE1ST_ESTABLISHED
) {
1246 isakmp_info_send_d1(iph1
);
1248 isakmp_ph1expire(iph1
);
1251 // send ipsecManager a notification
1252 if (reason
== ike_session_stopped_by_idle
) {
1254 if (((struct sockaddr
*)&session
->session_id
.remote
)->sa_family
== AF_INET
) {
1255 address
= ((struct sockaddr_in
*)&session
->session_id
.remote
)->sin_addr
.s_addr
;
1259 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_IDLE_TIMEOUT
, FROM_LOCAL
, address
, 0, NULL
);
1264 ike_session_has_negoing_ph1 (ike_session_t
*session
)
1266 struct ph1handle
*p
;
1269 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
1273 for (p
= LIST_FIRST(&session
->ikev1_state
.ph1tree
); p
; p
= LIST_NEXT(p
, ph1ofsession_chain
)) {
1274 if (!p
->is_dying
&& p
->status
>= PHASE1ST_START
&& p
->status
<= PHASE1ST_ESTABLISHED
) {
1283 ike_session_has_negoing_ph2 (ike_session_t
*session
)
1285 struct ph2handle
*p
;
1288 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
1292 for (p
= LIST_FIRST(&session
->ikev1_state
.ph2tree
); p
; p
= LIST_NEXT(p
, ph2ofsession_chain
)) {
1293 if (!p
->is_dying
&& p
->status
>= PHASE2ST_START
&& p
->status
<= PHASE2ST_ESTABLISHED
) {
1302 ike_session_has_established_ph2 (ike_session_t
*session
)
1304 struct ph2handle
*p
;
1307 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
1311 for (p
= LIST_FIRST(&session
->ikev1_state
.ph2tree
); p
; p
= LIST_NEXT(p
, ph2ofsession_chain
)) {
1312 if (!p
->is_dying
&& p
->status
== PHASE2ST_ESTABLISHED
) {
1321 ike_session_cleanup_ph1s_by_ph2 (struct ph2handle
*iph2
)
1323 struct ph1handle
*iph1
;
1325 if (!iph2
|| !iph2
->parent_session
) {
1326 plog(LLV_DEBUG2
, LOCATION
, NULL
, "invalid parameters in %s.\n", __FUNCTION__
);
1330 // phase1 is no longer useful
1331 for (iph1
= LIST_FIRST(&iph2
->parent_session
->ikev1_state
.ph1tree
); iph1
; iph1
= LIST_NEXT(iph1
, ph1ofsession_chain
)) {
1332 if (iph1
->status
== PHASE1ST_ESTABLISHED
) {
1333 isakmp_info_send_d1(iph1
);
1335 isakmp_ph1expire(iph1
);
1340 ike_session_is_client_ph2_rekey (struct ph2handle
*iph2
)
1342 if (iph2
->parent_session
&&
1343 iph2
->parent_session
->is_client
&&
1345 iph2
->parent_session
->is_cisco_ipsec
) {
1352 ike_session_is_client_ph1_rekey (struct ph1handle
*iph1
)
1354 if (iph1
->parent_session
&&
1355 iph1
->parent_session
->is_client
&&
1357 iph1
->parent_session
->is_cisco_ipsec
) {
1364 ike_session_start_xauth_timer (struct ph1handle
*iph1
)
1366 // if there are no more established ph2s, start a timer to teardown the session
1367 if (iph1
->parent_session
&&
1368 iph1
->parent_session
->is_client
&&
1369 iph1
->parent_session
->is_cisco_ipsec
&&
1370 !iph1
->parent_session
->sc_xauth
) {
1371 iph1
->parent_session
->sc_xauth
= sched_new(300 /* 5 mins */,
1372 ike_session_cleanup_xauth_timeout
,
1373 iph1
->parent_session
);
1378 ike_session_stop_xauth_timer (struct ph1handle
*iph1
)
1380 if (iph1
->parent_session
) {
1381 SCHED_KILL(iph1
->parent_session
->sc_xauth
);
1386 ike_session_is_id_ipany (vchar_t
*ext_id
)
1389 u_int8_t type
; /* ID Type */
1390 u_int8_t proto_id
; /* Protocol ID */
1391 u_int16_t port
; /* Port */
1392 u_int32_t addr
; /* IPv4 address */
1396 /* ignore protocol and port */
1397 id_ptr
= (struct id
*)ext_id
->v
;
1398 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1399 id_ptr
->addr
== 0) {
1401 } else if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
&&
1402 id_ptr
->mask
== 0 &&
1403 id_ptr
->addr
== 0) {
1406 plog(LLV_DEBUG2
, LOCATION
, NULL
, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
1407 __FUNCTION__
, id_ptr
->type
, id_ptr
->addr
, id_ptr
->mask
);
1412 ike_session_is_id_portany (vchar_t
*ext_id
)
1415 u_int8_t type
; /* ID Type */
1416 u_int8_t proto_id
; /* Protocol ID */
1417 u_int16_t port
; /* Port */
1418 u_int32_t addr
; /* IPv4 address */
1423 id_ptr
= (struct id
*)ext_id
->v
;
1424 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1425 id_ptr
->port
== 0) {
1428 plog(LLV_DEBUG2
, LOCATION
, NULL
, "not portany_ids in %s: type %d, port %x.\n",
1429 __FUNCTION__
, id_ptr
->type
, id_ptr
->port
);
1434 ike_session_set_id_portany (vchar_t
*ext_id
)
1437 u_int8_t type
; /* ID Type */
1438 u_int8_t proto_id
; /* Protocol ID */
1439 u_int16_t port
; /* Port */
1440 u_int32_t addr
; /* IPv4 address */
1445 id_ptr
= (struct id
*)ext_id
->v
;
1446 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
) {
1453 ike_session_cmp_ph2_ids_ipany (vchar_t
*ext_id
,
1456 if (ike_session_is_id_ipany(ext_id
) &&
1457 ike_session_is_id_ipany(ext_id_p
)) {
1464 * ipsec rekeys for l2tp-over-ipsec fail particularly when client is behind nat because the client's configs and policies don't
1465 * match the server's view of the client's address and port.
1466 * servers behave differently when using this address-port info to generate ids during phase2 rekeys, so try to match the incoming id to
1467 * a variety of info saved in the older phase2.
1470 ike_session_cmp_ph2_ids (struct ph2handle
*iph2
,
1471 struct ph2handle
*older_ph2
)
1473 vchar_t
*portany_id
= NULL
;
1474 vchar_t
*portany_id_p
= NULL
;
1476 if (iph2
->id
&& older_ph2
->id
&&
1477 iph2
->id
->l
== older_ph2
->id
->l
&&
1478 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1479 iph2
->id_p
&& older_ph2
->id_p
&&
1480 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1481 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1484 if (iph2
->ext_nat_id
&& older_ph2
->ext_nat_id
&&
1485 iph2
->ext_nat_id
->l
== older_ph2
->ext_nat_id
->l
&&
1486 memcmp(iph2
->ext_nat_id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->ext_nat_id
->l
) == 0 &&
1487 iph2
->ext_nat_id_p
&& older_ph2
->ext_nat_id_p
&&
1488 iph2
->ext_nat_id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1489 memcmp(iph2
->ext_nat_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->ext_nat_id_p
->l
) == 0) {
1492 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1493 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1494 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1495 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1496 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1497 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1500 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1501 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1502 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1503 iph2
->id_p
&& older_ph2
->id_p
&&
1504 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1505 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1508 if (iph2
->id
&& older_ph2
->id
&&
1509 iph2
->id
->l
== older_ph2
->id
->l
&&
1510 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1511 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1512 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1513 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1517 /* check if the external id has a wildcard port and compare ids accordingly */
1518 if ((older_ph2
->ext_nat_id
&& ike_session_is_id_portany(older_ph2
->ext_nat_id
)) ||
1519 (older_ph2
->ext_nat_id_p
&& ike_session_is_id_portany(older_ph2
->ext_nat_id_p
))) {
1520 // try ignoring ports in iph2->id and iph2->id
1521 if (iph2
->id
&& (portany_id
= vdup(iph2
->id
))) {
1522 ike_session_set_id_portany(portany_id
);
1524 if (iph2
->id_p
&& (portany_id_p
= vdup(iph2
->id_p
))) {
1525 ike_session_set_id_portany(portany_id_p
);
1527 if (portany_id
&& older_ph2
->ext_nat_id
&&
1528 portany_id
->l
== older_ph2
->ext_nat_id
->l
&&
1529 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1530 portany_id_p
&& older_ph2
->ext_nat_id_p
&&
1531 portany_id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1532 memcmp(portany_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, portany_id_p
->l
) == 0) {
1537 vfree(portany_id_p
);
1541 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1542 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1543 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1544 iph2
->id_p
&& older_ph2
->id_p
&&
1545 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1546 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1551 vfree(portany_id_p
);
1555 if (iph2
->id
&& older_ph2
->id
&&
1556 iph2
->id
->l
== older_ph2
->id
->l
&&
1557 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1558 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1559 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1560 memcmp(portany_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, portany_id_p
->l
) == 0) {
1565 vfree(portany_id_p
);
1573 vfree(portany_id_p
);
1580 ike_session_get_sainfo_r (struct ph2handle
*iph2
)
1582 if (iph2
->parent_session
&&
1583 iph2
->parent_session
->is_client
&&
1584 iph2
->id
&& iph2
->id_p
) {
1585 struct ph2handle
*p
;
1586 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1587 plog(LLV_DEBUG2
, LOCATION
, NULL
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1589 for (p
= LIST_FIRST(&iph2
->parent_session
->ikev1_state
.ph2tree
); p
; p
= LIST_NEXT(p
, ph2ofsession_chain
)) {
1590 if (iph2
!= p
&& !p
->is_dying
&& p
->status
>= PHASE2ST_ESTABLISHED
&&
1591 p
->sainfo
&& !p
->sainfo
->to_delete
&& !p
->sainfo
->to_remove
) {
1592 plog(LLV_DEBUG2
, LOCATION
, NULL
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1594 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1595 plog(LLV_DEBUG2
, LOCATION
, NULL
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1596 iph2
->sainfo
= p
->sainfo
;
1597 if (p
->ext_nat_id
) {
1598 if (iph2
->ext_nat_id
) {
1599 vfree(iph2
->ext_nat_id
);
1601 iph2
->ext_nat_id
= vdup(p
->ext_nat_id
);
1603 if (p
->ext_nat_id_p
) {
1604 if (iph2
->ext_nat_id_p
) {
1605 vfree(iph2
->ext_nat_id_p
);
1607 iph2
->ext_nat_id_p
= vdup(p
->ext_nat_id_p
);
1618 ike_session_get_proposal_r (struct ph2handle
*iph2
)
1620 if (iph2
->parent_session
&&
1621 iph2
->parent_session
->is_client
&&
1622 iph2
->id
&& iph2
->id_p
) {
1623 struct ph2handle
*p
;
1624 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1625 plog(LLV_DEBUG2
, LOCATION
, NULL
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1627 for (p
= LIST_FIRST(&iph2
->parent_session
->ikev1_state
.ph2tree
); p
; p
= LIST_NEXT(p
, ph2ofsession_chain
)) {
1628 if (iph2
!= p
&& !p
->is_dying
&& p
->status
>= PHASE2ST_ESTABLISHED
&&
1630 plog(LLV_DEBUG2
, LOCATION
, NULL
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1632 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1633 plog(LLV_DEBUG2
, LOCATION
, NULL
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1634 iph2
->proposal
= dupsaprop(p
->approval
, 1);
1644 ike_session_update_natt_version (struct ph1handle
*iph1
)
1646 if (iph1
->parent_session
) {
1647 if (iph1
->natt_options
) {
1648 iph1
->parent_session
->natt_version
= iph1
->natt_options
->version
;
1650 iph1
->parent_session
->natt_version
= 0;
1656 ike_session_get_natt_version (struct ph1handle
*iph1
)
1658 if (iph1
->parent_session
) {
1659 return(iph1
->parent_session
->natt_version
);
1665 ike_session_drop_rekey (ike_session_t
*session
)
1668 // drop if btmm session is idle) {
1669 if (session
->is_btmm_ipsec
&&
1670 session
->last_time_data_sc_detected
&&
1671 session
->traffic_monitor
.interv_mon
&&
1672 session
->traffic_monitor
.interv_idle
) {
1673 time_t now
= time(NULL
);
1675 if ((now
- session
->last_time_data_sc_detected
) > (session
->traffic_monitor
.interv_mon
<< 1)) {
1676 plog(LLV_DEBUG2
, LOCATION
, NULL
, "session is idle: drop rekey.\n");
1685 ike_session_ph2_retransmits (struct ph2handle
*iph2
)
1687 int num_retransmits
;
1689 if (!iph2
->is_dying
&&
1692 iph2
->ph1
->sce_rekey
&& !iph2
->ph1
->sce_rekey
->dead
&&
1693 iph2
->parent_session
&&
1694 !iph2
->parent_session
->is_cisco_ipsec
&& /* not for Cisco */
1695 iph2
->parent_session
->is_client
) {
1696 num_retransmits
= iph2
->ph1
->rmconf
->retry_counter
- iph2
->retry_counter
;
1697 if (num_retransmits
== 3) {
1699 * phase2 negotiation is stalling on retransmits, inspite of a valid ph1.
1700 * one of the following is possible:
1701 * - (0) severe packet loss.
1702 * - (1) the peer is dead.
1703 * - (2) the peer is out of sync hence dropping this phase2 rekey (and perhaps responding with insecure
1704 * invalid-cookie notifications... but those are untrusted and so we can't rekey phase1 off that)
1705 * (2.1) the peer rebooted (or process restarted) and is now alive.
1706 * (2.2) the peer has deleted phase1 without notifying us (or the notification got dropped somehow).
1707 * (2.3) the peer has a policy/bug stopping this phase2 rekey
1709 * in all these cases, one sure way to know is to trigger a phase1 rekey early.
1711 plog(LLV_DEBUG2
, LOCATION
, NULL
, "many phase2 retransmits: try phase1 rekey and this phase2 to quit earlier.\n");
1712 isakmp_ph1rekeyexpire(iph2
->ph1
, TRUE
);
1713 iph2
->retry_counter
= 0;