diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 1b5112cd60..412ca3c4a7 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -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 diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h index c76ad60768..f27ecc5bc0 100644 --- a/libnm-core/nm-connection.h +++ b/libnm-core/nm-connection.h @@ -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, diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c index 900e973eb7..0cf386d894 100644 --- a/libnm-core/nm-setting-adsl.c +++ b/libnm-core/nm-setting-adsl.c @@ -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 */ diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c index c09b9c9411..3c01b43f9a 100644 --- a/libnm-core/nm-setting-cdma.c +++ b/libnm-core/nm-setting-cdma.c @@ -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 */ diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c index 73bd6590d2..4bb5ba9fc9 100644 --- a/libnm-core/nm-setting-gsm.c +++ b/libnm-core/nm-setting-gsm.c @@ -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 */ diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index 8f59e26303..cb7ca52e3d 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -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, diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index df2190bc28..7c5e393243 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -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; diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 0f8347c166..b08eea108a 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -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, diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index 7b1d87d576..3083ef6029 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -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); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 0a73b27233..4692f12eba 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -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;