libnm,core: make for-each-secret implementation virtual functions of NMSetting

We already need to special handle regular settings (with secrets as
GObject properties) and VPN secrets.

Next, we will also need to special handle WireGuard peers, which can
have secrets too.

Move the code to a virtual function, so that "nm-connection.c" and
"nm-setting.c" does not have explicit per-setting knowledge.
This commit is contained in:
Thomas Haller
2019-01-31 09:38:58 +01:00
parent 866ac505a8
commit 353e619c9f
5 changed files with 99 additions and 54 deletions

View File

@@ -1881,7 +1881,7 @@ GVariant *
_nm_connection_for_each_secret (NMConnection *self,
GVariant *secrets,
gboolean remove_non_secrets,
NMConnectionForEachSecretFunc callback,
_NMConnectionForEachSecretFunc callback,
gpointer callback_data)
{
GVariantBuilder secrets_builder;
@@ -1900,10 +1900,8 @@ _nm_connection_for_each_secret (NMConnection *self,
* The one complexity is that the VPN setting's 'secrets' property is
* *also* a dict (since the key/value pairs are arbitrary and known
* only to the VPN plugin itself). That means we have three levels of
* dicts that we potentially have to traverse here. When we hit the
* VPN setting's 'secrets' property, we special-case that and iterate over
* each item in that 'secrets' dict, calling the supplied callback
* each time.
* dicts that we potentially have to traverse here. The differences
* are handled by the virtual for_each_secret() function.
*/
g_return_val_if_fail (callback, NULL);
@@ -1923,49 +1921,14 @@ _nm_connection_for_each_secret (NMConnection *self,
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
while (g_variant_iter_next (setting_iter, "{&sv}", &secret_name, &val)) {
_nm_unused gs_unref_variant GVariant *val_free = val;
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
/* VPN secrets need slightly different treatment here since the
* "secrets" property is actually a hash table of secrets.
*/
if (NM_IS_SETTING_VPN (setting) && !g_strcmp0 (secret_name, NM_SETTING_VPN_SECRETS)) {
GVariantBuilder vpn_secrets_builder;
GVariantIter vpn_secrets_iter;
const char *vpn_secret_name, *secret;
if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("a{ss}"))) {
/* invalid type. Silently ignore the secrets as we cannot find out the
* secret-flags. */
g_variant_unref (val);
continue;
}
/* Iterate through each secret from the VPN dict in the overall secrets dict */
g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
g_variant_iter_init (&vpn_secrets_iter, val);
while (g_variant_iter_next (&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) {
/* we ignore the return value of get_secret_flags. The function may determine
* that this is not a secret, based on having not secret-flags and no secrets.
* But we have the secret at hand. We know it would be a valid secret, if we
* only would add it to the VPN settings. */
nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL);
if (callback (secret_flags, callback_data))
g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
}
g_variant_builder_add (&setting_builder, "{sv}",
secret_name, g_variant_builder_end (&vpn_secrets_builder));
} else {
if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) {
if (!remove_non_secrets)
g_variant_builder_add (&setting_builder, "{sv}", secret_name, val);
continue;
}
if (callback (secret_flags, callback_data))
g_variant_builder_add (&setting_builder, "{sv}", secret_name, val);
}
NM_SETTING_GET_CLASS (setting)->for_each_secret (setting,
secret_name,
val,
remove_non_secrets,
callback,
callback_data,
&setting_builder);
}
g_variant_builder_add (&secrets_builder, "{sa{sv}}", setting_name, &setting_builder);

View File

@@ -733,14 +733,10 @@ GBytes *_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme,
/*****************************************************************************/
/* Return TRUE to keep (copy to the result), FALSE to drop. */
typedef gboolean (*NMConnectionForEachSecretFunc) (NMSettingSecretFlags flags,
gpointer user_data);
GVariant *_nm_connection_for_each_secret (NMConnection *self,
GVariant *secrets,
gboolean remove_non_secrets,
NMConnectionForEachSecretFunc callback,
_NMConnectionForEachSecretFunc callback,
gpointer callback_data);
typedef gboolean (*NMConnectionFindSecretFunc) (NMSettingSecretFlags flags,

View File

@@ -684,6 +684,57 @@ update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError
return success;
}
static void
for_each_secret (NMSetting *setting,
const char *secret_name,
GVariant *val,
gboolean remove_non_secrets,
_NMConnectionForEachSecretFunc callback,
gpointer callback_data,
GVariantBuilder *setting_builder)
{
GVariantBuilder vpn_secrets_builder;
GVariantIter vpn_secrets_iter;
const char *vpn_secret_name;
const char *secret;
if (!nm_streq (secret_name, NM_SETTING_VPN_SECRETS)) {
NM_SETTING_CLASS (nm_setting_vpn_parent_class)->for_each_secret (setting,
secret_name,
val,
remove_non_secrets,
callback,
callback_data,
setting_builder);
return;
}
if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("a{ss}"))) {
/* invalid type. Silently ignore the secrets as we cannot find out the
* secret-flags. */
return;
}
/* Iterate through each secret from the VPN dict in the overall secrets dict */
g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
g_variant_iter_init (&vpn_secrets_iter, val);
while (g_variant_iter_next (&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) {
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
/* we ignore the return value of get_secret_flags. The function may determine
* that this is not a secret, based on having not secret-flags and no secrets.
* But we have the secret at hand. We know it would be a valid secret, if we
* only add it to the VPN settings. */
nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL);
if (callback (secret_flags, callback_data))
g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
}
g_variant_builder_add (setting_builder, "{sv}",
secret_name, g_variant_builder_end (&vpn_secrets_builder));
}
static gboolean
get_secret_flags (NMSetting *setting,
const char *secret_name,
@@ -976,6 +1027,7 @@ nm_setting_vpn_class_init (NMSettingVpnClass *klass)
setting_class->verify = verify;
setting_class->update_one_secret = update_one_secret;
setting_class->for_each_secret = for_each_secret;
setting_class->get_secret_flags = get_secret_flags;
setting_class->set_secret_flags = set_secret_flags;
setting_class->need_secrets = need_secrets;

View File

@@ -2094,6 +2094,26 @@ _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **erro
return result;
}
static void
for_each_secret (NMSetting *setting,
const char *secret_name,
GVariant *val,
gboolean remove_non_secrets,
_NMConnectionForEachSecretFunc callback,
gpointer callback_data,
GVariantBuilder *setting_builder)
{
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) {
if (!remove_non_secrets)
g_variant_builder_add (setting_builder, "{sv}", secret_name, val);
return;
}
if (callback (secret_flags, callback_data))
g_variant_builder_add (setting_builder, "{sv}", secret_name, val);
}
static void
_set_error_secret_property_not_found (GError **error,
NMSetting *setting,
@@ -2629,6 +2649,7 @@ nm_setting_class_init (NMSettingClass *setting_class)
setting_class->set_secret_flags = set_secret_flags;
setting_class->compare_property = compare_property;
setting_class->clear_secrets = clear_secrets;
setting_class->for_each_secret = for_each_secret;
setting_class->duplicate_copy_properties = duplicate_copy_properties;
setting_class->enumerate_values = enumerate_values;
setting_class->aggregate = aggregate;

View File

@@ -187,6 +187,10 @@ typedef void (*NMSettingValueIterFn) (NMSetting *setting,
GParamFlags flags,
gpointer user_data);
/*< private >*/
typedef gboolean (*_NMConnectionForEachSecretFunc) (NMSettingSecretFlags flags,
gpointer user_data);
typedef struct {
GObjectClass parent;
@@ -253,10 +257,19 @@ typedef struct {
gpointer arg);
/*< private >*/
const struct _NMMetaSettingInfo *setting_info;
void (*for_each_secret) (NMSetting *setting,
const char *secret_name,
GVariant *val,
gboolean remove_non_secrets,
_NMConnectionForEachSecretFunc callback,
gpointer callback_data,
GVariantBuilder *setting_builder);
/*< private >*/
gpointer padding[3];
gpointer padding[2];
/*< private >*/
const struct _NMMetaSettingInfo *setting_info;
} NMSettingClass;
GType nm_setting_get_type (void);