Merge branch 'nm-reauth'

With these changes, the NM service should be able to handle
reauthentication (and redirection) by switching to the new IKE_SA and
not considering the old SA going down an error.

Fixes #852.
This commit is contained in:
Tobias Brunner
2020-02-14 13:58:50 +01:00
+61 -52
View File
@@ -248,77 +248,85 @@ static void signal_failure(NMVpnServicePlugin *plugin, NMVpnPluginFailure failur
nm_vpn_service_plugin_failure(plugin, failure); nm_vpn_service_plugin_failure(plugin, failure);
} }
/** METHOD(listener_t, ike_state_change, bool,
* Implementation of listener_t.ike_state_change NMStrongswanPluginPrivate *this, ike_sa_t *ike_sa, ike_sa_state_t state)
*/
static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa,
ike_sa_state_t state)
{ {
NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; if (this->ike_sa == ike_sa && state == IKE_DESTROYING)
if (private->ike_sa == ike_sa && state == IKE_DESTROYING)
{ {
signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); signal_failure(this->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED);
return FALSE;
} }
return TRUE; return TRUE;
} }
/** METHOD(listener_t, child_state_change, bool,
* Implementation of listener_t.child_state_change NMStrongswanPluginPrivate *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
*/ child_sa_state_t state)
static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa,
child_sa_t *child_sa, child_sa_state_t state)
{ {
NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; if (this->ike_sa == ike_sa && state == CHILD_DESTROYING)
if (private->ike_sa == ike_sa && state == CHILD_DESTROYING)
{ {
signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); signal_failure(this->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
return FALSE;
} }
return TRUE; return TRUE;
} }
/** METHOD(listener_t, ike_rekey, bool,
* Implementation of listener_t.child_updown NMStrongswanPluginPrivate *this, ike_sa_t *old, ike_sa_t *new)
*/
static bool child_updown(listener_t *listener, ike_sa_t *ike_sa,
child_sa_t *child_sa, bool up)
{ {
NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; if (this->ike_sa == old)
{ /* follow a rekeyed IKE_SA */
this->ike_sa = new;
}
return TRUE;
}
if (private->ike_sa == ike_sa) METHOD(listener_t, ike_reestablish_pre, bool,
NMStrongswanPluginPrivate *this, ike_sa_t *old, ike_sa_t *new)
{
if (this->ike_sa == old)
{ /* ignore child state changes during redirects etc. (task migration) */
this->listener.child_state_change = NULL;
}
return TRUE;
}
METHOD(listener_t, ike_reestablish_post, bool,
NMStrongswanPluginPrivate *this, ike_sa_t *old, ike_sa_t *new,
bool initiated)
{
if (this->ike_sa == old && initiated)
{ /* if we get redirected during IKE_AUTH we just migrate to the new SA */
this->ike_sa = new;
/* re-register hooks to detect initiation failures */
this->listener.ike_state_change = _ike_state_change;
this->listener.child_state_change = _child_state_change;
}
return TRUE;
}
METHOD(listener_t, child_updown, bool,
NMStrongswanPluginPrivate *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
bool up)
{
if (this->ike_sa == ike_sa)
{ {
if (up) if (up)
{ /* disable initiate-failure-detection hooks */ { /* disable initiate-failure-detection hooks */
private->listener.ike_state_change = NULL; this->listener.ike_state_change = NULL;
private->listener.child_state_change = NULL; this->listener.child_state_change = NULL;
signal_ip_config(private->plugin, ike_sa, child_sa); signal_ip_config(this->plugin, ike_sa, child_sa);
} }
else else
{ {
signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); if (ike_sa->has_condition(ike_sa, COND_REAUTHENTICATING))
return FALSE; { /* we ignore this during reauthentication */
return TRUE;
}
signal_failure(this->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
} }
} }
return TRUE; return TRUE;
} }
/**
* Implementation of listener_t.ike_rekey
*/
static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new)
{
NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
if (private->ike_sa == old)
{ /* follow a rekeyed IKE_SA */
private->ike_sa = new;
}
return TRUE;
}
/** /**
* Find a certificate for which we have a private key on a smartcard * Find a certificate for which we have a private key on a smartcard
*/ */
@@ -827,9 +835,8 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
* Register listener, enable initiate-failure-detection hooks * Register listener, enable initiate-failure-detection hooks
*/ */
priv->ike_sa = ike_sa; priv->ike_sa = ike_sa;
priv->listener.ike_state_change = ike_state_change; priv->listener.ike_state_change = _ike_state_change;
priv->listener.child_state_change = child_state_change; priv->listener.child_state_change = _child_state_change;
charon->bus->add_listener(charon->bus, &priv->listener);
/** /**
* Initiate * Initiate
@@ -837,7 +844,6 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
child_cfg->get_ref(child_cfg); child_cfg->get_ref(child_cfg);
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
{ {
charon->bus->remove_listener(charon->bus, &priv->listener);
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
@@ -968,8 +974,11 @@ static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
priv->plugin = NM_VPN_SERVICE_PLUGIN(plugin); priv->plugin = NM_VPN_SERVICE_PLUGIN(plugin);
memset(&priv->listener, 0, sizeof(listener_t)); memset(&priv->listener, 0, sizeof(listener_t));
priv->listener.child_updown = child_updown; priv->listener.child_updown = _child_updown;
priv->listener.ike_rekey = ike_rekey; priv->listener.ike_rekey = _ike_rekey;
priv->listener.ike_reestablish_pre = _ike_reestablish_pre;
priv->listener.ike_reestablish_post = _ike_reestablish_post;
charon->bus->add_listener(charon->bus, &priv->listener);
priv->name = NULL; priv->name = NULL;
} }