child-create: Initiate and handle childless IKE_SAs according to RFC 6023
This commit is contained in:
parent
93104d0fe9
commit
ed521a7470
|
@ -1037,6 +1037,31 @@ static void process_payloads(private_child_create_t *this, message_t *message)
|
|||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we should defer the creation of this CHILD_SA until after the
|
||||
* IKE_SA has been established childless.
|
||||
*/
|
||||
static status_t defer_child_sa(private_child_create_t *this)
|
||||
{
|
||||
ike_cfg_t *ike_cfg;
|
||||
|
||||
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
|
||||
|
||||
if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_CHILDLESS))
|
||||
{
|
||||
if (ike_cfg->childless(ike_cfg) == CHILDLESS_FORCE)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
}
|
||||
else if (ike_cfg->childless(ike_cfg) == CHILDLESS_FORCE)
|
||||
{
|
||||
DBG1(DBG_IKE, "peer does not support childless IKE_SA initiation");
|
||||
return DESTROY_ME;
|
||||
}
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(task_t, build_i, status_t,
|
||||
private_child_create_t *this, message_t *message)
|
||||
{
|
||||
|
@ -1067,6 +1092,19 @@ METHOD(task_t, build_i, status_t,
|
|||
/* send only in the first request, not in subsequent rounds */
|
||||
return NEED_MORE;
|
||||
}
|
||||
switch (defer_child_sa(this))
|
||||
{
|
||||
case DESTROY_ME:
|
||||
/* config mismatch */
|
||||
return DESTROY_ME;
|
||||
case NEED_MORE:
|
||||
/* defer until after IKE_SA has been established */
|
||||
chunk_free(&this->my_nonce);
|
||||
return NEED_MORE;
|
||||
default:
|
||||
/* just continue to establish the CHILD_SA */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1312,6 +1350,37 @@ static child_cfg_t* select_child_cfg(private_child_create_t *this)
|
|||
return child_cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check how to handle a possibly childless IKE_SA
|
||||
*/
|
||||
static status_t handle_childless(private_child_create_t *this)
|
||||
{
|
||||
ike_cfg_t *ike_cfg;
|
||||
|
||||
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
|
||||
|
||||
if (!this->proposals && !this->tsi && !this->tsr)
|
||||
{
|
||||
/* looks like a childless IKE_SA, check if we allow it */
|
||||
if (ike_cfg->childless(ike_cfg) == CHILDLESS_NEVER)
|
||||
{
|
||||
/* we don't allow childless initiation */
|
||||
DBG1(DBG_IKE, "peer tried to initiate a childless IKE_SA");
|
||||
return INVALID_STATE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* the peer apparently wants to create a regular IKE_SA */
|
||||
if (ike_cfg->childless(ike_cfg) == CHILDLESS_FORCE)
|
||||
{
|
||||
/* reject it if we only allow childless initiation */
|
||||
DBG1(DBG_IKE, "peer did not initiate a childless IKE_SA");
|
||||
return INVALID_STATE;
|
||||
}
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(task_t, build_r, status_t,
|
||||
private_child_create_t *this, message_t *message)
|
||||
{
|
||||
|
@ -1348,6 +1417,19 @@ METHOD(task_t, build_r, status_t,
|
|||
{ /* no CHILD_SA is created for redirected SAs */
|
||||
return SUCCESS;
|
||||
}
|
||||
switch (handle_childless(this))
|
||||
{
|
||||
case SUCCESS:
|
||||
/* no CHILD_SA built */
|
||||
return SUCCESS;
|
||||
case INVALID_STATE:
|
||||
message->add_notify(message, FALSE, INVALID_SYNTAX,
|
||||
chunk_empty);
|
||||
return FAILED;
|
||||
default:
|
||||
/* continue with regular initiation */
|
||||
break;
|
||||
}
|
||||
ike_auth = TRUE;
|
||||
default:
|
||||
break;
|
||||
|
@ -1533,6 +1615,11 @@ METHOD(task_t, process_i, status_t,
|
|||
{ /* wait until all authentication round completed */
|
||||
return NEED_MORE;
|
||||
}
|
||||
if (defer_child_sa(this) == NEED_MORE)
|
||||
{ /* defer until after IKE_SA has been established */
|
||||
chunk_free(&this->other_nonce);
|
||||
return NEED_MORE;
|
||||
}
|
||||
ike_auth = TRUE;
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue