mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-01 23:30:13 +01:00
iwd: handle new secret request types from IWD agent
The IWD DBus interface currently (https://git.kernel.org/pub/scm/network/wireless/iwd.git/tree/doc/agent-api.txt?id=38952813dddd776f66d2ed5e88eca9a892964c06) knows about 3 secret types related to 802.1x authentication in addition to the PSK secret request. Add support for the new methods and the new secret types in NM's implementation of the IWD secret agent. Note that the secret types are mapped to NMSetting8021x property keys and they are then sent to the NM Secret Agent in the hints parameter to GetSecrets, this will need support in the NM clients as the exact usage of the hints parameter is specified a little ambiguously, but this seems to be one of the permitted usages. Rework the IWD agent interface info initialization to use NM convenience macros.
This commit is contained in:
parent
ffd96edf76
commit
74d9e04a66
3 changed files with 224 additions and 97 deletions
|
|
@ -992,6 +992,127 @@ scanning_prohibited (NMDeviceIwd *self, gboolean periodic)
|
|||
return !priv->can_scan;
|
||||
}
|
||||
|
||||
/*
|
||||
* try_reply_agent_request
|
||||
*
|
||||
* Check if the connection settings already have the secrets corresponding
|
||||
* to the IWD agent method that was invoked. If they do, send the method reply
|
||||
* with the appropriate secrets. Otherwise return the missing secret's setting
|
||||
* name and key so the caller can send a NM secrets request with this data.
|
||||
* Return TRUE in either case, return FALSE if an error is detected.
|
||||
*/
|
||||
static gboolean
|
||||
try_reply_agent_request (NMDeviceIwd *self,
|
||||
NMConnection *connection,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar **setting_name,
|
||||
const gchar **setting_key,
|
||||
gboolean *replied)
|
||||
{
|
||||
const gchar *method_name = g_dbus_method_invocation_get_method_name (invocation);
|
||||
NMSettingWirelessSecurity *s_wireless_sec;
|
||||
NMSetting8021x *s_8021x;
|
||||
|
||||
s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
|
||||
s_8021x = nm_connection_get_setting_802_1x (connection);
|
||||
|
||||
*replied = FALSE;
|
||||
|
||||
if (!strcmp (method_name, "RequestPassphrase")) {
|
||||
const gchar *psk;
|
||||
|
||||
if (!s_wireless_sec)
|
||||
return FALSE;
|
||||
|
||||
psk = nm_setting_wireless_security_get_psk (s_wireless_sec);
|
||||
if (psk) {
|
||||
_LOGD (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Returning the PSK to the IWD Agent");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(s)", psk));
|
||||
*replied = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
|
||||
*setting_key = NM_SETTING_WIRELESS_SECURITY_PSK;
|
||||
return TRUE;
|
||||
} else if (!strcmp (method_name, "RequestPrivateKeyPassphrase")) {
|
||||
const gchar *password;
|
||||
|
||||
if (!s_8021x)
|
||||
return FALSE;
|
||||
|
||||
password = nm_setting_802_1x_get_private_key_password (s_8021x);
|
||||
if (password) {
|
||||
_LOGD (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Returning the private key password to the IWD Agent");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(s)", password));
|
||||
*replied = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*setting_name = NM_SETTING_802_1X_SETTING_NAME;
|
||||
*setting_key = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
|
||||
return TRUE;
|
||||
} else if (!strcmp (method_name, "RequestUserNameAndPassword")) {
|
||||
const gchar *identity, *password;
|
||||
|
||||
if (!s_8021x)
|
||||
return FALSE;
|
||||
|
||||
identity = nm_setting_802_1x_get_identity (s_8021x);
|
||||
password = nm_setting_802_1x_get_password (s_8021x);
|
||||
if (identity && password) {
|
||||
_LOGD (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Returning the username and password to the IWD Agent");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(ss)", identity, password));
|
||||
*replied = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*setting_name = NM_SETTING_802_1X_SETTING_NAME;
|
||||
if (!identity)
|
||||
*setting_key = NM_SETTING_802_1X_IDENTITY;
|
||||
else
|
||||
*setting_key = NM_SETTING_802_1X_PASSWORD;
|
||||
return TRUE;
|
||||
} else if (!strcmp (method_name, "RequestUserPassword")) {
|
||||
const gchar *password;
|
||||
|
||||
if (!s_8021x)
|
||||
return FALSE;
|
||||
|
||||
password = nm_setting_802_1x_get_password (s_8021x);
|
||||
if (password) {
|
||||
_LOGD (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Returning the user password to the IWD Agent");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(s)", password));
|
||||
*replied = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*setting_name = NM_SETTING_802_1X_SETTING_NAME;
|
||||
*setting_key = NM_SETTING_802_1X_PASSWORD;
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
wifi_secrets_get_one (NMDeviceIwd *self,
|
||||
const char *setting_name,
|
||||
NMSecretAgentGetSecretsFlags flags,
|
||||
const char *setting_key,
|
||||
GDBusMethodInvocation *invocation);
|
||||
|
||||
static void
|
||||
wifi_secrets_cb (NMActRequest *req,
|
||||
NMActRequestGetSecretsCallId *call_id,
|
||||
|
|
@ -1002,9 +1123,10 @@ wifi_secrets_cb (NMActRequest *req,
|
|||
NMDeviceIwd *self;
|
||||
NMDeviceIwdPrivate *priv;
|
||||
NMDevice *device;
|
||||
NMSettingWirelessSecurity *s_wireless_sec;
|
||||
const gchar *psk;
|
||||
GDBusMethodInvocation *invocation;
|
||||
const gchar *setting_name;
|
||||
const gchar *setting_key;
|
||||
gboolean replied;
|
||||
|
||||
nm_utils_user_data_unpack (user_data, &self, &invocation);
|
||||
|
||||
|
|
@ -1035,22 +1157,24 @@ wifi_secrets_cb (NMActRequest *req,
|
|||
goto secrets_error;
|
||||
}
|
||||
|
||||
s_wireless_sec = nm_connection_get_setting_wireless_security (nm_act_request_get_applied_connection (req));
|
||||
if (!s_wireless_sec)
|
||||
if (!try_reply_agent_request (self, nm_act_request_get_applied_connection (req),
|
||||
invocation, &setting_name, &setting_key,
|
||||
&replied))
|
||||
goto secrets_error;
|
||||
|
||||
psk = nm_setting_wireless_security_get_psk (s_wireless_sec);
|
||||
if (!psk)
|
||||
goto secrets_error;
|
||||
if (replied) {
|
||||
/* Change state back to what it was before NEED_AUTH */
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Returning a new PSK to the IWD Agent");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(s)", psk));
|
||||
|
||||
/* Change state back to what it was before NEED_AUTH */
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
||||
/* Request further secrets if we still need something */
|
||||
wifi_secrets_get_one (self,
|
||||
setting_name,
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION
|
||||
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW,
|
||||
setting_key,
|
||||
invocation);
|
||||
return;
|
||||
|
||||
secrets_error:
|
||||
|
|
@ -1066,10 +1190,11 @@ secrets_error:
|
|||
}
|
||||
|
||||
static void
|
||||
wifi_secrets_get_secrets (NMDeviceIwd *self,
|
||||
const char *setting_name,
|
||||
NMSecretAgentGetSecretsFlags flags,
|
||||
GDBusMethodInvocation *invocation)
|
||||
wifi_secrets_get_one (NMDeviceIwd *self,
|
||||
const char *setting_name,
|
||||
NMSecretAgentGetSecretsFlags flags,
|
||||
const char *setting_key,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
|
||||
NMActRequest *req;
|
||||
|
|
@ -1083,7 +1208,7 @@ wifi_secrets_get_secrets (NMDeviceIwd *self,
|
|||
TRUE,
|
||||
setting_name,
|
||||
flags,
|
||||
NULL,
|
||||
setting_key,
|
||||
wifi_secrets_cb,
|
||||
nm_utils_user_data_pack (self, invocation));
|
||||
}
|
||||
|
|
@ -1722,38 +1847,34 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object)
|
|||
}
|
||||
|
||||
gboolean
|
||||
nm_device_iwd_agent_psk_query (NMDeviceIwd *self,
|
||||
GDBusMethodInvocation *invocation)
|
||||
nm_device_iwd_agent_query (NMDeviceIwd *self,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
NMActRequest *req;
|
||||
NMSettingWirelessSecurity *s_wireless_sec;
|
||||
const gchar *psk;
|
||||
const gchar *setting_name;
|
||||
const gchar *setting_key;
|
||||
gboolean replied;
|
||||
|
||||
req = nm_device_get_act_request (NM_DEVICE (self));
|
||||
if (!req)
|
||||
return FALSE;
|
||||
|
||||
s_wireless_sec = nm_connection_get_setting_wireless_security (nm_act_request_get_applied_connection (req));
|
||||
if (!s_wireless_sec)
|
||||
if (!try_reply_agent_request (self, nm_act_request_get_applied_connection (req),
|
||||
invocation, &setting_name, &setting_key,
|
||||
&replied))
|
||||
return FALSE;
|
||||
|
||||
psk = nm_setting_wireless_security_get_psk (s_wireless_sec);
|
||||
if (psk) {
|
||||
_LOGD (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Returning the PSK to the IWD Agent");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(s)", psk));
|
||||
if (replied)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH,
|
||||
NM_DEVICE_STATE_REASON_NO_SECRETS);
|
||||
wifi_secrets_get_secrets (self,
|
||||
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION
|
||||
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW,
|
||||
invocation);
|
||||
wifi_secrets_get_one (self,
|
||||
setting_name,
|
||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION
|
||||
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW,
|
||||
setting_key,
|
||||
invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ NMDevice *nm_device_iwd_new (const char *iface, NMDeviceWifiCapabilities capabil
|
|||
|
||||
void nm_device_iwd_set_dbus_object (NMDeviceIwd *device, GDBusObject *object);
|
||||
|
||||
gboolean nm_device_iwd_agent_psk_query (NMDeviceIwd *device,
|
||||
GDBusMethodInvocation *invocation);
|
||||
gboolean nm_device_iwd_agent_query (NMDeviceIwd *device,
|
||||
GDBusMethodInvocation *invocation);
|
||||
|
||||
const CList *_nm_device_iwd_get_aps (NMDeviceIwd *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -84,12 +84,12 @@ G_DEFINE_TYPE (NMIwdManager, nm_iwd_manager, G_TYPE_OBJECT)
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
psk_agent_dbus_method_cb (GDBusConnection *connection,
|
||||
const gchar *sender, const gchar *object_path,
|
||||
const gchar *interface_name, const gchar *method_name,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
agent_dbus_method_cb (GDBusConnection *connection,
|
||||
const gchar *sender, const gchar *object_path,
|
||||
const gchar *interface_name, const gchar *method_name,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMIwdManager *self = user_data;
|
||||
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
|
||||
|
|
@ -104,7 +104,10 @@ psk_agent_dbus_method_cb (GDBusConnection *connection,
|
|||
if (!nm_streq0 (g_dbus_object_manager_client_get_name_owner (omc), sender))
|
||||
goto return_error;
|
||||
|
||||
g_variant_get (parameters, "(&o)", &network_path);
|
||||
if (!strcmp (method_name, "RequestUserPassword"))
|
||||
g_variant_get (parameters, "(&os)", &network_path, NULL);
|
||||
else
|
||||
g_variant_get (parameters, "(&o)", &network_path);
|
||||
|
||||
network = g_dbus_object_manager_get_interface (priv->object_manager,
|
||||
network_path,
|
||||
|
|
@ -145,7 +148,7 @@ psk_agent_dbus_method_cb (GDBusConnection *connection,
|
|||
goto return_error;
|
||||
}
|
||||
|
||||
if (nm_device_iwd_agent_psk_query (NM_DEVICE_IWD (device), invocation))
|
||||
if (nm_device_iwd_agent_query (NM_DEVICE_IWD (device), invocation))
|
||||
return;
|
||||
|
||||
_LOGE ("Device %s did not handle the IWD Agent request", ifname);
|
||||
|
|
@ -154,56 +157,59 @@ return_error:
|
|||
/* IWD doesn't look at the specific error */
|
||||
g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"No PSK available for this connection");
|
||||
"Secrets not available for this connection");
|
||||
}
|
||||
|
||||
static const GDBusInterfaceInfo iwd_agent_iface_info = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
|
||||
"net.connman.iwd.Agent",
|
||||
.methods = NM_DEFINE_GDBUS_METHOD_INFOS (
|
||||
NM_DEFINE_GDBUS_METHOD_INFO (
|
||||
"RequestPassphrase",
|
||||
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("network", "o"),
|
||||
),
|
||||
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("passphrase", "s"),
|
||||
),
|
||||
),
|
||||
NM_DEFINE_GDBUS_METHOD_INFO (
|
||||
"RequestPrivateKeyPassphrase",
|
||||
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("network", "o"),
|
||||
),
|
||||
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("passphrase", "s"),
|
||||
),
|
||||
),
|
||||
NM_DEFINE_GDBUS_METHOD_INFO (
|
||||
"RequestUserNameAndPassword",
|
||||
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("network", "o"),
|
||||
),
|
||||
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("user", "s"),
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("password", "s"),
|
||||
),
|
||||
),
|
||||
NM_DEFINE_GDBUS_METHOD_INFO (
|
||||
"RequestUserPassword",
|
||||
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("network", "o"),
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("user", "s"),
|
||||
),
|
||||
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
NM_DEFINE_GDBUS_ARG_INFO ("password", "s"),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
static guint
|
||||
psk_agent_export (GDBusConnection *connection, gpointer user_data,
|
||||
iwd_agent_export (GDBusConnection *connection, gpointer user_data,
|
||||
gchar **agent_path, GError **error)
|
||||
{
|
||||
static const GDBusArgInfo request_passphrase_arg_network = {
|
||||
-1,
|
||||
(gchar *) "network",
|
||||
(gchar *) "o",
|
||||
NULL,
|
||||
};
|
||||
static const GDBusArgInfo *const request_passphrase_in_args[] = {
|
||||
&request_passphrase_arg_network,
|
||||
NULL,
|
||||
};
|
||||
static const GDBusArgInfo request_passphrase_arg_passphrase = {
|
||||
-1,
|
||||
(gchar *) "passphrase",
|
||||
(gchar *) "s",
|
||||
NULL,
|
||||
};
|
||||
static const GDBusArgInfo *const request_passphrase_out_args[] = {
|
||||
&request_passphrase_arg_passphrase,
|
||||
NULL,
|
||||
};
|
||||
static const GDBusMethodInfo request_passphrase_info = {
|
||||
-1,
|
||||
(gchar *) "RequestPassphrase",
|
||||
(GDBusArgInfo **) &request_passphrase_in_args,
|
||||
(GDBusArgInfo **) &request_passphrase_out_args,
|
||||
NULL,
|
||||
};
|
||||
static const GDBusMethodInfo *const method_info[] = {
|
||||
&request_passphrase_info,
|
||||
NULL,
|
||||
};
|
||||
static GDBusInterfaceInfo interface_info = {
|
||||
-1,
|
||||
(gchar *) "net.connman.iwd.Agent",
|
||||
(GDBusMethodInfo **) &method_info,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
static GDBusInterfaceVTable vtable = {
|
||||
psk_agent_dbus_method_cb,
|
||||
NULL,
|
||||
NULL,
|
||||
static const GDBusInterfaceVTable vtable = {
|
||||
.method_call = agent_dbus_method_cb,
|
||||
};
|
||||
|
||||
gchar path[50];
|
||||
|
|
@ -221,8 +227,8 @@ psk_agent_export (GDBusConnection *connection, gpointer user_data,
|
|||
nm_sprintf_buf (path, "/agent/%u", rnd);
|
||||
|
||||
id = g_dbus_connection_register_object (connection, path,
|
||||
&interface_info, &vtable,
|
||||
user_data, NULL, error);
|
||||
NM_UNCONST_PTR (GDBusInterfaceInfo, &iwd_agent_iface_info),
|
||||
&vtable, user_data, NULL, error);
|
||||
|
||||
if (id)
|
||||
*agent_path = g_strdup (path);
|
||||
|
|
@ -549,7 +555,7 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
|
|||
|
||||
connection = g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
|
||||
|
||||
priv->agent_id = psk_agent_export (connection, self,
|
||||
priv->agent_id = iwd_agent_export (connection, self,
|
||||
&priv->agent_path, &error);
|
||||
if (!priv->agent_id) {
|
||||
_LOGE ("failed to export the IWD Agent: PSK/8021x WiFi networks will not work: %s",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue