libnm: add nm_setting_verify_secrets() and nm_connection_verify_secrets()
authorJiří Klimeš <jklimes@redhat.com>
Tue, 10 Nov 2015 13:36:20 +0000 (14:36 +0100)
committerJiří Klimeš <jklimes@redhat.com>
Fri, 20 Nov 2015 09:35:10 +0000 (10:35 +0100)
for verifying the secrets, because it is not done in plain nm_setting_verify().

For simple verification of free-form string secrets,
_nm_setting_verify_secret_string() helper is used.

libnm-core/nm-connection.c
libnm-core/nm-connection.h
libnm-core/nm-setting-adsl.c
libnm-core/nm-setting-cdma.c
libnm-core/nm-setting-gsm.c
libnm-core/nm-setting-private.h
libnm-core/nm-setting-wireless-security.c
libnm-core/nm-setting.c
libnm-core/nm-setting.h
libnm/libnm.ver

index 1b5112c..412ca3c 100644 (file)
@@ -896,6 +896,34 @@ EXIT:
        return success;
 }
 
+/**
+ * nm_connection_verify_secrets:
+ * @connection: the #NMConnection to verify in
+ * @error: location to store error, or %NULL
+ *
+ * Verifies the secrets in the connection.
+ *
+ * Returns: %TRUE if the secrets are valid, %FALSE if they are not
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_connection_verify_secrets (NMConnection *connection, GError **error)
+{
+       GHashTableIter iter;
+       NMSetting *setting;
+
+       g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+       g_return_val_if_fail (!error || !*error, FALSE);
+
+       g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+       while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
+               if (!nm_setting_verify_secrets (setting, connection, error))
+                       return FALSE;
+       }
+       return TRUE;
+}
+
 /**
  * nm_connection_normalize:
  * @connection: the #NMConnection to normalize
index c76ad60..f27ecc5 100644 (file)
@@ -145,6 +145,8 @@ gboolean      nm_connection_diff          (NMConnection *a,
                                            GHashTable **out_settings);
 
 gboolean      nm_connection_verify        (NMConnection *connection, GError **error);
+NM_AVAILABLE_IN_1_2
+gboolean      nm_connection_verify_secrets (NMConnection *connection, GError **error);
 gboolean      nm_connection_normalize     (NMConnection *connection,
                                            GHashTable *parameters,
                                            gboolean *modified,
index 900e973..0cf386d 100644 (file)
@@ -226,6 +226,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
        return TRUE;
 }
 
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+       return _nm_setting_verify_secret_string (NM_SETTING_ADSL_GET_PRIVATE (setting)->password,
+                                                NM_SETTING_ADSL_SETTING_NAME,
+                                                NM_SETTING_ADSL_PASSWORD,
+                                                error);
+}
+
 static GPtrArray *
 need_secrets (NMSetting *setting)
 {
@@ -349,6 +358,7 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
        object_class->get_property = get_property;
        object_class->finalize     = finalize;
        parent_class->verify       = verify;
+       parent_class->verify_secrets = verify_secrets;
        parent_class->need_secrets = need_secrets;
 
        /* Properties */
index c09b9c9..3c01b43 100644 (file)
@@ -162,6 +162,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
        return TRUE;
 }
 
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+       return _nm_setting_verify_secret_string (NM_SETTING_CDMA_GET_PRIVATE (setting)->password,
+                                                NM_SETTING_CDMA_SETTING_NAME,
+                                                NM_SETTING_CDMA_PASSWORD,
+                                                error);
+}
+
 static GPtrArray *
 need_secrets (NMSetting *setting)
 {
@@ -264,6 +273,7 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
        object_class->get_property = get_property;
        object_class->finalize     = finalize;
        parent_class->verify       = verify;
+       parent_class->verify_secrets = verify_secrets;
        parent_class->need_secrets = need_secrets;
 
        /* Properties */
index 73bd659..4bb5ba9 100644 (file)
@@ -414,6 +414,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
        return TRUE;
 }
 
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+       return _nm_setting_verify_secret_string (NM_SETTING_GSM_GET_PRIVATE (setting)->password,
+                                                NM_SETTING_GSM_SETTING_NAME,
+                                                NM_SETTING_GSM_PASSWORD,
+                                                error);
+}
+
 static GPtrArray *
 need_secrets (NMSetting *setting)
 {
@@ -583,6 +592,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
        object_class->get_property = get_property;
        object_class->finalize     = finalize;
        parent_class->verify       = verify;
+       parent_class->verify_secrets = verify_secrets;
        parent_class->need_secrets = need_secrets;
 
        /* Properties */
index 8f59e26..cb7ca52 100644 (file)
@@ -112,6 +112,11 @@ NMSettingVerifyResult _nm_setting_verify (NMSetting *setting,
                                           NMConnection *connection,
                                           GError **error);
 
+gboolean _nm_setting_verify_secret_string (const char *str,
+                                           const char *setting_name,
+                                           const char *property,
+                                           GError **error);
+
 gboolean _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type);
 
 GVariant   *_nm_setting_to_dbus       (NMSetting *setting,
index df2190b..7c5e393 100644 (file)
@@ -1016,6 +1016,63 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
        return TRUE;
 }
 
+static gboolean
+_verify_wep_key (const char *wep_key,
+                 NMWepKeyType wep_key_type,
+                 const char *property,
+                 GError **error)
+{
+       if (wep_key && !nm_utils_wep_key_valid (wep_key, wep_key_type)) {
+               g_set_error_literal (error,
+                                    NM_CONNECTION_ERROR,
+                                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                    _("property is invalid"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, property);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+       NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (setting);
+       NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self);
+
+       /* LEAP */
+       if (   priv->auth_alg
+           && !strcmp (priv->auth_alg, "leap")
+           && !strcmp (priv->key_mgmt, "ieee8021x")) {
+               if (!_nm_setting_verify_secret_string (priv->leap_password,
+                                                      NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+                                                      NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+                                                      error))
+                       return FALSE;
+       }
+
+       /* WEP */
+       if (!_verify_wep_key (priv->wep_key0, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, error))
+               return FALSE;
+       if (!_verify_wep_key (priv->wep_key1, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, error))
+               return FALSE;
+       if (!_verify_wep_key (priv->wep_key2, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, error))
+               return FALSE;
+       if (!_verify_wep_key (priv->wep_key3, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, error))
+               return FALSE;
+
+       /* WPA-PSK */
+       if (priv->psk && !nm_utils_wpa_psk_valid (priv->psk)) {
+               g_set_error_literal (error,
+                                    NM_CONNECTION_ERROR,
+                                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                    _("property is invalid"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PSK);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 static gboolean
 get_secret_flags (NMSetting *setting,
                   const char *secret_name,
@@ -1266,6 +1323,7 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
        object_class->finalize     = finalize;
 
        parent_class->verify           = verify;
+       parent_class->verify_secrets   = verify_secrets;
        parent_class->need_secrets     = need_secrets;
        parent_class->get_secret_flags = get_secret_flags;
        parent_class->set_secret_flags = set_secret_flags;
index 0f8347c..b08eea1 100644 (file)
@@ -1010,6 +1010,53 @@ _nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error
        return NM_SETTING_VERIFY_SUCCESS;
 }
 
+/**
+ * nm_setting_verify_secrets:
+ * @setting: the #NMSetting to verify secrets in
+ * @connection: (allow-none): the #NMConnection that @setting came from, or
+ *   %NULL if @setting is being verified in isolation.
+ * @error: location to store error, or %NULL
+ *
+ * Verifies the secrets in the setting.
+ * The returned #GError contains information about which secret of the setting
+ * failed validation, and in what way that secret failed validation.
+ * The secret validation is done separately from main setting validation, because
+ * in some cases connection failure is not desired just for the secrets.
+ *
+ * Returns: %TRUE if the setting secrets are valid, %FALSE if they are not
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+       g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
+       g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
+       g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
+
+       if (NM_SETTING_GET_CLASS (setting)->verify_secrets)
+               return NM_SETTING_GET_CLASS (setting)->verify_secrets (setting, connection, error);
+
+       return NM_SETTING_VERIFY_SUCCESS;
+}
+
+gboolean
+_nm_setting_verify_secret_string (const char *str,
+                                  const char *setting_name,
+                                  const char *property,
+                                  GError **error)
+{
+       if (str && !*str) {
+               g_set_error_literal (error,
+                                    NM_CONNECTION_ERROR,
+                                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                    _("property is empty"));
+               g_prefix_error (error, "%s.%s: ", setting_name, property);
+               return FALSE;
+       }
+       return TRUE;
+}
+
 static gboolean
 compare_property (NMSetting *setting,
                   NMSetting *other,
index 7b1d87d..3083ef6 100644 (file)
@@ -180,6 +180,10 @@ typedef struct {
                                          NMConnection  *connection,
                                          GError       **error);
 
+       gboolean    (*verify_secrets)    (NMSetting     *setting,
+                                         NMConnection  *connection,
+                                         GError       **error);
+
        GPtrArray  *(*need_secrets)      (NMSetting  *setting);
 
        int         (*update_one_secret) (NMSetting  *setting,
@@ -211,7 +215,7 @@ typedef struct {
                                          NMSettingCompareFlags flags);
 
        /*< private >*/
-       gpointer padding[8];
+       gpointer padding[7];
 } NMSettingClass;
 
 /**
@@ -242,6 +246,11 @@ gboolean    nm_setting_verify        (NMSetting     *setting,
                                       NMConnection  *connection,
                                       GError       **error);
 
+NM_AVAILABLE_IN_1_2
+gboolean    nm_setting_verify_secrets (NMSetting     *setting,
+                                       NMConnection  *connection,
+                                       GError       **error);
+
 gboolean    nm_setting_compare       (NMSetting *a,
                                       NMSetting *b,
                                       NMSettingCompareFlags flags);
index 0a73b27..4692f12 100644 (file)
@@ -858,6 +858,7 @@ libnm_1_0_6 {
 libnm_1_2_0 {
 global:
        nm_access_point_get_last_seen;
+       nm_connection_verify_secrets;
        nm_device_ethernet_get_s390_subchannels;
        nm_device_get_lldp_neighbors;
        nm_device_get_metered;
@@ -895,6 +896,7 @@ global:
        nm_setting_ip_config_remove_dns_option;
        nm_setting_ip_config_remove_dns_option_by_value;
        nm_setting_mac_randomization_get_type;
+       nm_setting_verify_secrets;
        nm_setting_vpn_get_timeout;
        nm_setting_wired_get_wake_on_lan;
        nm_setting_wired_get_wake_on_lan_password;