/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* * Dan Williams * Tambet Ingo * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * * (C) Copyright 2007 - 2008 Red Hat, Inc. * (C) Copyright 2007 - 2008 Novell, Inc. */ #include #include #include #include "nm-setting-8021x.h" #include "nm-param-spec-specialized.h" #include "nm-utils.h" #include "nm-dbus-glib-types.h" #include "crypto.h" #include "nm-utils-private.h" GQuark nm_setting_802_1x_error_quark (void) { static GQuark quark; if (G_UNLIKELY (!quark)) quark = g_quark_from_static_string ("nm-setting-802-1x-error-quark"); return quark; } /* This should really be standard. */ #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } GType nm_setting_802_1x_error_get_type (void) { static GType etype = 0; if (etype == 0) { static const GEnumValue values[] = { /* Unknown error. */ ENUM_ENTRY (NM_SETTING_802_1X_ERROR_UNKNOWN, "UnknownError"), /* The specified property was invalid. */ ENUM_ENTRY (NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, "InvalidProperty"), /* The specified property was missing and is required. */ ENUM_ENTRY (NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, "MissingProperty"), { 0, 0, 0 } }; etype = g_enum_register_static ("NMSetting8021xError", values); } return etype; } G_DEFINE_TYPE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING) #define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) typedef struct { GSList *eap; /* GSList of strings */ char *identity; char *anonymous_identity; GByteArray *ca_cert; char *ca_path; GByteArray *client_cert; char *phase1_peapver; char *phase1_peaplabel; char *phase1_fast_provisioning; char *phase2_auth; char *phase2_autheap; GByteArray *phase2_ca_cert; char *phase2_ca_path; GByteArray *phase2_client_cert; char *password; char *pin; char *psk; GByteArray *private_key; char *private_key_password; GByteArray *phase2_private_key; char *phase2_private_key_password; gboolean system_ca_certs; } NMSetting8021xPrivate; enum { PROP_0, PROP_EAP, PROP_IDENTITY, PROP_ANONYMOUS_IDENTITY, PROP_CA_CERT, PROP_CA_PATH, PROP_CLIENT_CERT, PROP_PHASE1_PEAPVER, PROP_PHASE1_PEAPLABEL, PROP_PHASE1_FAST_PROVISIONING, PROP_PHASE2_AUTH, PROP_PHASE2_AUTHEAP, PROP_PHASE2_CA_CERT, PROP_PHASE2_CA_PATH, PROP_PHASE2_CLIENT_CERT, PROP_PASSWORD, PROP_PRIVATE_KEY, PROP_PRIVATE_KEY_PASSWORD, PROP_PHASE2_PRIVATE_KEY, PROP_PHASE2_PRIVATE_KEY_PASSWORD, PROP_PIN, PROP_PSK, PROP_SYSTEM_CA_CERTS, LAST_PROP }; NMSetting * nm_setting_802_1x_new (void) { return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL); } guint32 nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0); return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->eap); } const char * nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i) { NMSetting8021xPrivate *priv; g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); priv = NM_SETTING_802_1X_GET_PRIVATE (setting); g_return_val_if_fail (i <= g_slist_length (priv->eap), NULL); return (const char *) g_slist_nth_data (priv->eap, i); } gboolean nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap) { NMSetting8021xPrivate *priv; GSList *iter; g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); g_return_val_if_fail (eap != NULL, FALSE); priv = NM_SETTING_802_1X_GET_PRIVATE (setting); for (iter = priv->eap; iter; iter = g_slist_next (iter)) { if (!strcmp (eap, (char *) iter->data)) return FALSE; } priv->eap = g_slist_append (priv->eap, g_ascii_strdown (eap, -1)); return TRUE; } void nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i) { NMSetting8021xPrivate *priv; GSList *elt; g_return_if_fail (NM_IS_SETTING_802_1X (setting)); priv = NM_SETTING_802_1X_GET_PRIVATE (setting); elt = g_slist_nth (priv->eap, i); g_return_if_fail (elt != NULL); g_free (elt->data); priv->eap = g_slist_delete_link (priv->eap, elt); } void nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting) { NMSetting8021xPrivate *priv; g_return_if_fail (NM_IS_SETTING_802_1X (setting)); priv = NM_SETTING_802_1X_GET_PRIVATE (setting); nm_utils_slist_free (priv->eap, g_free); priv->eap = NULL; } const char * nm_setting_802_1x_get_identity (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->identity; } const char * nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->anonymous_identity; } const GByteArray * nm_setting_802_1x_get_ca_cert (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert; } const char * nm_setting_802_1x_get_ca_path (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_path; } gboolean nm_setting_802_1x_set_ca_cert_from_file (NMSetting8021x *self, const char *filename, NMSetting8021xCKType *out_ck_type, GError **err) { NMSetting8021xPrivate *priv; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); g_return_val_if_fail (filename != NULL, FALSE); if (out_ck_type) g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE); priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (priv->ca_cert) g_byte_array_free (priv->ca_cert, TRUE); priv->ca_cert = crypto_load_and_verify_certificate (filename, &format, err); if (priv->ca_cert) { /* wpa_supplicant can only use raw x509 CA certs */ switch (format) { case NM_CRYPTO_FILE_FORMAT_X509: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509; break; default: g_byte_array_free (priv->ca_cert, TRUE); priv->ca_cert = NULL; g_set_error (err, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_CA_CERT); break; } } return priv->ca_cert != NULL; } gboolean nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); return NM_SETTING_802_1X_GET_PRIVATE (setting)->system_ca_certs; } const GByteArray * nm_setting_802_1x_get_client_cert (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert; } gboolean nm_setting_802_1x_set_client_cert_from_file (NMSetting8021x *self, const char *filename, NMSetting8021xCKType *out_ck_type, GError **err) { NMSetting8021xPrivate *priv; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); g_return_val_if_fail (filename != NULL, FALSE); if (out_ck_type) g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE); priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (priv->client_cert) g_byte_array_free (priv->client_cert, TRUE); priv->client_cert = crypto_load_and_verify_certificate (filename, &format, err); if (priv->client_cert) { switch (format) { case NM_CRYPTO_FILE_FORMAT_X509: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509; break; case NM_CRYPTO_FILE_FORMAT_PKCS12: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12; break; default: g_byte_array_free (priv->client_cert, TRUE); priv->client_cert = NULL; g_set_error (err, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_CLIENT_CERT); break; } } return priv->client_cert != NULL; } const char * nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peapver; } const char * nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peaplabel; } const char * nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_fast_provisioning; } const char * nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_auth; } const char * nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_autheap; } const GByteArray * nm_setting_802_1x_get_phase2_ca_cert (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert; } const char * nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_path; } gboolean nm_setting_802_1x_set_phase2_ca_cert_from_file (NMSetting8021x *self, const char *filename, NMSetting8021xCKType *out_ck_type, GError **err) { NMSetting8021xPrivate *priv; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); g_return_val_if_fail (filename != NULL, FALSE); if (out_ck_type) g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE); priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (priv->phase2_ca_cert) g_byte_array_free (priv->phase2_ca_cert, TRUE); priv->phase2_ca_cert = crypto_load_and_verify_certificate (filename, &format, err); if (priv->phase2_ca_cert) { /* wpa_supplicant can only use X509 CA certs */ switch (format) { case NM_CRYPTO_FILE_FORMAT_X509: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509; break; default: g_byte_array_free (priv->phase2_ca_cert, TRUE); priv->phase2_ca_cert = NULL; g_set_error (err, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_CA_CERT); break; } } return priv->phase2_ca_cert != NULL; } const GByteArray * nm_setting_802_1x_get_phase2_client_cert (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert; } gboolean nm_setting_802_1x_set_phase2_client_cert_from_file (NMSetting8021x *self, const char *filename, NMSetting8021xCKType *out_ck_type, GError **err) { NMSetting8021xPrivate *priv; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); g_return_val_if_fail (filename != NULL, FALSE); if (out_ck_type) g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE); priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (priv->phase2_client_cert) g_byte_array_free (priv->phase2_client_cert, TRUE); priv->phase2_client_cert = crypto_load_and_verify_certificate (filename, &format, err); if (priv->phase2_client_cert) { /* Only X509 client certs should be used; not pkcs#12 */ switch (format) { case NM_CRYPTO_FILE_FORMAT_X509: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509; break; case NM_CRYPTO_FILE_FORMAT_PKCS12: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12; break; default: g_byte_array_free (priv->phase2_client_cert, TRUE); priv->phase2_client_cert = NULL; g_set_error (err, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_CLIENT_CERT); break; } } return priv->phase2_client_cert != NULL; } const char * nm_setting_802_1x_get_password (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->password; } const char * nm_setting_802_1x_get_pin (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->pin; } const char * nm_setting_802_1x_get_psk (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->psk; } const GByteArray * nm_setting_802_1x_get_private_key (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key; } const char * nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key_password; } gboolean nm_setting_802_1x_set_private_key_from_file (NMSetting8021x *self, const char *filename, const char *password, NMSetting8021xCKType *out_ck_type, GError **err) { NMSetting8021xPrivate *priv; NMCryptoKeyType ignore = NM_CRYPTO_KEY_TYPE_UNKNOWN; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); g_return_val_if_fail (filename != NULL, FALSE); if (out_ck_type) g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE); priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (priv->private_key) { /* Try not to leave the decrypted private key around in memory */ memset (priv->private_key, 0, priv->private_key->len); g_byte_array_free (priv->private_key, TRUE); } g_free (priv->private_key_password); priv->private_key_password = NULL; priv->private_key = crypto_get_private_key (filename, password, &ignore, &format, err); if (priv->private_key) { switch (format) { case NM_CRYPTO_FILE_FORMAT_RAW_KEY: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_RAW_KEY; break; case NM_CRYPTO_FILE_FORMAT_PKCS12: // FIXME: use secure memory priv->private_key_password = g_strdup (password); if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12; /* As required by NM, set the client-cert property to the same PKCS#12 data */ if (priv->client_cert) g_byte_array_free (priv->client_cert, TRUE); priv->client_cert = g_byte_array_sized_new (priv->private_key->len); g_byte_array_append (priv->client_cert, priv->private_key->data, priv->private_key->len); break; default: g_assert_not_reached (); break; } } else { /* As a special case for private keys, even if the decrypt fails, * return the key's file type. */ if (out_ck_type && crypto_is_pkcs12_file (filename)) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12; } return priv->private_key != NULL; } NMSetting8021xCKType nm_setting_802_1x_get_private_key_type (NMSetting8021x *setting) { NMSetting8021xPrivate *priv; g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_TYPE_UNKNOWN); priv = NM_SETTING_802_1X_GET_PRIVATE (setting); if (!priv->private_key) return NM_SETTING_802_1X_CK_TYPE_UNKNOWN; if (crypto_is_pkcs12_data (priv->private_key)) return NM_SETTING_802_1X_CK_TYPE_PKCS12; return NM_SETTING_802_1X_CK_TYPE_X509; } const GByteArray * nm_setting_802_1x_get_phase2_private_key (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key; } const char * nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key_password; } gboolean nm_setting_802_1x_set_phase2_private_key_from_file (NMSetting8021x *self, const char *filename, const char *password, NMSetting8021xCKType *out_ck_type, GError **err) { NMSetting8021xPrivate *priv; NMCryptoKeyType ignore = NM_CRYPTO_KEY_TYPE_UNKNOWN; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); g_return_val_if_fail (filename != NULL, FALSE); if (out_ck_type) g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE); priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (priv->phase2_private_key) { /* Try not to leave the decrypted private key around in memory */ memset (priv->phase2_private_key, 0, priv->phase2_private_key->len); g_byte_array_free (priv->phase2_private_key, TRUE); } g_free (priv->phase2_private_key_password); priv->phase2_private_key_password = NULL; priv->phase2_private_key = crypto_get_private_key (filename, password, &ignore, &format, err); if (priv->phase2_private_key) { switch (format) { case NM_CRYPTO_FILE_FORMAT_RAW_KEY: if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_RAW_KEY; break; case NM_CRYPTO_FILE_FORMAT_PKCS12: // FIXME: use secure memory priv->phase2_private_key_password = g_strdup (password); if (out_ck_type) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12; /* As required by NM, set the client-cert property to the same PKCS#12 data */ if (priv->phase2_client_cert) g_byte_array_free (priv->phase2_client_cert, TRUE); priv->phase2_client_cert = g_byte_array_sized_new (priv->phase2_private_key->len); g_byte_array_append (priv->phase2_client_cert, priv->phase2_private_key->data, priv->phase2_private_key->len); break; default: g_assert_not_reached (); break; } } else { /* As a special case for private keys, even if the decrypt fails, * return the key's file type. */ if (out_ck_type && crypto_is_pkcs12_file (filename)) *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12; } return priv->phase2_private_key != NULL; } NMSetting8021xCKType nm_setting_802_1x_get_phase2_private_key_type (NMSetting8021x *setting) { NMSetting8021xPrivate *priv; g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_TYPE_UNKNOWN); priv = NM_SETTING_802_1X_GET_PRIVATE (setting); if (!priv->phase2_private_key) return NM_SETTING_802_1X_CK_TYPE_UNKNOWN; if (crypto_is_pkcs12_data (priv->phase2_private_key)) return NM_SETTING_802_1X_CK_TYPE_PKCS12; return NM_SETTING_802_1X_CK_TYPE_X509; } static void need_secrets_password (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (!priv->password || !strlen (priv->password)) g_ptr_array_add (secrets, NM_SETTING_802_1X_PASSWORD); } static void need_secrets_sim (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (!priv->pin || !strlen (priv->pin)) g_ptr_array_add (secrets, NM_SETTING_802_1X_PIN); } static gboolean need_private_key_password (GByteArray *key, const char *password) { GError *error = NULL; gboolean needed = TRUE; /* See if a private key password is needed, which basically is whether * or not the private key is a PKCS#12 file or not, since PKCS#1 files * are decrypted by the settings service. */ if (!crypto_is_pkcs12_data (key)) return FALSE; if (crypto_verify_pkcs12 (key, password, &error)) return FALSE; /* pkcs#12 validation successful */ /* If the error was a decryption error then a password is needed */ if (!error || g_error_matches (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED)) needed = TRUE; g_clear_error (&error); return needed; } static void need_secrets_tls (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (phase2) { if (!priv->phase2_private_key || !priv->phase2_private_key->len) g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); else if (need_private_key_password (priv->phase2_private_key, priv->phase2_private_key_password)) g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); } else { if (!priv->private_key || !priv->private_key->len) g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY); else if (need_private_key_password (priv->private_key, priv->private_key_password)) g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); } } static gboolean verify_tls (NMSetting8021x *self, gboolean phase2, GError **error) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (phase2) { if (!priv->phase2_client_cert) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_PHASE2_CLIENT_CERT); return FALSE; } else if (!priv->phase2_client_cert->len) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_CLIENT_CERT); return FALSE; } /* If the private key is PKCS#12, check that it matches the client cert */ if (priv->phase2_private_key && crypto_is_pkcs12_data (priv->phase2_private_key)) { if (priv->phase2_private_key->len != priv->phase2_client_cert->len) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_CLIENT_CERT); return FALSE; } if (memcmp (priv->phase2_private_key->data, priv->phase2_client_cert->data, priv->phase2_private_key->len)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_CLIENT_CERT); return FALSE; } } } else { if (!priv->client_cert) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_CLIENT_CERT); return FALSE; } else if (!priv->client_cert->len) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_CLIENT_CERT); return FALSE; } /* If the private key is PKCS#12, check that it matches the client cert */ if (priv->private_key && crypto_is_pkcs12_data (priv->private_key)) { if (priv->private_key->len != priv->client_cert->len) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_CLIENT_CERT); return FALSE; } if (memcmp (priv->private_key->data, priv->client_cert->data, priv->private_key->len)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_CLIENT_CERT); return FALSE; } } } return TRUE; } static gboolean verify_ttls (NMSetting8021x *self, gboolean phase2, GError **error) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); if ( (!priv->identity || !strlen (priv->identity)) && (!priv->anonymous_identity || !strlen (priv->anonymous_identity))) { if (!priv->identity) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_IDENTITY); } else if (!strlen (priv->identity)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_IDENTITY); } else if (!priv->anonymous_identity) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_ANONYMOUS_IDENTITY); } else { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_ANONYMOUS_IDENTITY); } return FALSE; } if ( (!priv->phase2_auth || !strlen (priv->phase2_auth)) && (!priv->phase2_autheap || !strlen (priv->phase2_autheap))) { if (!priv->phase2_auth) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_PHASE2_AUTH); } else if (!strlen (priv->phase2_auth)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_AUTH); } else if (!priv->phase2_autheap) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_PHASE2_AUTHEAP); } else { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_AUTHEAP); } return FALSE; } return TRUE; } static gboolean verify_identity (NMSetting8021x *self, gboolean phase2, GError **error) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); if (!priv->identity) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_IDENTITY); } else if (!strlen (priv->identity)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_IDENTITY); } return TRUE; } /* Implemented below... */ static void need_secrets_phase2 (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2); typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2); typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, gboolean phase2, GError **error); typedef struct { const char *method; EAPMethodNeedSecretsFunc ns_func; EAPMethodValidateFunc v_func; } EAPMethodsTable; static EAPMethodsTable eap_methods_table[] = { { "leap", need_secrets_password, verify_identity }, { "md5", need_secrets_password, verify_identity }, { "pap", need_secrets_password, verify_identity }, { "chap", need_secrets_password, verify_identity }, { "mschap", need_secrets_password, verify_identity }, { "mschapv2", need_secrets_password, verify_identity }, { "fast", need_secrets_password, verify_identity }, { "tls", need_secrets_tls, verify_tls }, { "peap", need_secrets_phase2, verify_ttls }, { "ttls", need_secrets_phase2, verify_ttls }, { "sim", need_secrets_sim, NULL }, { "gtc", NULL, NULL }, // FIXME: implement { "otp", NULL, NULL }, // FIXME: implement { NULL, NULL, NULL } }; static void need_secrets_phase2 (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); char *method = NULL; int i; g_return_if_fail (phase2 == FALSE); /* Check phase2_auth and phase2_autheap */ method = priv->phase2_auth; if (!method && priv->phase2_autheap) method = priv->phase2_autheap; if (!method) { g_warning ("Couldn't find EAP method."); g_assert_not_reached(); return; } /* Ask the configured phase2 method if it needs secrets */ for (i = 0; eap_methods_table[i].method; i++) { if (eap_methods_table[i].ns_func == NULL) continue; if (strcmp (eap_methods_table[i].method, method)) { (*eap_methods_table[i].ns_func) (self, secrets, TRUE); break; } } } static GPtrArray * need_secrets (NMSetting *setting) { NMSetting8021x *self = NM_SETTING_802_1X (setting); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); GSList *iter; GPtrArray *secrets; gboolean eap_method_found = FALSE; secrets = g_ptr_array_sized_new (4); /* Ask each configured EAP method if it needs secrets */ for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next (iter)) { const char *method = (const char *) iter->data; int i; for (i = 0; eap_methods_table[i].method; i++) { if (eap_methods_table[i].ns_func == NULL) continue; if (!strcmp (eap_methods_table[i].method, method)) { (*eap_methods_table[i].ns_func) (self, secrets, FALSE); /* Only break out of the outer loop if this EAP method * needed secrets. */ if (secrets->len > 0) eap_method_found = TRUE; break; } } } if (secrets->len == 0) { g_ptr_array_free (secrets, TRUE); secrets = NULL; } return secrets; } static gboolean verify (NMSetting *setting, GSList *all_settings, GError **error) { NMSetting8021x *self = NM_SETTING_802_1X (setting); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", NULL }; const char *valid_phase1_peapver[] = { "0", "1", NULL }; const char *valid_phase1_peaplabel[] = { "0", "1", NULL }; const char *valid_phase2_auth[] = { "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls", NULL }; const char *valid_phase2_autheap[] = { "md5", "mschapv2", "otp", "gtc", "tls", NULL }; GSList *iter; if (error) g_return_val_if_fail (*error == NULL, FALSE); if (!priv->eap) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, NM_SETTING_802_1X_EAP); return FALSE; } if (!_nm_utils_string_slist_validate (priv->eap, valid_eap)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_EAP); return FALSE; } /* Ask each configured EAP method if its valid */ for (iter = priv->eap; iter; iter = g_slist_next (iter)) { const char *method = (const char *) iter->data; int i; for (i = 0; eap_methods_table[i].method; i++) { if (eap_methods_table[i].v_func == NULL) continue; if (!strcmp (eap_methods_table[i].method, method)) { if (!(*eap_methods_table[i].v_func) (self, FALSE, error)) return FALSE; break; } } } if (priv->phase1_peapver && !_nm_utils_string_in_list (priv->phase1_peapver, valid_phase1_peapver)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE1_PEAPVER); return FALSE; } if (priv->phase1_peaplabel && !_nm_utils_string_in_list (priv->phase1_peaplabel, valid_phase1_peaplabel)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE1_PEAPLABEL); return FALSE; } if (priv->phase1_fast_provisioning && strcmp (priv->phase1_fast_provisioning, "1")) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING); return FALSE; } if (priv->phase2_auth && !_nm_utils_string_in_list (priv->phase2_auth, valid_phase2_auth)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_AUTH); return FALSE; } if (priv->phase2_autheap && !_nm_utils_string_in_list (priv->phase2_autheap, valid_phase2_autheap)) { g_set_error (error, NM_SETTING_802_1X_ERROR, NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, NM_SETTING_802_1X_PHASE2_AUTHEAP); return FALSE; } /* FIXME: finish */ return TRUE; } static void nm_setting_802_1x_init (NMSetting8021x *setting) { g_object_set (setting, NM_SETTING_NAME, NM_SETTING_802_1X_SETTING_NAME, NULL); } static void finalize (GObject *object) { NMSetting8021x *self = NM_SETTING_802_1X (object); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); /* Strings first. g_free() already checks for NULLs so we don't have to */ g_free (priv->identity); g_free (priv->anonymous_identity); g_free (priv->ca_path); g_free (priv->phase1_peapver); g_free (priv->phase1_peaplabel); g_free (priv->phase1_fast_provisioning); g_free (priv->phase2_auth); g_free (priv->phase2_autheap); g_free (priv->phase2_ca_path); g_free (priv->password); nm_utils_slist_free (priv->eap, g_free); if (priv->ca_cert) g_byte_array_free (priv->ca_cert, TRUE); if (priv->client_cert) g_byte_array_free (priv->client_cert, TRUE); if (priv->private_key) g_byte_array_free (priv->private_key, TRUE); g_free (priv->private_key_password); if (priv->phase2_ca_cert) g_byte_array_free (priv->phase2_ca_cert, TRUE); if (priv->phase2_client_cert) g_byte_array_free (priv->phase2_client_cert, TRUE); if (priv->phase2_private_key) g_byte_array_free (priv->phase2_private_key, TRUE); g_free (priv->phase2_private_key_password); G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object); } static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMSetting8021x *setting = NM_SETTING_802_1X (object); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting); switch (prop_id) { case PROP_EAP: nm_utils_slist_free (priv->eap, g_free); priv->eap = g_value_dup_boxed (value); break; case PROP_IDENTITY: g_free (priv->identity); priv->identity = g_value_dup_string (value); break; case PROP_ANONYMOUS_IDENTITY: g_free (priv->anonymous_identity); priv->anonymous_identity = g_value_dup_string (value); break; case PROP_CA_CERT: if (priv->ca_cert) g_byte_array_free (priv->ca_cert, TRUE); priv->ca_cert = g_value_dup_boxed (value); break; case PROP_CA_PATH: g_free (priv->ca_path); priv->ca_path = g_value_dup_string (value); break; case PROP_CLIENT_CERT: if (priv->client_cert) g_byte_array_free (priv->client_cert, TRUE); priv->client_cert = g_value_dup_boxed (value); break; case PROP_PHASE1_PEAPVER: g_free (priv->phase1_peapver); priv->phase1_peapver = g_value_dup_string (value); break; case PROP_PHASE1_PEAPLABEL: g_free (priv->phase1_peaplabel); priv->phase1_peaplabel = g_value_dup_string (value); break; case PROP_PHASE1_FAST_PROVISIONING: g_free (priv->phase1_fast_provisioning); priv->phase1_fast_provisioning = g_value_dup_string (value); break; case PROP_PHASE2_AUTH: g_free (priv->phase2_auth); priv->phase2_auth = g_value_dup_string (value); break; case PROP_PHASE2_AUTHEAP: g_free (priv->phase2_autheap); priv->phase2_autheap = g_value_dup_string (value); break; case PROP_PHASE2_CA_CERT: if (priv->phase2_ca_cert) g_byte_array_free (priv->phase2_ca_cert, TRUE); priv->phase2_ca_cert = g_value_dup_boxed (value); break; case PROP_PHASE2_CA_PATH: g_free (priv->phase2_ca_path); priv->phase2_ca_path = g_value_dup_string (value); break; case PROP_PHASE2_CLIENT_CERT: if (priv->phase2_client_cert) g_byte_array_free (priv->phase2_client_cert, TRUE); priv->phase2_client_cert = g_value_dup_boxed (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; case PROP_PRIVATE_KEY: if (priv->private_key) g_byte_array_free (priv->private_key, TRUE); priv->private_key = g_value_dup_boxed (value); break; case PROP_PRIVATE_KEY_PASSWORD: g_free (priv->private_key_password); priv->private_key_password = g_value_dup_string (value); break; case PROP_PHASE2_PRIVATE_KEY: if (priv->phase2_private_key) g_byte_array_free (priv->phase2_private_key, TRUE); priv->phase2_private_key = g_value_dup_boxed (value); break; case PROP_PHASE2_PRIVATE_KEY_PASSWORD: g_free (priv->phase2_private_key_password); priv->phase2_private_key_password = g_value_dup_string (value); break; case PROP_SYSTEM_CA_CERTS: priv->system_ca_certs = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMSetting8021x *setting = NM_SETTING_802_1X (object); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting); switch (prop_id) { case PROP_EAP: g_value_set_boxed (value, priv->eap); break; case PROP_IDENTITY: g_value_set_string (value, priv->identity); break; case PROP_ANONYMOUS_IDENTITY: g_value_set_string (value, priv->anonymous_identity); break; case PROP_CA_CERT: g_value_set_boxed (value, priv->ca_cert); break; case PROP_CA_PATH: g_value_set_string (value, priv->ca_path); break; case PROP_CLIENT_CERT: g_value_set_boxed (value, priv->client_cert); break; case PROP_PHASE1_PEAPVER: g_value_set_string (value, priv->phase1_peapver); break; case PROP_PHASE1_PEAPLABEL: g_value_set_string (value, priv->phase1_peaplabel); break; case PROP_PHASE1_FAST_PROVISIONING: g_value_set_string (value, priv->phase1_fast_provisioning); break; case PROP_PHASE2_AUTH: g_value_set_string (value, priv->phase2_auth); break; case PROP_PHASE2_AUTHEAP: g_value_set_string (value, priv->phase2_autheap); break; case PROP_PHASE2_CA_CERT: g_value_set_boxed (value, priv->phase2_ca_cert); break; case PROP_PHASE2_CA_PATH: g_value_set_string (value, priv->phase2_ca_path); break; case PROP_PHASE2_CLIENT_CERT: g_value_set_boxed (value, priv->phase2_client_cert); break; case PROP_PASSWORD: g_value_set_string (value, priv->password); break; case PROP_PRIVATE_KEY: g_value_set_boxed (value, priv->private_key); break; case PROP_PRIVATE_KEY_PASSWORD: g_value_set_string (value, priv->private_key_password); break; case PROP_PHASE2_PRIVATE_KEY: g_value_set_boxed (value, priv->phase2_private_key); break; case PROP_PHASE2_PRIVATE_KEY_PASSWORD: g_value_set_string (value, priv->phase2_private_key_password); break; case PROP_SYSTEM_CA_CERTS: g_value_set_boolean (value, priv->system_ca_certs); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) { GObjectClass *object_class = G_OBJECT_CLASS (setting_class); NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); GError *error = NULL; g_type_class_add_private (setting_class, sizeof (NMSetting8021xPrivate)); /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; parent_class->verify = verify; parent_class->need_secrets = need_secrets; /* Properties */ g_object_class_install_property (object_class, PROP_EAP, _nm_param_spec_specialized (NM_SETTING_802_1X_EAP, "EAP", "EAP", DBUS_TYPE_G_LIST_OF_STRING, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_IDENTITY, g_param_spec_string (NM_SETTING_802_1X_IDENTITY, "Identity", "Identity", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_ANONYMOUS_IDENTITY, g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "Anonymous identity", "Anonymous identity", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_CA_CERT, _nm_param_spec_specialized (NM_SETTING_802_1X_CA_CERT, "CA certificate", "CA certificate", DBUS_TYPE_G_UCHAR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_CA_PATH, g_param_spec_string (NM_SETTING_802_1X_CA_PATH, "CA path", "CA path", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_CLIENT_CERT, _nm_param_spec_specialized (NM_SETTING_802_1X_CLIENT_CERT, "Client certificate", "Client certificate", DBUS_TYPE_G_UCHAR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE1_PEAPVER, g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER, "Phase1 PEAPVER", "Phase1 PEAPVER", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE1_PEAPLABEL, g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL, "Phase1 PEAP label", "Phase1 PEAP label", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE1_FAST_PROVISIONING, g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "Phase1 fast provisioning", "Phase1 fast provisioning", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE2_AUTH, g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH, "Phase2 auth", "Phase2 auth", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE2_AUTHEAP, g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP, "Phase2 autheap", "Phase2 autheap", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE2_CA_CERT, _nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CA_CERT, "Phase2 CA certificate", "Phase2 CA certificate", DBUS_TYPE_G_UCHAR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE2_CA_PATH, g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH, "Phase2 auth CA path", "Phase2 auth CA path", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PHASE2_CLIENT_CERT, _nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, "Phase2 client certificate", "Phase2 client certificate", DBUS_TYPE_G_UCHAR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property (object_class, PROP_PASSWORD, g_param_spec_string (NM_SETTING_802_1X_PASSWORD, "Password", "Password", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); g_object_class_install_property (object_class, PROP_PRIVATE_KEY, _nm_param_spec_specialized (NM_SETTING_802_1X_PRIVATE_KEY, "Private key", "Private key", DBUS_TYPE_G_UCHAR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); g_object_class_install_property (object_class, PROP_PRIVATE_KEY_PASSWORD, g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, "Private key password", "Private key password", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); g_object_class_install_property (object_class, PROP_PHASE2_PRIVATE_KEY, _nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, "Phase2 private key", "Phase2 private key", DBUS_TYPE_G_UCHAR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); g_object_class_install_property (object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD, g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, "Phase2 private key password", "Phase2 private key password", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); g_object_class_install_property (object_class, PROP_SYSTEM_CA_CERTS, g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS, "Use system CA certificates", "Use system CA certificates", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); /* Initialize crypto lbrary. */ if (!nm_utils_init (&error)) { g_warning ("Couldn't initilize nm-utils/crypto system: %d %s", error->code, error->message); g_error_free (error); } }