[Swan-dev] IKEv2 rekey saga
Matt Rogers
mrogers at redhat.com
Wed May 28 23:42:30 EEST 2014
Here's what I have so far. With the event replacement changes in the patch,
ipsecdoi_replace initiates and sends a new Parent SA when the old one expires.
The rekeymargin options also don't seem to work with IKEv2 (since it's not
negotiated?) so I needed a hack to delay the delete event otherwise it goes
right out after the first IKE message on the rekey.
So we get to ikev2parent_outI1 to rekey. I don't understand the policy part of
this in regards to the addition of a pending state, as it seems that we need our
new SA's to pend until they are established and the code later on expects that
it can find a pending state.
It does:
if (HAS_IPSEC_POLICY(policy)) {
#ifdef HAVE_LABELED_IPSEC
st->sec_ctx = NULL;
if ( uctx != NULL)
libreswan_log(
"Labeled ipsec is not supported with ikev2 yet");
#endif
add_pending(dup_any(whack_sock), st, c, policy, 1,
predecessor == NULL ? SOS_NOBODY : predecessor->st_serialno
#ifdef HAVE_LABELED_IPSEC
, st->sec_ctx
#endif
);
Before we rekey the IPSEC part of the policy is removed. So this is confusing
and I work around it in the patch.
Now we rekey:
May 28 15:45:15 west pluto[16030]: | event after this is EVENT_PENDING_DDNS in 3 seconds
May 28 15:45:15 west pluto[16030]: | processing connection rekey
May 28 15:45:15 west pluto[16030]: "rekey" #1: replacing stale ISAKMP SA
May 28 15:45:15 west pluto[16030]: | creating state object #3 at 0x7f64366d6630
May 28 15:45:15 west pluto[16030]: | processing connection rekey
May 28 15:45:15 west pluto[16030]: | ICOOKIE: f0 48 39 19 c8 3c 58 e8
May 28 15:45:15 west pluto[16030]: | RCOOKIE: 00 00 00 00 00 00 00 00
May 28 15:45:15 west pluto[16030]: | state hash entry 20
May 28 15:45:15 west pluto[16030]: | inserting state object #3
May 28 15:45:15 west pluto[16030]: | inserting event EVENT_SO_DISCARD, timeout in 0 seconds for #3
May 28 15:45:15 west pluto[16030]: | event added at head of queue
May 28 15:45:15 west pluto[16030]: | processing connection rekey
May 28 15:45:15 west pluto[16030]: | Queuing pending Quick Mode with 192.168.1.113 "rekey"
May 28 15:45:15 west pluto[16030]: "rekey" #3: initiating v2 parent SA to replace #1
v2R1 comes back and:
May 28 15:45:16 west pluto[16030]: | PSK auth octets cf 29 10 e6 1d 7b bc c1 61 8c 38 6b 6d e4 47 0d
May 28 15:45:16 west pluto[16030]: | emitting 16 raw bytes of PSK auth into IKEv2 Authentication Payload
May 28 15:45:16 west pluto[16030]: | PSK auth cf 29 10 e6 1d 7b bc c1 61 8c 38 6b 6d e4 47 0d
May 28 15:45:16 west pluto[16030]: | emitting length of IKEv2 Authentication Payload: 24
May 28 15:45:16 west pluto[16030]: | kernel_alg_db_new() initial trans_cnt=0
May 28 15:45:16 west pluto[16030]: | kernel_alg_db_new() will return p_new->protoid=0, p_new->trans_cnt=0
May 28 15:45:16 west pluto[16030]: | returning new proposal from esp_info
May 28 15:45:16 west pluto[16030]: | *****emit IKEv2 Security Association Payload:
May 28 15:45:16 west pluto[16030]: | next payload type: ISAKMP_NEXT_v2TSi
May 28 15:45:16 west pluto[16030]: | critical bit: none
May 28 15:45:16 west pluto[16030]: | netlink_get_spi: allocated 0xf99f3a87 for esp.0 at 192.168.1.112
<crash> :(
Program received signal SIGSEGV, Segmentation fault.
ikev2_out_sa (outs=outs at entry=0x7fffb9898920, protoid=protoid at entry=3, sadb=0x7f1e871eb330, st=0x7f1e871f1c50, parentSA=parentSA at entry=0, np=np at entry=44 ',') at /root/libreswan-test/programs/pluto/ikev2_spdb_struct.c:149
(gdb) bt
#0 ikev2_out_sa (outs=outs at entry=0x7fffb9898920, protoid=protoid at entry=3, sadb=0x7f1e871eb330, st=0x7f1e871f1c50, parentSA=parentSA at entry=0, np=np at entry=44 ',') at /root/libreswan-test/programs/pluto/ikev2_spdb_struct.c:149
#1 0x00007f1e86529485 in ikev2_emit_ipsec_sa (md=md at entry=0x7f1e871c6aa0, outpbs=outpbs at entry=0x7fffb9898920, np=np at entry=44, c=c at entry=0x7f1e871c00c0, policy=<optimized out>) at /root/libreswan-test/programs/pluto/ikev2_spdb_struct.c:175
8
#2 0x00007f1e86521cd4 in ikev2_parent_inR1outI2_tail (pcrc=pcrc at entry=0x7f1e871ecad0, r=r at entry=0x7fffb9898b70) at /root/libreswan-test/programs/pluto/ikev2_parent.c:1625
#3 0x00007f1e86522005 in ikev2_parent_inR1outI2_continue (pcrc=0x7f1e871ecad0, r=0x7fffb9898b70, ugh=<optimized out>) at /root/libreswan-test/programs/pluto/ikev2_parent.c:1168
This happens at:
144| for (pc_cnt = 0; pc_cnt < sadb->prop_disj_cnt; pc_cnt++) {
145| struct db_v2_prop *vp = &sadb->prop_disj[pc_cnt];
146| unsigned int pr_cnt;
147|
148| /* now send out all the transforms */
149+> for (pr_cnt = 0; pr_cnt < vp->prop_cnt; pr_cnt++) {
150| unsigned int ts_cnt;
151| struct db_v2_prop_conj *vpc = &vp->props[pr_cnt];
(gdb) p vp
$1 = (struct db_v2_prop *) 0x0
(gdb) p *sadb
$4 = {
dynamic = 1,
parentSA = 0,
prop_conjs = 0x7f1e871f56c0,
prop_conj_cnt = 1,
prop_disj = 0x0,
prop_disj_cnt = 1
}
I can't tell why the prop_disj data is missing here. Any ideas?
While IKEv2 rekeying without a CREATE_CHILD_SA seems hacky enough so I don't
want to butcher this too much :)
Matt
-------------- next part --------------
diff --git a/include/pluto_constants.h b/include/pluto_constants.h
index 88fa7ab..b0e174b 100644
--- a/include/pluto_constants.h
+++ b/include/pluto_constants.h
@@ -437,6 +437,10 @@ enum phase1_role {
#define IS_PARENT_SA(st) (!IS_CHILD_SA(st))
+#define V1_V2_IKESA(st) (IS_PHASE1(st->st_state) || \
+ IS_PHASE15(st->st_state) || \
+ IS_PARENT_SA(st))
+
/* kind of struct connection
* Ordered (mostly) by concreteness. Order is exploited.
*/
diff --git a/programs/pluto/ikev2_parent.c b/programs/pluto/ikev2_parent.c
index 324610c..ed5868f 100644
--- a/programs/pluto/ikev2_parent.c
+++ b/programs/pluto/ikev2_parent.c
@@ -124,7 +124,7 @@ stf_status ikev2parent_outI1(int whack_sock,
st->st_msgid_nextuse = 0;
st->st_try = try;
- if (HAS_IPSEC_POLICY(policy)) {
+ if (HAS_IPSEC_POLICY(policy) || predecessor != NULL) {
#ifdef HAVE_LABELED_IPSEC
st->sec_ctx = NULL;
if ( uctx != NULL)
diff --git a/programs/pluto/timer.c b/programs/pluto/timer.c
index 1e919b0..7d94944 100644
--- a/programs/pluto/timer.c
+++ b/programs/pluto/timer.c
@@ -627,11 +627,11 @@ void handle_next_timer_event(void)
{
struct connection *c;
so_serial_t newest;
+ time_t margin;
passert(st != NULL);
c = st->st_connection;
- newest = (IS_PHASE1(st->st_state) ||
- IS_PHASE15(st->st_state )) ?
+ newest = V1_V2_IKESA(st) ?
c->newest_isakmp_sa : c->newest_ipsec_sa;
if (newest > st->st_serialno &&
@@ -640,9 +640,8 @@ void handle_next_timer_event(void)
DBG(DBG_LIFECYCLE,
libreswan_log(
"not replacing stale %s SA: #%lu will do",
- (IS_PHASE1(st->st_state) ||
- IS_PHASE15(st->st_state )) ?
- "ISAKMP" : "IPsec", newest));
+ V1_V2_IKESA(st) ?
+ "ISAKMP" : "IPsec", newest));
} else if (type == EVENT_SA_REPLACE_IF_USED &&
st->st_outbound_time <= tm - c->sa_rekey_margin) {
/*
@@ -666,22 +665,26 @@ void handle_next_timer_event(void)
DBG(DBG_LIFECYCLE,
libreswan_log(
"not replacing stale %s SA: inactive for %lus",
- (IS_PHASE1(st->st_state) ||
- IS_PHASE15(st->st_state )) ?
- "ISAKMP" : "IPsec",
+ V1_V2_IKESA(st) ? "ISAKMP" : "IPsec",
(unsigned long)(tm -
st->st_outbound_time)));
} else {
DBG(DBG_LIFECYCLE,
libreswan_log("replacing stale %s SA",
- (IS_PHASE1(st->st_state) ||
- IS_PHASE15(st->st_state)) ?
- "ISAKMP" : "IPsec"));
+ V1_V2_IKESA(st) ?
+ "ISAKMP" : "IPsec"));
ipsecdoi_replace(st, LEMPTY, LEMPTY, 1);
}
delete_liveness_event(st);
delete_dpd_event(st);
- event_schedule(EVENT_SA_EXPIRE, st->st_margin, st);
+
+ /* XXX hack - get around st->st_margin being 0 here on ikev2 rekey for the moment */
+ if (st->st_ikev2 && st->st_margin < 1)
+ margin = 10;
+ else
+ margin = st->st_margin;
+
+ event_schedule(EVENT_SA_EXPIRE, margin, st);
}
break;
@@ -694,7 +697,7 @@ void handle_next_timer_event(void)
passert(st != NULL);
c = st->st_connection;
- if (IS_PHASE1(st->st_state) || IS_PHASE15(st->st_state)) {
+ if (V1_V2_IKESA(st)) {
satype = "ISAKMP";
latest = c->newest_isakmp_sa;
} else {
More information about the Swan-dev
mailing list