summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-09-04 09:07:00 -0500
committerDan Williams <dcbw@redhat.com>2009-09-04 09:07:00 -0500
commite5ed391f288d7e2a653aa19d58ae0dedbc9a67f7 (patch)
tree12d1c303a81f35b0b8575490f1ad5a0303f43430
parentcecf8f64c77ceb6c6e783f74a05384cacf5de31f (diff)
libnm-util: allow certificate/key paths
Overload the certificate and key properties to allow paths to the certificates and keys using a special prefix for the property data. Add API to libnm-util for easy certificate path handling, and documentation for NMSetting8021x.
-rw-r--r--libnm-util/crypto.c4
-rw-r--r--libnm-util/crypto.h2
-rw-r--r--libnm-util/libnm-util.ver40
-rw-r--r--libnm-util/nm-setting-8021x.c1621
-rw-r--r--libnm-util/nm-setting-8021x.h155
-rw-r--r--libnm-util/tests/test-crypto.c2
-rw-r--r--src/supplicant-manager/nm-supplicant-config.c174
-rw-r--r--system-settings/plugins/ifcfg-rh/common.h18
-rw-r--r--system-settings/plugins/ifcfg-rh/reader.c145
-rw-r--r--system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c204
-rw-r--r--system-settings/plugins/ifcfg-rh/utils.c11
-rw-r--r--system-settings/plugins/ifcfg-rh/utils.h2
-rw-r--r--system-settings/plugins/ifcfg-rh/writer.c209
13 files changed, 2008 insertions, 579 deletions
diff --git a/libnm-util/crypto.c b/libnm-util/crypto.c
index 9f4ccd48a5..cce7144c28 100644
--- a/libnm-util/crypto.c
+++ b/libnm-util/crypto.c
@@ -619,14 +619,14 @@ crypto_is_pkcs12_data (const GByteArray *data)
}
gboolean
-crypto_is_pkcs12_file (const char *file)
+crypto_is_pkcs12_file (const char *file, GError **error)
{
GByteArray *contents;
gboolean success = FALSE;
g_return_val_if_fail (file != NULL, FALSE);
- contents = file_to_g_byte_array (file, TRUE, NULL);
+ contents = file_to_g_byte_array (file, TRUE, error);
if (contents) {
success = crypto_is_pkcs12_data (contents);
g_byte_array_free (contents, TRUE);
diff --git a/libnm-util/crypto.h b/libnm-util/crypto.h
index bb66c7757e..f8c3ffd68c 100644
--- a/libnm-util/crypto.h
+++ b/libnm-util/crypto.h
@@ -83,7 +83,7 @@ GByteArray * crypto_load_and_verify_certificate (const char *file,
NMCryptoFileFormat *out_file_format,
GError **error);
-gboolean crypto_is_pkcs12_file (const char *file);
+gboolean crypto_is_pkcs12_file (const char *file, GError **error);
gboolean crypto_is_pkcs12_data (const GByteArray *data);
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index 6f2976152d..1471e54be9 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -31,11 +31,15 @@ global:
nm_setting_802_1x_error_get_type;
nm_setting_802_1x_error_quark;
nm_setting_802_1x_get_anonymous_identity;
- nm_setting_802_1x_get_ca_cert;
- nm_setting_802_1x_set_ca_cert_from_file;
+ nm_setting_802_1x_get_ca_cert_scheme;
+ nm_setting_802_1x_get_ca_cert_blob;
+ nm_setting_802_1x_get_ca_cert_path;
+ nm_setting_802_1x_set_ca_cert;
nm_setting_802_1x_get_ca_path;
- nm_setting_802_1x_get_client_cert;
- nm_setting_802_1x_set_client_cert_from_file;
+ nm_setting_802_1x_get_client_cert_scheme;
+ nm_setting_802_1x_get_client_cert_blob;
+ nm_setting_802_1x_get_client_cert_path;
+ nm_setting_802_1x_set_client_cert;
nm_setting_802_1x_get_eap_method;
nm_setting_802_1x_get_identity;
nm_setting_802_1x_get_num_eap_methods;
@@ -45,20 +49,28 @@ global:
nm_setting_802_1x_get_phase1_peapver;
nm_setting_802_1x_get_phase2_auth;
nm_setting_802_1x_get_phase2_autheap;
- nm_setting_802_1x_get_phase2_ca_cert;
- nm_setting_802_1x_set_phase2_ca_cert_from_file;
+ nm_setting_802_1x_get_phase2_ca_cert_scheme;
+ nm_setting_802_1x_get_phase2_ca_cert_blob;
+ nm_setting_802_1x_get_phase2_ca_cert_path;
+ nm_setting_802_1x_set_phase2_ca_cert;
nm_setting_802_1x_get_phase2_ca_path;
- nm_setting_802_1x_get_phase2_client_cert;
- nm_setting_802_1x_set_phase2_client_cert_from_file;
- nm_setting_802_1x_get_phase2_private_key;
- nm_setting_802_1x_set_phase2_private_key_from_file;
+ nm_setting_802_1x_get_phase2_client_cert_scheme;
+ nm_setting_802_1x_get_phase2_client_cert_blob;
+ nm_setting_802_1x_get_phase2_client_cert_path;
+ nm_setting_802_1x_set_phase2_client_cert;
+ nm_setting_802_1x_get_phase2_private_key_blob;
+ nm_setting_802_1x_get_phase2_private_key_format;
nm_setting_802_1x_get_phase2_private_key_password;
- nm_setting_802_1x_get_phase2_private_key_type;
+ nm_setting_802_1x_get_phase2_private_key_path;
+ nm_setting_802_1x_get_phase2_private_key_scheme;
+ nm_setting_802_1x_set_phase2_private_key;
nm_setting_802_1x_get_pin;
- nm_setting_802_1x_get_private_key;
- nm_setting_802_1x_set_private_key_from_file;
+ nm_setting_802_1x_get_private_key_blob;
+ nm_setting_802_1x_get_private_key_format;
nm_setting_802_1x_get_private_key_password;
- nm_setting_802_1x_get_private_key_type;
+ nm_setting_802_1x_get_private_key_path;
+ nm_setting_802_1x_get_private_key_scheme;
+ nm_setting_802_1x_set_private_key;
nm_setting_802_1x_get_psk;
nm_setting_802_1x_get_system_ca_certs;
nm_setting_802_1x_get_type;
diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c
index 68efff391f..15c0608040 100644
--- a/libnm-util/nm-setting-8021x.c
+++ b/libnm-util/nm-setting-8021x.c
@@ -33,6 +33,44 @@
#include "crypto.h"
#include "nm-utils-private.h"
+/**
+ * SECTION:nm-setting-802-1x
+ * @short_description: Describes 802.1x-authenticated connection properties
+ * @include: nm-setting-8021x.h
+ *
+ * The #NMSetting8021x object is a #NMSetting subclass that describes
+ * properties necessary for connection to 802.1x-authenticated networks, such as
+ * WPA and WPA2 Enterprise WiFi networks and wired 802.1x networks. 802.1x
+ * connections typically use certificates and/or EAP authentication methods to
+ * securely verify, identify, and authenticate the client to the network itself,
+ * instead of simply relying on a widely shared static key.
+ *
+ * It's a good idea to read up on wpa_supplicant configuration before using this
+ * setting extensively, since most of the options here correspond closely with
+ * the relevant wpa_supplicant configuration options.
+ *
+ * Furthermore, to get a good idea of 802.1x, EAP, TLS, TTLS, etc and their
+ * applications to WiFi and wired networks, you'll want to get copies of the
+ * following books.
+ *
+ * 802.11 Wireless Networks: The Definitive Guide, Second Edition
+ * Author: Matthew Gast
+ * ISBN: 978-0596100520
+ *
+ * Cisco Wireless LAN Security
+ * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky
+ * ISBN: 978-1587051548
+ **/
+
+#define SCHEME_PATH "file://"
+
+/**
+ * nm_setting_802_1x_error_quark:
+ *
+ * Registers an error quark for #NMSetting8021x if necessary.
+ *
+ * Returns: the error quark used for #NMSetting8021x errors.
+ **/
GQuark
nm_setting_802_1x_error_quark (void)
{
@@ -124,12 +162,31 @@ enum {
LAST_PROP
};
+/**
+ * nm_setting_802_1x_new:
+ *
+ * Creates a new #NMSetting8021x object with default values.
+ *
+ * Returns: the new empty #NMSetting8021x object
+ **/
NMSetting *
nm_setting_802_1x_new (void)
{
return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL);
}
+/**
+ * nm_setting_802_1x_get_num_eap_methods:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the number of eap methods allowed for use when connecting to the
+ * network. Generally only one EAP method is used. Use the functions
+ * nm_setting_802_1x_get_eap_method(), nm_setting_802_1x_add_eap_method(),
+ * and nm_setting_802_1x_remove_eap_method() for adding, removing, and retrieving
+ * allowed EAP methods.
+ *
+ * Returns: the number of allowed EAP methods
+ **/
guint32
nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting)
{
@@ -138,6 +195,15 @@ nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting)
return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->eap);
}
+/**
+ * nm_setting_802_1x_get_eap_method:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the EAP method name to return
+ *
+ * Returns the name of the allowed EAP method at index @i.
+ *
+ * Returns: the name of the allowed EAP method at index @i
+ **/
const char *
nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i)
{
@@ -151,6 +217,18 @@ nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i)
return (const char *) g_slist_nth_data (priv->eap, i);
}
+/**
+ * nm_setting_802_1x_add_eap_method:
+ * @setting: the #NMSetting8021x
+ * @eap: the name of the EAP method to allow for this connection
+ *
+ * Adds an allowed EAP method. The setting is not valid until at least one
+ * EAP method has been added. See #NMSetting8021x:eap property for a list of
+ * allowed EAP methods.
+ *
+ * Returns: TRUE if the EAP method was successfully added, FALSE if it was
+ * not a valid method or if it was already allowed.
+ **/
gboolean
nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap)
{
@@ -170,6 +248,13 @@ nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap)
return TRUE;
}
+/**
+ * nm_setting_802_1x_remove_eap_method:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the EAP method to remove
+ *
+ * Removes the allowed EAP method at the specified index.
+ **/
void
nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i)
{
@@ -186,6 +271,12 @@ nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i)
priv->eap = g_slist_delete_link (priv->eap, elt);
}
+/**
+ * nm_setting_802_1x_clear_eap_methods:
+ * @setting: the #NMSetting8021x
+ *
+ * Clears all allowed EAP methods.
+ **/
void
nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting)
{
@@ -198,6 +289,15 @@ nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting)
priv->eap = NULL;
}
+/**
+ * nm_setting_802_1x_get_identity:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the identifier used by some EAP methods (like TLS) to
+ * authenticate the user. Often this is a username or login name.
+ *
+ * Returns: the user identifier
+ **/
const char *
nm_setting_802_1x_get_identity (NMSetting8021x *setting)
{
@@ -206,6 +306,17 @@ nm_setting_802_1x_get_identity (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->identity;
}
+/**
+ * nm_setting_802_1x_get_anonymous_identity:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the anonymous identifier used by some EAP methods (like TTLS) to
+ * authenticate the user in the outer unencrypted "phase 1" authentication. The
+ * inner "phase 2" authentication will use the #NMSetting8021x:identity in
+ * a secure form, if applicable for that EAP method.
+ *
+ * Returns: the anonymous identifier
+ **/
const char *
nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting)
{
@@ -214,121 +325,382 @@ nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->anonymous_identity;
}
+/**
+ * nm_setting_802_1x_get_ca_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the path of the CA certificate directory if previously set. Systems
+ * will often have a directory that contains multiple individual CA certificates
+ * which the supplicant can then add to the verification chain. This may be
+ * used in addition to the #NMSetting8021x:ca-cert property to add more CA
+ * certificates for verifying the network to client.
+ *
+ * Returns: the CA certificate directory path
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_system_ca_certs:
+ * @setting: the #NMSetting8021x
+ *
+ * Sets the #NMSetting8021x:system-ca-certs property. The
+ * #NMSetting8021x:ca-path and #NMSetting8021x:phase2-ca-path
+ * properties are ignored if the #NMSetting8021x:system-ca-certs property is
+ * TRUE, in which case a system-wide CA certificate directory specified at
+ * compile time (using the --system-ca-path configure option) is used in place
+ * of these properties.
+ *
+ * Returns: TRUE if a system CA certificate path should be used, FALSE if not
+ **/
+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;
+}
+
+static NMSetting8021xCKScheme
+get_cert_scheme (GByteArray *array)
+{
+ if (!array || !array->len)
+ return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+
+ if ( (array->len > strlen (SCHEME_PATH))
+ && !memcmp (array->data, SCHEME_PATH, strlen (SCHEME_PATH)))
+ return NM_SETTING_802_1X_CK_SCHEME_PATH;
+
+ return NM_SETTING_802_1X_CK_SCHEME_BLOB;
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the CA certificate. If the returned scheme
+ * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_ca_cert_blob();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path().
+ *
+ * Returns: scheme used to store the CA certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+ return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the CA certificate blob if the CA certificate is stored using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use a
+ * CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: the CA certificate data
+ **/
const GByteArray *
-nm_setting_802_1x_get_ca_cert (NMSetting8021x *setting)
+nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+ scheme = nm_setting_802_1x_get_ca_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert;
}
+/**
+ * nm_setting_802_1x_get_ca_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the CA certificate path if the CA certificate is stored using the
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use a
+ * CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: path to the CA certificate file
+ **/
const char *
-nm_setting_802_1x_get_ca_path (NMSetting8021x *setting)
+nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
- return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_path;
+ scheme = nm_setting_802_1x_get_ca_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+ return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert->data + strlen (SCHEME_PATH));
}
+/**
+ * nm_setting_802_1x_set_ca_cert:
+ * @setting: the #NMSetting8021x
+ * @filename: path of the CA certificate file (PEM or DER format). Filename
+ * must be UTF-8 encoded; use g_filename_to_utf8() to convert if needed. Pass
+ * NULL to clear the CA certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:ca-cert property
+ * with the raw certificate data if using the %NM_SETTING_802_1X_CK_SCHEME_BLOB
+ * scheme, or with the path to the certificate file if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful
+ **/
gboolean
-nm_setting_802_1x_set_ca_cert_from_file (NMSetting8021x *self,
- const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err)
+nm_setting_802_1x_set_ca_cert (NMSetting8021x *self,
+ const char *filename,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ GByteArray *data;
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);
+
+ if (filename) {
+ g_return_val_if_fail (g_utf8_validate (filename, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ FALSE);
+ }
+
+ if (out_format)
+ g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_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);
+ /* Clear out any previous ca_cert blob */
if (priv->ca_cert) {
+ g_byte_array_free (priv->ca_cert, TRUE);
+ priv->ca_cert = NULL;
+ }
+
+ if (!filename)
+ return TRUE;
+
+ data = crypto_load_and_verify_certificate (filename, &format, error);
+ if (data) {
/* 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;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
break;
default:
- g_byte_array_free (priv->ca_cert, TRUE);
- priv->ca_cert = NULL;
- g_set_error (err,
+ g_byte_array_free (data, TRUE);
+ data = NULL;
+ g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CA_CERT);
break;
- }
+ }
+
+ if (data) {
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ priv->ca_cert = data;
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ /* Add the path scheme tag to the front, then the fielname */
+ priv->ca_cert = g_byte_array_sized_new (strlen (filename) + strlen (SCHEME_PATH) + 1);
+ g_byte_array_append (priv->ca_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+ g_byte_array_append (priv->ca_cert, (const guint8 *) filename, strlen (filename));
+ g_byte_array_append (priv->ca_cert, (const guint8 *) "\0", 1);
+ } else
+ g_assert_not_reached ();
+ }
}
return priv->ca_cert != NULL;
}
-gboolean
-nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting)
+/**
+ * nm_setting_802_1x_get_client_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the client certificate. If the returned scheme
+ * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_client_cert_blob();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the client certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting)
{
- g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
- return NM_SETTING_802_1X_GET_PRIVATE (setting)->system_ca_certs;
+ return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert);
}
+/**
+ * nm_setting_802_1x_get_client_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: the client certificate data
+ **/
const GByteArray *
-nm_setting_802_1x_get_client_cert (NMSetting8021x *setting)
+nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+ scheme = nm_setting_802_1x_get_client_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
return NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert;
}
+/**
+ * nm_setting_802_1x_get_client_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the client certificate file
+ **/
+const char *
+nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting)
+{
+ NMSetting8021xCKScheme scheme;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ scheme = nm_setting_802_1x_get_client_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+ return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert->data + strlen (SCHEME_PATH));
+}
+
+/**
+ * nm_setting_802_1x_set_client_cert:
+ * @setting: the #NMSetting8021x
+ * @filename: path of the client certificate file (PEM, DER, or PKCS#12 format).
+ * Filename must be UTF-8 encoded; use g_filename_to_utf8() to convert if
+ * needed. Pass NULL to clear the client certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:client-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful
+ **/
gboolean
-nm_setting_802_1x_set_client_cert_from_file (NMSetting8021x *self,
- const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err)
+nm_setting_802_1x_set_client_cert (NMSetting8021x *self,
+ const char *filename,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ GByteArray *data;
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);
+
+ if (filename) {
+ g_return_val_if_fail (g_utf8_validate (filename, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ FALSE);
+ }
+
+ if (out_format)
+ g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_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);
+ /* Clear out any previous ca_cert blob */
if (priv->client_cert) {
+ g_byte_array_free (priv->client_cert, TRUE);
+ priv->client_cert = NULL;
+ }
+
+ if (!filename)
+ return TRUE;
+
+ data = crypto_load_and_verify_certificate (filename, &format, error);
+ if (data) {
+ /* 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;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
break;
case NM_CRYPTO_FILE_FORMAT_PKCS12:
- if (out_ck_type)
- *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
break;
default:
- g_byte_array_free (priv->client_cert, TRUE);
- priv->client_cert = NULL;
- g_set_error (err,
+ g_byte_array_free (data, TRUE);
+ data = NULL;
+ g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CLIENT_CERT);
break;
- }
+ }
+
+ if (data) {
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ priv->client_cert = data;
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ /* Add the path scheme tag to the front, then the fielname */
+ priv->client_cert = g_byte_array_sized_new (strlen (filename) + strlen (SCHEME_PATH) + 1);
+ g_byte_array_append (priv->client_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+ g_byte_array_append (priv->client_cert, (const guint8 *) filename, strlen (filename));
+ g_byte_array_append (priv->client_cert, (const guint8 *) "\0", 1);
+ } else
+ g_assert_not_reached ();
+ }
}
return priv->client_cert != NULL;
}
+/**
+ * nm_setting_802_1x_get_phase1_peapver:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 1" PEAP version to be used when authenticating with
+ * EAP-PEAP as contained in the #NMSetting8021x:phase1-peapver property. Valid
+ * values are NULL (unset), "0" (PEAP version 0), and "1" (PEAP version 1).
+ **/
const char *
nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting)
{
@@ -337,6 +709,16 @@ nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peapver;
}
+/**
+ * nm_setting_802_1x_get_phase1_peaplabel:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: whether the "phase 1" PEAP label is new-style or old-style, to be
+ * used when authenticating with EAP-PEAP, as contained in the
+ * #NMSetting8021x:phase1-peaplabel property. Valid values are NULL (unset),
+ * "0" (use old-style label), and "1" (use new-style label). See the
+ * wpa_supplicant documentation for more details.
+ **/
const char *
nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting)
{
@@ -345,6 +727,14 @@ nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peaplabel;
}
+/**
+ * nm_setting_802_1x_get_phase1_fast_provisioning:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: whether "phase 1" PEAP fast provisioning should be used, as specified
+ * by the #NMSetting8021x:phase1-fast-provisioning property. See the
+ * wpa_supplicant documentation for more details.
+ **/
const char *
nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting)
{
@@ -353,6 +743,13 @@ nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_fast_provisioning;
}
+/**
+ * nm_setting_802_1x_get_phase2_auth:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 2" non-EAP (ex MD5) allowed authentication method as
+ * specified by the #NMSetting8021x:phase2-auth property.
+ **/
const char *
nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting)
{
@@ -361,6 +758,13 @@ nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_auth;
}
+/**
+ * nm_setting_802_1x_get_phase2_autheap:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 2" EAP-based (ex TLS) allowed authentication method as
+ * specified by the #NMSetting8021x:phase2-autheap property.
+ **/
const char *
nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting)
{
@@ -369,114 +773,350 @@ nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_autheap;
}
+/**
+ * nm_setting_802_1x_get_phase2_ca_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the path of the "phase 2" CA certificate directory if previously set.
+ * Systems will often have a directory that contains multiple individual CA
+ * certificates which the supplicant can then add to the verification chain.
+ * This may be used in addition to the #NMSetting8021x:phase2-ca-cert property
+ * to add more CA certificates for verifying the network to client.
+ *
+ * Returns: the "phase 2" CA certificate directory path
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" CA certificate. If the
+ * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_ca_cert_blob(); if %NM_SETTING_802_1X_CK_SCHEME_PATH,
+ * use nm_setting_802_1x_get_ca_cert_path().
+ *
+ * Returns: scheme used to store the "phase 2" CA certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+ return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" CA certificate blob if the CA certificate is stored
+ * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use
+ * a CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: the "phase 2" CA certificate data
+ **/
const GByteArray *
-nm_setting_802_1x_get_phase2_ca_cert (NMSetting8021x *setting)
+nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+ scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert;
}
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" CA certificate path if the CA certificate is stored
+ * using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use
+ * a CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: path to the "phase 2" CA certificate file
+ **/
const char *
-nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting)
+nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
- return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_path;
+ scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+ return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert->data + strlen (SCHEME_PATH));
}
+/**
+ * nm_setting_802_1x_set_phase2_ca_cert:
+ * @setting: the #NMSetting8021x
+ * @filename: path of the "phase 2" CA certificate file (PEM or DER format).
+ * Filename must be UTF-8 encoded; use g_filename_to_utf8() to convert if
+ * needed. Pass NULL to clear the "phase 2" CA certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:phase2-ca-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful
+ **/
gboolean
-nm_setting_802_1x_set_phase2_ca_cert_from_file (NMSetting8021x *self,
- const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err)
+nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *self,
+ const char *filename,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ GByteArray *data;
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);
+
+ if (filename) {
+ g_return_val_if_fail (g_utf8_validate (filename, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ FALSE);
+ }
+
+ if (out_format)
+ g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_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);
+ /* Clear out any previous ca_cert blob */
if (priv->phase2_ca_cert) {
- /* wpa_supplicant can only use X509 CA certs */
+ g_byte_array_free (priv->phase2_ca_cert, TRUE);
+ priv->phase2_ca_cert = NULL;
+ }
+
+ if (!filename)
+ return TRUE;
+
+ data = crypto_load_and_verify_certificate (filename, &format, error);
+ if (data) {
+ /* 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;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
break;
default:
- g_byte_array_free (priv->phase2_ca_cert, TRUE);
- priv->phase2_ca_cert = NULL;
- g_set_error (err,
+ g_byte_array_free (data, TRUE);
+ data = NULL;
+ g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_CA_CERT);
break;
- }
+ }
+
+ if (data) {
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ priv->phase2_ca_cert = data;
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ /* Add the path scheme tag to the front, then the fielname */
+ priv->phase2_ca_cert = g_byte_array_sized_new (strlen (filename) + strlen (SCHEME_PATH) + 1);
+ g_byte_array_append (priv->phase2_ca_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+ g_byte_array_append (priv->phase2_ca_cert, (const guint8 *) filename, strlen (filename));
+ g_byte_array_append (priv->phase2_ca_cert, (const guint8 *) "\0", 1);
+ } else
+ g_assert_not_reached ();
+ }
}
return priv->phase2_ca_cert != NULL;
}
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" client certificate. If the
+ * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the "phase 2" client certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+ return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: the "phase 2" client certificate data
+ **/
const GByteArray *
-nm_setting_802_1x_get_phase2_client_cert (NMSetting8021x *setting)
+nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+ scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert;
}
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the "phase 2" client certificate file
+ **/
+const char *
+nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting)
+{
+ NMSetting8021xCKScheme scheme;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+ return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert->data + strlen (SCHEME_PATH));
+}
+
+/**
+ * nm_setting_802_1x_set_phase2_client_cert:
+ * @setting: the #NMSetting8021x
+ * @filename: path of the client certificate file (PEM, DER, or PKCS#12 format).
+ * Filename must be UTF-8 encoded; use g_filename_to_utf8() to convert if
+ * needed. Pass NULL to clear the client certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:phase2-client-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful
+ **/
gboolean
-nm_setting_802_1x_set_phase2_client_cert_from_file (NMSetting8021x *self,
- const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err)
+nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self,
+ const char *filename,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ GByteArray *data;
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);
+
+ if (filename) {
+ g_return_val_if_fail (g_utf8_validate (filename, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ FALSE);
+ }
+
+ if (out_format)
+ g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_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);
+ /* Clear out any previous ca_cert blob */
if (priv->phase2_client_cert) {
- /* Only X509 client certs should be used; not pkcs#12 */
+ g_byte_array_free (priv->phase2_client_cert, TRUE);
+ priv->phase2_client_cert = NULL;
+ }
+
+ if (!filename)
+ return TRUE;
+
+ data = crypto_load_and_verify_certificate (filename, &format, error);
+ if (data) {
+ /* 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;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
break;
case NM_CRYPTO_FILE_FORMAT_PKCS12:
- if (out_ck_type)
- *out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
break;
default:
- g_byte_array_free (priv->phase2_client_cert, TRUE);
- priv->phase2_client_cert = NULL;
- g_set_error (err,
+ g_byte_array_free (data, TRUE);
+ data = NULL;
+ g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
- NM_SETTING_802_1X_CLIENT_CERT);
+ NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
break;
- }
+ }
+
+ if (data) {
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ priv->phase2_client_cert = data;
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ /* Add the path scheme tag to the front, then the fielname */
+ priv->phase2_client_cert = g_byte_array_sized_new (strlen (filename) + strlen (SCHEME_PATH) + 1);
+ g_byte_array_append (priv->phase2_client_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+ g_byte_array_append (priv->phase2_client_cert, (const guint8 *) filename, strlen (filename));
+ g_byte_array_append (priv->phase2_client_cert, (const guint8 *) "\0", 1);
+ } else
+ g_assert_not_reached ();
+ }
}
return priv->phase2_client_cert != NULL;
}
+/**
+ * nm_setting_802_1x_get_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the password used by the authentication method, if any, as specified
+ * by the #NMSetting8021x:password property
+ **/
const char *
nm_setting_802_1x_get_password (NMSetting8021x *setting)
{
@@ -485,6 +1125,13 @@ nm_setting_802_1x_get_password (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->password;
}
+/**
+ * nm_setting_802_1x_get_pin:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the PIN used by the authentication method, if any, as specified
+ * by the #NMSetting8021x:pin property
+ **/
const char *
nm_setting_802_1x_get_pin (NMSetting8021x *setting)
{
@@ -493,6 +1140,13 @@ nm_setting_802_1x_get_pin (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->pin;
}
+/**
+ * nm_setting_802_1x_get_psk:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the Pre-Shared-Key used by the authentication method, if any, as
+ * specified by the #NMSetting8021x:psk property
+ **/
const char *
nm_setting_802_1x_get_psk (NMSetting8021x *setting)
{
@@ -501,192 +1155,518 @@ nm_setting_802_1x_get_psk (NMSetting8021x *setting)
return NM_SETTING_802_1X_GET_PRIVATE (setting)->psk;
}
+/**
+ * nm_setting_802_1x_get_private_key_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the private key. If the returned scheme is
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the private key (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+ return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: the private key data
+ **/
const GByteArray *
-nm_setting_802_1x_get_private_key (NMSetting8021x *setting)
+nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+ scheme = nm_setting_802_1x_get_private_key_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key;
}
+/**
+ * nm_setting_802_1x_get_private_key_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the private key file
+ **/
const char *
-nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting)
+nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
- return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key_password;
+ scheme = nm_setting_802_1x_get_private_key_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+ return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key->data + strlen (SCHEME_PATH));
}
+/**
+ * nm_setting_802_1x_set_private_key:
+ * @setting: the #NMSetting8021x
+ * @filename: path of the private key file (PEM, DER, or PKCS#12 format).
+ * Filename must be UTF-8 encoded; use g_filename_to_utf8() to convert if
+ * needed. Pass NULL to clear the private key.
+ * @scheme: desired storage scheme for the private key
+ * @out_format: on successful return, the type of the private key added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a private key from disk and sets the #NMSetting8021x:private-key
+ * property with the raw private key data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the private key
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful
+ **/
gboolean
-nm_setting_802_1x_set_private_key_from_file (NMSetting8021x *self,
- const char *filename,
- const char *password,
- NMSetting8021xCKType *out_ck_type,
- GError **err)
+nm_setting_802_1x_set_private_key (NMSetting8021x *self,
+ const char *filename,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
{
NMSetting8021xPrivate *priv;
- NMCryptoKeyType ignore = NM_CRYPTO_KEY_TYPE_UNKNOWN;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ GByteArray *data;
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);
+
+ if (filename) {
+ g_return_val_if_fail (g_utf8_validate (filename, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ FALSE);
+ }
+
+ if (out_format)
+ g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+
+ /* Clear out any previous private key blob */
if (priv->private_key) {
- /* Try not to leave the decrypted private key around in memory */
+ /* Try not to leave the private key around in memory */
memset (priv->private_key, 0, priv->private_key->len);
g_byte_array_free (priv->private_key, TRUE);
+ priv->private_key = NULL;
}
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) {
+ if (!filename)
+ return TRUE;
+
+ data = crypto_load_and_verify_certificate (filename, &format, error);
+ if (data) {
+ /* wpa_supplicant can only use raw x509 CA certs */
switch (format) {
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
- if (out_ck_type)
- *out_ck_type = NM_SETTING_802_1X_CK_TYPE_RAW_KEY;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+ break;
+ case NM_CRYPTO_FILE_FORMAT_X509:
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
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);
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
break;
default:
- g_assert_not_reached ();
+ g_byte_array_free (data, TRUE);
+ data = NULL;
+ g_set_error (error,
+ NM_SETTING_802_1X_ERROR,
+ NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+ NM_SETTING_802_1X_PRIVATE_KEY);
break;
- }
+ }
+
+ if (data) {
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ priv->private_key = data;
+
+ /* Always update the private key for blob + pkcs12 since the
+ * pkcs12 files are encrypted
+ */
+ if (format == NM_CRYPTO_FILE_FORMAT_PKCS12)
+ priv->private_key_password = g_strdup (password);
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ /* Add the path scheme tag to the front, then the fielname */
+ priv->private_key = g_byte_array_sized_new (strlen (filename) + strlen (SCHEME_PATH) + 1);
+ g_byte_array_append (priv->private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+ g_byte_array_append (priv->private_key, (const guint8 *) filename, strlen (filename));
+ g_byte_array_append (priv->private_key, (const guint8 *) "\0", 1);
+
+ /* Always update the private key with paths since the key the
+ * cert refers to is encrypted.
+ */
+ priv->private_key_password = g_strdup (password);
+ } else
+ g_assert_not_reached ();
+
+ /* As required by NM and wpa_supplicant, set the client-cert
+ * property to the same PKCS#12 data.
+ */
+ if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
+ 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);
+ }
+ }
} 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;
+ if (out_format && crypto_is_pkcs12_file (filename, NULL))
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
}
return priv->private_key != NULL;
}
-NMSetting8021xCKType
-nm_setting_802_1x_get_private_key_type (NMSetting8021x *setting)
+/**
+ * nm_setting_802_1x_get_private_key_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the private key password used to decrypt the private key if
+ * previously set with nm_setting_802_1x_set_private_key_from_file(),
+ * nm_setting_802_1x_set_private_key_path(), or the
+ * #NMSetting8021x:private-key-password property.
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_format:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the data format of the private key data stored in the
+ * #NMSetting8021x:private-key property
+ **/
+NMSetting8021xCKFormat
+nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting)
{
NMSetting8021xPrivate *priv;
+ const char *path;
+ GError *error = NULL;
- g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_TYPE_UNKNOWN);
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
if (!priv->private_key)
- return NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
+ return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+
+ switch (nm_setting_802_1x_get_private_key_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ if (crypto_is_pkcs12_data (priv->private_key))
+ return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+ return NM_SETTING_802_1X_CK_FORMAT_X509;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_private_key_path (setting);
+ if (crypto_is_pkcs12_file (path, &error))
+ return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+ if (error) {
+ /* Couldn't read the file or something */
+ g_error_free (error);
+ return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ }
+ return NM_SETTING_802_1X_CK_FORMAT_X509;
+ default:
+ break;
+ }
+
+ return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the private key password used to decrypt the private key if
+ * previously set with nm_setting_802_1x_set_phase2_private_key_from_file(),
+ * nm_setting_802_1x_set_phase2_private_key_path(), or the
+ * #NMSetting8021x:phase2-private-key-password property.
+ **/
+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;
+}
- if (crypto_is_pkcs12_data (priv->private_key))
- return NM_SETTING_802_1X_CK_TYPE_PKCS12;
+/**
+ * nm_setting_802_1x_get_phase2_private_key_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" private key. If the returned
+ * scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the "phase 2" private key (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
- return NM_SETTING_802_1X_CK_TYPE_X509;
+ return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key);
}
+/**
+ * nm_setting_802_1x_get_phase2_private_key_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: the "phase 2" private key data
+ **/
const GByteArray *
-nm_setting_802_1x_get_phase2_private_key (NMSetting8021x *setting)
+nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+ scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key;
}
+/**
+ * nm_setting_802_1x_get_phase2_private_key_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the "phase 2" private key file
+ **/
const char *
-nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting)
+nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting)
{
+ NMSetting8021xCKScheme scheme;
+
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
- return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key_password;
+ scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting);
+ g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+ return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key->data + strlen (SCHEME_PATH));
}
+/**
+ * nm_setting_802_1x_set_phase2_private_key:
+ * @setting: the #NMSetting8021x
+ * @filename: path of the private key file (PEM, DER, or PKCS#12 format).
+ * Filename must be UTF-8 encoded; use g_filename_to_utf8() to convert if
+ * needed. Pass NULL to clear the private key.
+ * @scheme: desired storage scheme for the private key
+ * @out_format: on successful return, the type of the private key added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a "phase 2" private key from disk and sets the
+ * #NMSetting8021x:phase2-private-key property with the raw private key data if
+ * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the
+ * private key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful
+ **/
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)
+nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
+ const char *filename,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
{
NMSetting8021xPrivate *priv;
- NMCryptoKeyType ignore = NM_CRYPTO_KEY_TYPE_UNKNOWN;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ GByteArray *data;
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);
+
+ if (filename) {
+ g_return_val_if_fail (g_utf8_validate (filename, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ FALSE);
+ }
+
+ if (out_format)
+ g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+
+ /* Clear out any previous private key blob */
if (priv->phase2_private_key) {
- /* Try not to leave the decrypted private key around in memory */
+ /* Try not to leave the 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);
+ priv->phase2_private_key = NULL;
}
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) {
+ if (!filename)
+ return TRUE;
+
+ data = crypto_load_and_verify_certificate (filename, &format, error);
+ if (data) {
+ /* wpa_supplicant can only use raw x509 CA certs */
switch (format) {
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
- if (out_ck_type)
- *out_ck_type = NM_SETTING_802_1X_CK_TYPE_RAW_KEY;
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+ break;
+ case NM_CRYPTO_FILE_FORMAT_X509:
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
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);
+ if (out_format)
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
break;
default:
- g_assert_not_reached ();
+ g_byte_array_free (data, TRUE);
+ data = NULL;
+ g_set_error (error,
+ NM_SETTING_802_1X_ERROR,
+ NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
break;
- }
+ }
+
+ if (data) {
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ priv->phase2_private_key = data;
+
+ /* Always update the private key for blob + pkcs12 since the
+ * pkcs12 files are encrypted
+ */
+ if (format == NM_CRYPTO_FILE_FORMAT_PKCS12)
+ priv->phase2_private_key_password = g_strdup (password);
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ /* Add the path scheme tag to the front, then the fielname */
+ priv->phase2_private_key = g_byte_array_sized_new (strlen (filename) + strlen (SCHEME_PATH) + 1);
+ g_byte_array_append (priv->phase2_private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+ g_byte_array_append (priv->phase2_private_key, (const guint8 *) filename, strlen (filename));
+ g_byte_array_append (priv->phase2_private_key, (const guint8 *) "\0", 1);
+
+ /* Always update the private key with paths since the key the
+ * cert refers to is encrypted.
+ */
+ priv->phase2_private_key_password = g_strdup (password);
+ } else
+ g_assert_not_reached ();
+
+ /* As required by NM and wpa_supplicant, set the client-cert
+ * property to the same PKCS#12 data.
+ */
+ if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
+ 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);
+ }
+ }
} 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;
+ if (out_format && crypto_is_pkcs12_file (filename, NULL))
+ *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
}
return priv->phase2_private_key != NULL;
}
-NMSetting8021xCKType
-nm_setting_802_1x_get_phase2_private_key_type (NMSetting8021x *setting)
+/**
+ * nm_setting_802_1x_get_phase2_private_key_format:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the data format of the "phase 2" private key data stored in the
+ * #NMSetting8021x:phase2-private-key property
+ **/
+NMSetting8021xCKFormat
+nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting)
{
NMSetting8021xPrivate *priv;
+ const char *path;
+ GError *error = NULL;
- g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_TYPE_UNKNOWN);
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_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_FORMAT_UNKNOWN;
+
+ switch (nm_setting_802_1x_get_phase2_private_key_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ if (crypto_is_pkcs12_data (priv->phase2_private_key))
+ return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+ return NM_SETTING_802_1X_CK_FORMAT_X509;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_phase2_private_key_path (setting);
+ if (crypto_is_pkcs12_file (path, &error))
+ return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+ if (error) {
+ /* Couldn't read the file or something */
+ g_error_free (error);
+ return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ }
+ return NM_SETTING_802_1X_CK_FORMAT_X509;
+ default:
+ break;
+ }
- return NM_SETTING_802_1X_CK_TYPE_X509;
+ return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
}
static void
@@ -1027,6 +2007,36 @@ need_secrets (NMSetting *setting)
}
static gboolean
+verify_cert (GByteArray *array, const char *prop_name, GError **error)
+{
+ if (!array)
+ return TRUE;
+
+ switch (get_cert_scheme (array)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ return TRUE;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ /* For path-based schemes, verify that the path is zero-terminated */
+ if (array->data[array->len - 1] == '\0') {
+ /* And ensure it's UTF-8 valid too so we can pass it through
+ * D-Bus and stuff like that.
+ */
+ if (g_utf8_validate ((const char *) (array->data + strlen (SCHEME_PATH)), -1, NULL))
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ g_set_error (error,
+ NM_SETTING_802_1X_ERROR,
+ NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+ prop_name);
+ return FALSE;
+}
+
+static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
NMSetting8021x *self = NM_SETTING_802_1X (setting);
@@ -1034,6 +2044,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
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_phase1_fast_pac[] = { "0", "1", "2", "3", 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;
@@ -1089,7 +2100,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
return FALSE;
}
- if (priv->phase1_fast_provisioning && strcmp (priv->phase1_fast_provisioning, "1")) {
+ if (priv->phase1_fast_provisioning && !_nm_utils_string_in_list (priv->phase1_fast_provisioning, valid_phase1_fast_pac)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
@@ -1113,6 +2124,21 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
return FALSE;
}
+ if (!verify_cert (priv->ca_cert, NM_SETTING_802_1X_CA_CERT, error))
+ return FALSE;
+ if (!verify_cert (priv->phase2_ca_cert, NM_SETTING_802_1X_PHASE2_CA_CERT, error))
+ return FALSE;
+
+ if (!verify_cert (priv->client_cert, NM_SETTING_802_1X_CLIENT_CERT, error))
+ return FALSE;
+ if (!verify_cert (priv->phase2_client_cert, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, error))
+ return FALSE;
+
+ if (!verify_cert (priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, error))
+ return FALSE;
+ if (!verify_cert (priv->phase2_private_key, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, error))
+ return FALSE;
+
/* FIXME: finish */
return TRUE;
@@ -1163,12 +2189,31 @@ finalize (GObject *object)
G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object);
}
+static GByteArray *
+set_cert_prop_helper (const GValue *value, const char *prop_name, GError **error)
+{
+ gboolean valid;
+ GByteArray *data = NULL;
+
+ data = g_value_dup_boxed (value);
+ /* Verify the new data */
+ if (data) {
+ valid = verify_cert (data, prop_name, error);
+ if (!valid) {
+ g_byte_array_free (data, TRUE);
+ data = NULL;
+ }
+ }
+ return data;
+}
+
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);
+ GError *error = NULL;
switch (prop_id) {
case PROP_EAP:
@@ -1184,18 +2229,32 @@ set_property (GObject *object, guint prop_id,
priv->anonymous_identity = g_value_dup_string (value);
break;
case PROP_CA_CERT:
- if (priv->ca_cert)
+ if (priv->ca_cert) {
g_byte_array_free (priv->ca_cert, TRUE);
- priv->ca_cert = g_value_dup_boxed (value);
+ priv->ca_cert = NULL;
+ }
+ priv->ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CA_CERT, &error);
+ if (error) {
+ g_warning ("Error setting certificate (invalid data): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
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)
+ if (priv->client_cert) {
g_byte_array_free (priv->client_cert, TRUE);
- priv->client_cert = g_value_dup_boxed (value);
+ priv->client_cert = NULL;
+ }
+ priv->client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CLIENT_CERT, &error);
+ if (error) {
+ g_warning ("Error setting certificate (invalid data): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
break;
case PROP_PHASE1_PEAPVER:
g_free (priv->phase1_peapver);
@@ -1218,36 +2277,64 @@ set_property (GObject *object, guint prop_id,
priv->phase2_autheap = g_value_dup_string (value);
break;
case PROP_PHASE2_CA_CERT:
- if (priv->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);
+ priv->phase2_ca_cert = NULL;
+ }
+ priv->phase2_ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CA_CERT, &error);
+ if (error) {
+ g_warning ("Error setting certificate (invalid data): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
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)
+ if (priv->phase2_client_cert) {
g_byte_array_free (priv->phase2_client_cert, TRUE);
- priv->phase2_client_cert = g_value_dup_boxed (value);
+ priv->phase2_client_cert = NULL;
+ }
+ priv->phase2_client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &error);
+ if (error) {
+ g_warning ("Error setting certificate (invalid data): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
break;
case PROP_PASSWORD:
g_free (priv->password);
priv->password = g_value_dup_string (value);
break;
case PROP_PRIVATE_KEY:
- if (priv->private_key)
+ if (priv->private_key) {
g_byte_array_free (priv->private_key, TRUE);
- priv->private_key = g_value_dup_boxed (value);
+ priv->private_key = NULL;
+ }
+ priv->private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PRIVATE_KEY, &error);
+ if (error) {
+ g_warning ("Error setting private key (invalid data): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
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)
+ if (priv->phase2_private_key) {
g_byte_array_free (priv->phase2_private_key, TRUE);
- priv->phase2_private_key = g_value_dup_boxed (value);
+ priv->phase2_private_key = NULL;
+ }
+ priv->phase2_private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &error);
+ if (error) {
+ g_warning ("Error setting private key (invalid data): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
break;
case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
g_free (priv->phase2_private_key_password);
@@ -1354,6 +2441,16 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
parent_class->need_secrets = need_secrets;
/* Properties */
+
+ /**
+ * NMSetting8021x:eap:
+ *
+ * The allowed EAP method to be used when authenticating to the network with
+ * 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", and
+ * "fast". Each method requires different configuration using the
+ * properties of this object; refer to wpa_supplicant documentation for the
+ * allowed combinations.
+ **/
g_object_class_install_property
(object_class, PROP_EAP,
_nm_param_spec_specialized (NM_SETTING_802_1X_EAP,
@@ -1362,6 +2459,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
DBUS_TYPE_G_LIST_OF_STRING,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:identity:
+ *
+ * Identity string for EAP authentication methods. Often the user's
+ * user or login name.
+ **/
g_object_class_install_property
(object_class, PROP_IDENTITY,
g_param_spec_string (NM_SETTING_802_1X_IDENTITY,
@@ -1370,6 +2473,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:anonymous-identity:
+ *
+ * Anonymous identity string for EAP authentication methods. Used as the
+ * unencrypted identity with EAP types that support different tunelled
+ * identity like EAP-TTLS.
+ **/
g_object_class_install_property
(object_class, PROP_ANONYMOUS_IDENTITY,
g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
@@ -1378,6 +2488,16 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:ca-cert:
+ *
+ * Raw X.509 CA certificate data if used by the EAP method specified in the
+ * #NMSetting8021x:eap property. Can be unset even if the EAP method
+ * supports CA certificates, but this allows man-in-the-middle attacks and
+ * is NOT recommended. This property is cleared when the
+ * #NMSetting8021x:ca-cert-path property is set since the two are mutually
+ * exclusive.
+ **/
g_object_class_install_property
(object_class, PROP_CA_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_CA_CERT,
@@ -1386,6 +2506,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:ca-path:
+ *
+ * Path to a directory containing PEM or DER formatted certificates to be
+ * added to the verification chain in addition to the certificate specified
+ * in either of the #NMSetting8021x:ca-cert or #NMSetting8021x:ca-cert-path
+ * properties.
+ **/
g_object_class_install_property
(object_class, PROP_CA_PATH,
g_param_spec_string (NM_SETTING_802_1X_CA_PATH,
@@ -1394,6 +2522,15 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:client-cert:
+ *
+ * Raw X.509 client certificate data if used by the EAP method specified in
+ * the #NMSetting8021x:eap property. Currently only EAP-TLS supports client
+ * certificates. This property is cleared when the
+ * #NMSetting8021x:client-cert-path property is set since the two are mutually
+ * exclusive.
+ **/
g_object_class_install_property
(object_class, PROP_CLIENT_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_CLIENT_CERT,
@@ -1402,6 +2539,16 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase1-peapver:
+ *
+ * Forces which PEAP version is used when PEAP is set as the EAP method in
+ * the #NMSetting8021x:eap property. When unset, the version reported by
+ * the server will be used. Sometimes when using older RADIUS servers, it
+ * is necessary to force the client to use a particular PEAP version. To do
+ * so, this property may be set to "0" or "1" to force that specific PEAP
+ * version.
+ **/
g_object_class_install_property
(object_class, PROP_PHASE1_PEAPVER,
g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER,
@@ -1410,6 +2557,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase1-peaplabel:
+ *
+ * Forces use of the new PEAP label during key derivation. Some RADIUS
+ * servers may require forcing the new PEAP label to interoperate with
+ * PEAPv1. Set to "1" to force use of the new PEAP label. See the
+ * wpa_supplicant documentation for more details.
+ **/
g_object_class_install_property
(object_class, PROP_PHASE1_PEAPLABEL,
g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL,
@@ -1418,6 +2573,15 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase1-fast-provisioning:
+ *
+ * Enables or disables in-line provisioning of EAP-FAST credentials when
+ * FAST is specified as the EAP method in the #NMSetting8021x:eap property.
+ * Recognized values are "0" (disabled), "1" (allow unauthenticated
+ * provisioning), "2" (allow authenticated provisioning), and "3" (allow
+ * both authenticated and unauthenticated provisioning).
+ **/
g_object_class_install_property
(object_class, PROP_PHASE1_FAST_PROVISIONING,
g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING,
@@ -1426,6 +2590,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase2-auth:
+ *
+ * Specifies the allowed "phase 2" inner non-EAP authentication methods when
+ * an EAP method that uses an inner TLS tunnel is specified in the
+ * #NMSetting8021x:eap property. Recognized non-EAP phase2 methods are
+ * "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", and "tls".
+ **/
g_object_class_install_property
(object_class, PROP_PHASE2_AUTH,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH,
@@ -1434,6 +2606,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase2-autheap:
+ *
+ * Specifies the allowed "phase 2" inner EAP-based authentication methods
+ * when an EAP method that uses an inner TLS tunnel is specified in the
+ * #NMSetting8021x:eap property. Recognized EAP-based phase2 methods are
+ * "md5", "mschapv2", "otp", "gtc", and "tls".
+ **/
g_object_class_install_property
(object_class, PROP_PHASE2_AUTHEAP,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP,
@@ -1442,6 +2622,17 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase2-ca-cert:
+ *
+ * Raw X.509 CA certificate data if used by the authentication method
+ * specified in the #NMSetting8021x:phase2-auth or
+ * #NMSetting8021x:phase2-autheap properties. Can be unset even if the
+ * authentication method supports CA certificates, but this allows
+ * man-in-the-middle attacks and is NOT recommended. This property is
+ * cleared when the #NMSetting8021x:phase2-ca-cert-path property is set
+ * since the two are mutually exclusive.
+ **/
g_object_class_install_property
(object_class, PROP_PHASE2_CA_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CA_CERT,
@@ -1450,6 +2641,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase2-ca-path:
+ *
+ * Path to a directory containing PEM or DER formatted certificates to be
+ * added to the verification chain in addition to the certificate specified
+ * in either of the #NMSetting8021x:phase2-ca-cert or
+ * #NMSetting8021x:phase2-ca-cert-path properties.
+ **/
g_object_class_install_property
(object_class, PROP_PHASE2_CA_PATH,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH,
@@ -1458,6 +2657,16 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:phase2-client-cert:
+ *
+ * Raw X.509 client certificate data if used by the authentication method
+ * specified in the #NMSetting8021x:phase2-auth or
+ * #NMSetting8021x:phase2-autheap properties. Currently only TLS supports
+ * client certificates. This property is cleared when the
+ * #NMSetting8021x:phase2-client-cert-path property is set since the two are
+ * mutually exclusive.
+ **/
g_object_class_install_property
(object_class, PROP_PHASE2_CLIENT_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
@@ -1466,6 +2675,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ /**
+ * NMSetting8021x:password:
+ *
+ * Password used for EAP authentication methods.
+ **/
g_object_class_install_property
(object_class, PROP_PASSWORD,
g_param_spec_string (NM_SETTING_802_1X_PASSWORD,
@@ -1474,6 +2688,21 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+ /**
+ * NMSetting8021x:private-key:
+ *
+ * When X.509 private keys are used by the EAP method specified in the
+ * #NMSetting8021x:eap property, contains the raw decrypted X.509 key
+ * data. When PKCS#12 format private keys are used, contains the PCKS#12
+ * data (which is encrypted) and the #NMSetting8021x:private-key-password
+ * property must also be set to the password used to decrypt the PKCS#12
+ * certificate and key. Currently only TLS supports private keys. When
+ * PKCS#12 format private keys are used, the #NMSetting8021x:client-cert
+ * must also be set to the same value.
+ *
+ * This property is cleared when the #NMSetting8021x:private-key-path
+ * property is set since the two are mutually exclusive.
+ **/
g_object_class_install_property
(object_class, PROP_PRIVATE_KEY,
_nm_param_spec_specialized (NM_SETTING_802_1X_PRIVATE_KEY,
@@ -1482,6 +2711,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+ /**
+ * NMSetting8021x:private-key-password:
+ *
+ * The password used to decrypt the private key specified by
+ * #NMSetting8021x:private-key or #NMSetting8021x:private-key-path
+ **/
g_object_class_install_property
(object_class, PROP_PRIVATE_KEY_PASSWORD,
g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
@@ -1490,6 +2725,24 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+ /**
+ * NMSetting8021x:phase2-private-key:
+ *
+ * Private key data used by "phase 2" inner authentication methods.
+ *
+ * When X.509 private keys are used by the authentication method specified
+ * by the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap
+ * properties, contains the raw decrypted X.509 key data. When PKCS#12
+ * format private keys are used, contains the PCKS#12 data (which is
+ * encrypted) and the #NMSetting8021x:private-key-password property must
+ * also be set to the password used to decrypt the PKCS#12 certificate and
+ * key. Currently only TLS supports private keys. When PKCS#12 format
+ * private keys are used, the #NMSetting8021x:phase2-client-cert must also
+ * be set to the same value.
+ *
+ * This property is cleared when the #NMSetting8021x:phase2-private-key-path
+ * property is set since the two are mutually exclusive.
+ **/
g_object_class_install_property
(object_class, PROP_PHASE2_PRIVATE_KEY,
_nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
@@ -1498,6 +2751,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+ /**
+ * NMSetting8021x:phase2-private-key-password:
+ *
+ * The password used to decrypt the private key specified by
+ * #NMSetting8021x:phase2-private-key or
+ * #NMSetting8021x:phase2-private-key-path
+ **/
g_object_class_install_property
(object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
@@ -1506,6 +2766,17 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+ /**
+ * NMSetting8021x:system-ca-certs:
+ *
+ * When TRUE, overrides #NMSetting8021x:ca-path and
+ * #NMSetting8021x:phase2-ca-path properties using the system CA directory
+ * specified and configure time with the --system-ca-path switch. The
+ * certificates in this directory are added to the verification chain in
+ * addition to any certificates specified by the #NMSetting8021x:ca-cert,
+ * #NMSetting8021x:ca-cert-path, #NMSetting8021x:phase2-ca-cert and
+ * #NMSetting8021x:phase2-ca-cert-path properties.
+ **/
g_object_class_install_property
(object_class, PROP_SYSTEM_CA_CERTS,
g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS,
diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h
index e956e685ae..a8ad941b39 100644
--- a/libnm-util/nm-setting-8021x.h
+++ b/libnm-util/nm-setting-8021x.h
@@ -19,7 +19,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
- * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ * (C) Copyright 2007 - 2009 Red Hat, Inc.
* (C) Copyright 2007 - 2008 Novell, Inc.
*/
@@ -31,11 +31,17 @@
G_BEGIN_DECLS
typedef enum {
- NM_SETTING_802_1X_CK_TYPE_UNKNOWN = 0,
- NM_SETTING_802_1X_CK_TYPE_X509,
- NM_SETTING_802_1X_CK_TYPE_RAW_KEY,
- NM_SETTING_802_1X_CK_TYPE_PKCS12
-} NMSetting8021xCKType;
+ NM_SETTING_802_1X_CK_FORMAT_UNKNOWN = 0,
+ NM_SETTING_802_1X_CK_FORMAT_X509,
+ NM_SETTING_802_1X_CK_FORMAT_RAW_KEY,
+ NM_SETTING_802_1X_CK_FORMAT_PKCS12
+} NMSetting8021xCKFormat;
+
+typedef enum {
+ NM_SETTING_802_1X_CK_SCHEME_UNKNOWN = 0,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ NM_SETTING_802_1X_CK_SCHEME_PATH
+} NMSetting8021xCKScheme;
#define NM_TYPE_SETTING_802_1X (nm_setting_802_1x_get_type ())
#define NM_SETTING_802_1X(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_802_1X, NMSetting8021x))
@@ -83,6 +89,30 @@ GQuark nm_setting_802_1x_error_quark (void);
#define NM_SETTING_802_1X_PSK "psk"
#define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs"
+/* PRIVATE KEY NOTE: when setting PKCS#12 private keys directly via properties
+ * using the "blob" scheme, the data must be passed in PKCS#12 format. In this
+ * case, the private key password must also be passed to NetworkManager, and the
+ * appropriate "client-cert" (or "phase2-client-cert") property of the
+ * NMSetting8021x object must also contain the exact same PKCS#12 data that the
+ * private key will when NetworkManager requests secrets. This is because the
+ * PKCS#12 file contains both the private key and client certificate, so both
+ * properties need to be set to the same thing. When using the "path" scheme,
+ * just set both the private-key and client-cert properties to the same path,
+ * and set the private-key password correctly.
+ *
+ * When setting OpenSSL-derived "traditional" format (ie S/MIME style, not
+ * PKCS#8) RSA and DSA keys directly via properties with the "blob" scheme, they
+ * must passed to NetworkManager completely decrypted because the OpenSSL
+ * "traditional" format is non-standard and is not complete enough for all
+ * crypto libraries to use. Thus, for OpenSSL "traditional" format keys, the
+ * private key password is not passed to NetworkManager (because the data is
+ * already decrypted by the client), and the appropriate "client-cert" (or
+ * "phase2-client-cert") property of the NMSetting8021x object must be a valid
+ * client certificate. When using the "path" scheme, just set the private-key
+ * and client-cert properties to the paths to their respective objects, and
+ * set the private-key password correctly.
+ */
+
typedef struct {
NMSetting parent;
} NMSetting8021x;
@@ -105,18 +135,27 @@ const char * nm_setting_802_1x_get_identity (NMSetting8
const char * nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting);
-const GByteArray *nm_setting_802_1x_get_ca_cert (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting);
const char * nm_setting_802_1x_get_ca_path (NMSetting8021x *setting);
-gboolean nm_setting_802_1x_set_ca_cert_from_file (NMSetting8021x *setting,
- const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err);
+const char * nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting);
-const GByteArray *nm_setting_802_1x_get_client_cert (NMSetting8021x *setting);
-gboolean nm_setting_802_1x_set_client_cert_from_file (NMSetting8021x *setting,
+NMSetting8021xCKScheme nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting);
+const GByteArray * nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
+ const char *filename,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting);
+const GByteArray * nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err);
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
const char * nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting);
@@ -128,19 +167,23 @@ const char * nm_setting_802_1x_get_phase2_auth (NMSetting8
const char * nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting);
-const GByteArray *nm_setting_802_1x_get_phase2_ca_cert (NMSetting8021x *setting);
-const char * nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting);
-gboolean nm_setting_802_1x_set_phase2_ca_cert_from_file (NMSetting8021x *setting,
- const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err);
-gboolean nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting);
-
-const GByteArray *nm_setting_802_1x_get_phase2_client_cert (NMSetting8021x *setting);
-gboolean nm_setting_802_1x_set_phase2_client_cert_from_file (NMSetting8021x *setting,
+NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting);
+const GByteArray * nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
const char *filename,
- NMSetting8021xCKType *out_ck_type,
- GError **err);
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting);
+const GByteArray * nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
+ const char *filename,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
const char * nm_setting_802_1x_get_password (NMSetting8021x *setting);
@@ -148,39 +191,31 @@ const char * nm_setting_802_1x_get_pin (NMSetting8
const char * nm_setting_802_1x_get_psk (NMSetting8021x *setting);
-/* PRIVATE KEY NOTE: when PKCS#12 private keys are used, the PKCS#12 data must
- * be passed to NetworkManager as PKCS#12 (ie, shrouded). In this case, the
- * private key password must also be passed to NetworkManager, and the
- * appropriate "client-cert" (or "phase2-client-cert") property of the
- * NMSetting8021x object must also contain the exact same PKCS#12 data that the
- * private key will when NetworkManager requests secrets.
- *
- * When OpenSSL-derived "traditional" format (ie S/MIME style, not PKCS#8) RSA
- * and DSA keys are used, they must passed to NetworkManager completely
- * decrypted because the OpenSSL "traditional" format is non-standard and is not
- * complete enough for all crypto libraries to use. Thus, for OpenSSL
- * "traditional" format keys, the private key password is not passed to
- * NetworkManager, and the appropriate "client-cert" (or "phase2-client-cert")
- * property of the NMSetting8021x object must be a valid client certificate.
- */
-
-const GByteArray *nm_setting_802_1x_get_private_key (NMSetting8021x *setting);
-const char * nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting);
-gboolean nm_setting_802_1x_set_private_key_from_file (NMSetting8021x *setting,
- const char *filename,
- const char *password,
- NMSetting8021xCKType *out_ck_type,
- GError **err);
-NMSetting8021xCKType nm_setting_802_1x_get_private_key_type (NMSetting8021x *setting);
-
-const GByteArray *nm_setting_802_1x_get_phase2_private_key (NMSetting8021x *setting);
-const char * nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting);
-gboolean nm_setting_802_1x_set_phase2_private_key_from_file (NMSetting8021x *setting,
- const char *filename,
- const char *password,
- NMSetting8021xCKType *out_ck_type,
- GError **err);
-NMSetting8021xCKType nm_setting_802_1x_get_phase2_private_key_type (NMSetting8021x *setting);
+NMSetting8021xCKScheme nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting);
+const GByteArray * nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_private_key (NMSetting8021x *setting,
+ const char *filename,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+const char * nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting);
+
+NMSetting8021xCKFormat nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting);
+const GByteArray * nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
+ const char *filename,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+const char * nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting);
+
+NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting);
G_END_DECLS
diff --git a/libnm-util/tests/test-crypto.c b/libnm-util/tests/test-crypto.c
index 75e34d3ad7..18920342d4 100644
--- a/libnm-util/tests/test-crypto.c
+++ b/libnm-util/tests/test-crypto.c
@@ -205,7 +205,7 @@ test_is_pkcs12 (const char *path, gboolean expect_fail, const char *desc)
{
gboolean is_pkcs12;
- is_pkcs12 = crypto_is_pkcs12_file (path);
+ is_pkcs12 = crypto_is_pkcs12_file (path, NULL);
if (expect_fail) {
ASSERT (is_pkcs12 == FALSE, desc,
"unexpected success reading non-PKCS#12 file '%s'",
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index 64a4a06265..3bf92794d2 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -702,8 +702,8 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
{
NMSupplicantConfigPrivate *priv;
char *tmp;
- const char *peapver, *value;
- gboolean success;
+ const char *peapver, *value, *path;
+ gboolean success, added;
GString *phase1, *phase2;
const GByteArray *array;
@@ -780,53 +780,163 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
}
g_string_free (phase2, TRUE);
- if (nm_setting_802_1x_get_system_ca_certs (setting)) {
- if (!add_string_val (self, SYSTEM_CA_PATH, "ca_path", FALSE, FALSE))
+ /* CA path */
+ path = nm_setting_802_1x_get_ca_path (setting);
+ if (nm_setting_802_1x_get_system_ca_certs (setting))
+ path = SYSTEM_CA_PATH;
+ if (path) {
+ if (!add_string_val (self, path, "ca_path", FALSE, FALSE))
return FALSE;
- } else {
- ADD_BLOB_VAL (nm_setting_802_1x_get_ca_cert (setting), "ca_cert", connection_uid);
}
- array = nm_setting_802_1x_get_private_key (setting);
- if (array) {
+ /* Phase2 CA path */
+ path = nm_setting_802_1x_get_phase2_ca_path (setting);
+ if (nm_setting_802_1x_get_system_ca_certs (setting))
+ path = SYSTEM_CA_PATH;
+ if (path) {
+ if (!add_string_val (self, path, "ca_path2", FALSE, FALSE))
+ return FALSE;
+ }
+
+ /* CA certificate */
+ switch (nm_setting_802_1x_get_ca_cert_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ array = nm_setting_802_1x_get_ca_cert_blob (setting);
+ ADD_BLOB_VAL (array, "ca_cert", connection_uid);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_ca_cert_path (setting);
+ if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
+
+ /* Phase 2 CA certificate */
+ switch (nm_setting_802_1x_get_phase2_ca_cert_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ array = nm_setting_802_1x_get_phase2_ca_cert_blob (setting);
+ ADD_BLOB_VAL (array, "ca_cert2", connection_uid);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_phase2_ca_cert_path (setting);
+ if (!add_string_val (self, path, "ca_cert2", FALSE, FALSE))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
+
+ /* Private key */
+ added = FALSE;
+ switch (nm_setting_802_1x_get_private_key_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ array = nm_setting_802_1x_get_private_key_blob (setting);
ADD_BLOB_VAL (array, "private_key", connection_uid);
+ added = TRUE;
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_private_key_path (setting);
+ if (!add_string_val (self, path, "private_key", FALSE, FALSE))
+ return FALSE;
+ added = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ if (added) {
+ NMSetting8021xCKFormat format;
+ NMSetting8021xCKScheme scheme;
- switch (nm_setting_802_1x_get_private_key_type (setting)) {
- case NM_SETTING_802_1X_CK_TYPE_PKCS12:
- /* Only add the private key password for PKCS#12 keys */
+ format = nm_setting_802_1x_get_private_key_format (setting);
+ scheme = nm_setting_802_1x_get_private_key_scheme (setting);
+
+ if ( scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+ || format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ /* Only add the private key password for PKCS#12 blobs and
+ * all path schemes, since in both of these cases the private key
+ * isn't decrypted at all.
+ */
value = nm_setting_802_1x_get_private_key_password (setting);
if (!add_string_val (self, value, "private_key_passwd", FALSE, TRUE))
return FALSE;
- break;
- default:
- /* Only add the client cert if the private key is not PKCS#12 */
- ADD_BLOB_VAL (nm_setting_802_1x_get_client_cert (setting), "client_cert", connection_uid);
- break;
+ }
+
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ /* Only add the client cert if the private key is not PKCS#12, as
+ * wpa_supplicant configuration directs us to do.
+ */
+ switch (nm_setting_802_1x_get_client_cert_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ array = nm_setting_802_1x_get_client_cert_blob (setting);
+ ADD_BLOB_VAL (array, "client_cert", connection_uid);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_client_cert_path (setting);
+ if (!add_string_val (self, path, "client_cert", FALSE, FALSE))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
}
}
- if (nm_setting_802_1x_get_system_ca_certs (setting)) {
- if (!add_string_val (self, SYSTEM_CA_PATH, "ca_path2", FALSE, FALSE))
+ /* Phase 2 private key */
+ added = FALSE;
+ switch (nm_setting_802_1x_get_phase2_private_key_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ array = nm_setting_802_1x_get_phase2_private_key_blob (setting);
+ ADD_BLOB_VAL (array, "private_key2", connection_uid);
+ added = TRUE;
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_phase2_private_key_path (setting);
+ if (!add_string_val (self, path, "private_key2", FALSE, FALSE))
return FALSE;
- } else {
- ADD_BLOB_VAL (nm_setting_802_1x_get_phase2_ca_cert (setting), "ca_cert2", connection_uid);
+ added = TRUE;
+ break;
+ default:
+ break;
}
- array = nm_setting_802_1x_get_phase2_private_key (setting);
- if (array) {
- ADD_BLOB_VAL (array, "private_key2", connection_uid);
+ if (added) {
+ NMSetting8021xCKFormat format;
+ NMSetting8021xCKScheme scheme;
+
+ format = nm_setting_802_1x_get_phase2_private_key_format (setting);
+ scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting);
- switch (nm_setting_802_1x_get_phase2_private_key_type (setting)) {
- case NM_SETTING_802_1X_CK_TYPE_PKCS12:
- /* Only add the private key password for PKCS#12 keys */
+ if ( scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+ || format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ /* Only add the private key password for PKCS#12 blobs and
+ * all path schemes, since in both of these cases the private key
+ * isn't decrypted at all.
+ */
value = nm_setting_802_1x_get_phase2_private_key_password (setting);
- if (!add_string_val (self, value, "private_key2_passwd", FALSE, TRUE))
+ if (!add_string_val (self, value, "private_key_passwd2", FALSE, TRUE))
return FALSE;
- break;
- default:
- /* Only add the client cert if the private key is not PKCS#12 */
- ADD_BLOB_VAL (nm_setting_802_1x_get_phase2_client_cert (setting), "client_cert2", connection_uid);
- break;
+ }
+
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ /* Only add the client cert if the private key is not PKCS#12, as
+ * wpa_supplicant configuration directs us to do.
+ */
+ switch (nm_setting_802_1x_get_phase2_client_cert_scheme (setting)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ array = nm_setting_802_1x_get_phase2_client_cert_blob (setting);
+ ADD_BLOB_VAL (array, "client_cert2", connection_uid);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = nm_setting_802_1x_get_phase2_client_cert_path (setting);
+ if (!add_string_val (self, path, "client_cert2", FALSE, FALSE))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/system-settings/plugins/ifcfg-rh/common.h b/system-settings/plugins/ifcfg-rh/common.h
index 1569132a93..c2dca77a6d 100644
--- a/system-settings/plugins/ifcfg-rh/common.h
+++ b/system-settings/plugins/ifcfg-rh/common.h
@@ -38,24 +38,6 @@
#define TYPE_ETHERNET "Ethernet"
#define TYPE_WIRELESS "Wireless"
-#define TAG_CA_CERT_PATH "ca-cert-path"
-#define TAG_CA_CERT_HASH "ca-cert-hash"
-
-#define TAG_CLIENT_CERT_PATH "client-cert-path"
-#define TAG_CLIENT_CERT_HASH "client-cert-hash"
-
-#define TAG_PRIVATE_KEY_PATH "private-key-path"
-#define TAG_PRIVATE_KEY_HASH "private-key-hash"
-
-#define TAG_PHASE2_CA_CERT_PATH "phase2-ca-cert-path"
-#define TAG_PHASE2_CA_CERT_HASH "phase2-ca-cert-hash"
-
-#define TAG_PHASE2_CLIENT_CERT_PATH "phase2-client-cert-path"
-#define TAG_PHASE2_CLIENT_CERT_HASH "phase2-client-cert-hash"
-
-#define TAG_PHASE2_PRIVATE_KEY_PATH "phase2-private-key-path"
-#define TAG_PHASE2_PRIVATE_KEY_HASH "phase2-private-key-hash"
-
GQuark ifcfg_plugin_error_quark (void);
diff --git a/system-settings/plugins/ifcfg-rh/reader.c b/system-settings/plugins/ifcfg-rh/reader.c
index 8d6b311d4c..0ac6e9f975 100644
--- a/system-settings/plugins/ifcfg-rh/reader.c
+++ b/system-settings/plugins/ifcfg-rh/reader.c
@@ -1201,21 +1201,6 @@ get_cert_file (const char *ifcfg_path, const char *cert_path)
return ret;
}
-static void
-set_file_path (NMSetting8021x *s_8021x,
- const char *path_tag,
- const char *hash_tag,
- const char *path,
- const char *setting_key)
-{
- GByteArray *data = NULL;
-
- g_object_set_data_full (G_OBJECT (s_8021x), path_tag, g_strdup (path), g_free);
- g_object_get (G_OBJECT (s_8021x), setting_key, &data, NULL);
- if (data)
- g_object_set_data_full (G_OBJECT (s_8021x), hash_tag, utils_hash_byte_array (data), g_free);
-}
-
static gboolean
eap_tls_reader (const char *eap_method,
shvarFile *ifcfg,
@@ -1231,7 +1216,7 @@ eap_tls_reader (const char *eap_method,
char *privkey = NULL;
char *privkey_password = NULL;
gboolean success = FALSE;
- NMSetting8021xCKType privkey_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
+ NMSetting8021xCKFormat privkey_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
value = svGetValue (ifcfg, "IEEE_8021X_IDENTITY", FALSE);
if (!value) {
@@ -1249,21 +1234,19 @@ eap_tls_reader (const char *eap_method,
if (ca_cert) {
real_path = get_cert_file (ifcfg->fileName, ca_cert);
if (phase2) {
- if (!nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, real_path, NULL, error))
+ if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x,
+ real_path,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_PHASE2_CA_CERT_PATH,
- TAG_PHASE2_CA_CERT_HASH,
- real_path,
- NM_SETTING_802_1X_PHASE2_CA_CERT);
} else {
- if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_path, NULL, error))
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+ real_path,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_CA_CERT_PATH,
- TAG_CA_CERT_HASH,
- real_path,
- NM_SETTING_802_1X_CA_CERT);
}
} else {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing %s for EAP"
@@ -1306,56 +1289,30 @@ eap_tls_reader (const char *eap_method,
g_free (real_path);
real_path = get_cert_file (ifcfg->fileName, privkey);
if (phase2) {
- if (!nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error))
+ if (!nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ real_path,
+ privkey_password,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ &privkey_format,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_PHASE2_PRIVATE_KEY_PATH,
- TAG_PHASE2_PRIVATE_KEY_HASH,
- real_path,
- NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
} else {
- if (!nm_setting_802_1x_set_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error))
+ if (!nm_setting_802_1x_set_private_key (s_8021x,
+ real_path,
+ privkey_password,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ &privkey_format,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_PRIVATE_KEY_PATH,
- TAG_PRIVATE_KEY_HASH,
- real_path,
- NM_SETTING_802_1X_PRIVATE_KEY);
}
- /* Per NM requirements, if the private key is pkcs12, set the client cert to the
- * same data as the private key, since pkcs12 files contain both.
+ /* Only set the client certificate if the private key is not PKCS#12 format,
+ * as NM (due to supplicant restrictions) requires. If the key was PKCS#12,
+ * then nm_setting_802_1x_set_private_key() already set the client certificate
+ * to the same value as the private key.
*/
- if (privkey_type == NM_SETTING_802_1X_CK_TYPE_PKCS12) {
- /* Set the private key password if PKCS#12, because PKCS#12 doesn't get
- * decrypted when being stored in the Setting.
- */
- if (phase2)
- g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, privkey_password, NULL);
- else
- g_object_set (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, privkey_password, NULL);
-
- if (phase2) {
- if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error))
- goto done;
- set_file_path (s_8021x,
- TAG_PHASE2_CLIENT_CERT_PATH,
- TAG_PHASE2_CLIENT_CERT_HASH,
- real_path,
- NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
- } else {
- if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error))
- goto done;
- set_file_path (s_8021x,
- TAG_CLIENT_CERT_PATH,
- TAG_CLIENT_CERT_HASH,
- real_path,
- NM_SETTING_802_1X_CLIENT_CERT);
- }
- } else {
- /* Otherwise, private key is "traditional" OpenSSL format, so
- * client certificate will be a separate file.
- */
+ if ( privkey_format == NM_SETTING_802_1X_CK_FORMAT_RAW_KEY
+ || privkey_format == NM_SETTING_802_1X_CK_FORMAT_X509) {
client_cert = svGetValue (ifcfg,
phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT",
FALSE);
@@ -1370,21 +1327,19 @@ eap_tls_reader (const char *eap_method,
g_free (real_path);
real_path = get_cert_file (ifcfg->fileName, client_cert);
if (phase2) {
- if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error))
+ if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x,
+ real_path,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_PHASE2_CLIENT_CERT_PATH,
- TAG_PHASE2_CLIENT_CERT_HASH,
- real_path,
- NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
} else {
- if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error))
+ if (!nm_setting_802_1x_set_client_cert (s_8021x,
+ real_path,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_CLIENT_CERT_PATH,
- TAG_CLIENT_CERT_HASH,
- real_path,
- NM_SETTING_802_1X_CLIENT_CERT);
}
}
@@ -1418,13 +1373,12 @@ eap_peap_reader (const char *eap_method,
ca_cert = svGetValue (ifcfg, "IEEE_8021X_CA_CERT", FALSE);
if (ca_cert) {
real_cert_path = get_cert_file (ifcfg->fileName, ca_cert);
- if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error))
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+ real_cert_path,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_CA_CERT_PATH,
- TAG_CA_CERT_HASH,
- real_cert_path,
- NM_SETTING_802_1X_CA_CERT);
} else {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing "
"IEEE_8021X_CA_CERT for EAP method '%s'; this is"
@@ -1520,13 +1474,12 @@ eap_ttls_reader (const char *eap_method,
ca_cert = svGetValue (ifcfg, "IEEE_8021X_CA_CERT", FALSE);
if (ca_cert) {
real_cert_path = get_cert_file (ifcfg->fileName, ca_cert);
- if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error))
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+ real_cert_path,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ error))
goto done;
- set_file_path (s_8021x,
- TAG_CA_CERT_PATH,
- TAG_CA_CERT_HASH,
- real_cert_path,
- NM_SETTING_802_1X_CA_CERT);
} else {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing "
"IEEE_8021X_CA_CERT for EAP method '%s'; this is"
diff --git a/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 2afb147b9b..12e8008596 100644
--- a/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -69,8 +69,9 @@ verify_cert_or_key (CertKeyType ck_type,
NMSetting8021x *s_8021x;
GError *error = NULL;
gboolean success = FALSE;
- const GByteArray *expected = NULL, *setting = NULL;
+ const char *expected = NULL, *setting = NULL;
gboolean phase2 = FALSE;
+ NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
if (strstr (setting_key, "phase2"))
phase2 = TRUE;
@@ -83,19 +84,19 @@ verify_cert_or_key (CertKeyType ck_type,
if (ck_type == CK_CA_CERT) {
if (phase2)
- success = nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, file, NULL, &error);
+ success = nm_setting_802_1x_set_phase2_ca_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
else
- success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x, file, NULL, &error);
+ success = nm_setting_802_1x_set_ca_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
} else if (ck_type == CK_CLIENT_CERT) {
if (phase2)
- success = nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, file, NULL, &error);
+ success = nm_setting_802_1x_set_phase2_client_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
else
- success = nm_setting_802_1x_set_client_cert_from_file (s_8021x, file, NULL, &error);
+ success = nm_setting_802_1x_set_client_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
} else if (ck_type == CK_PRIV_KEY) {
if (phase2)
- success = nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, file, privkey_password, NULL, &error);
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x, file, privkey_password, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
else
- success = nm_setting_802_1x_set_private_key_from_file (s_8021x, file, privkey_password, NULL, &error);
+ success = nm_setting_802_1x_set_private_key (s_8021x, file, privkey_password, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
}
ASSERT (success == TRUE,
test_name, "failed to verify %s: could not load item for %s / %s: %s",
@@ -103,19 +104,39 @@ verify_cert_or_key (CertKeyType ck_type,
if (ck_type == CK_CA_CERT) {
if (phase2)
- expected = nm_setting_802_1x_get_phase2_ca_cert (s_8021x);
+ scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (s_8021x);
else
- expected = nm_setting_802_1x_get_ca_cert (s_8021x);
+ scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
} else if (ck_type == CK_CLIENT_CERT) {
if (phase2)
- expected = nm_setting_802_1x_get_phase2_client_cert (s_8021x);
+ scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (s_8021x);
else
- expected = nm_setting_802_1x_get_client_cert (s_8021x);
+ scheme = nm_setting_802_1x_get_client_cert_scheme (s_8021x);
} else if (ck_type == CK_PRIV_KEY) {
if (phase2)
- expected = nm_setting_802_1x_get_phase2_private_key (s_8021x);
+ scheme = nm_setting_802_1x_get_phase2_private_key_scheme (s_8021x);
else
- expected = nm_setting_802_1x_get_private_key (s_8021x);
+ scheme = nm_setting_802_1x_get_private_key_scheme (s_8021x);
+ }
+ ASSERT (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ test_name, "failed to verify %s: unexpected cert/key scheme for %s / %s",
+ ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key);
+
+ if (ck_type == CK_CA_CERT) {
+ if (phase2)
+ expected = nm_setting_802_1x_get_phase2_ca_cert_path (s_8021x);
+ else
+ expected = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ } else if (ck_type == CK_CLIENT_CERT) {
+ if (phase2)
+ expected = nm_setting_802_1x_get_phase2_client_cert_path (s_8021x);
+ else
+ expected = nm_setting_802_1x_get_client_cert_path (s_8021x);
+ } else if (ck_type == CK_PRIV_KEY) {
+ if (phase2)
+ expected = nm_setting_802_1x_get_phase2_private_key_path (s_8021x);
+ else
+ expected = nm_setting_802_1x_get_private_key_path (s_8021x);
}
ASSERT (expected != NULL,
test_name, "failed to verify %s: failed to get read item for %s / %s",
@@ -123,29 +144,29 @@ verify_cert_or_key (CertKeyType ck_type,
if (ck_type == CK_CA_CERT) {
if (phase2)
- setting = nm_setting_802_1x_get_phase2_ca_cert (s_compare);
+ setting = nm_setting_802_1x_get_phase2_ca_cert_path (s_compare);
else
- setting = nm_setting_802_1x_get_ca_cert (s_compare);
+ setting = nm_setting_802_1x_get_ca_cert_path (s_compare);
} else if (ck_type == CK_CLIENT_CERT) {
if (phase2)
- setting = nm_setting_802_1x_get_phase2_client_cert (s_compare);
+ setting = nm_setting_802_1x_get_phase2_client_cert_path (s_compare);
else
- setting = nm_setting_802_1x_get_client_cert (s_compare);
+ setting = nm_setting_802_1x_get_client_cert_path (s_compare);
} else if (ck_type == CK_PRIV_KEY) {
if (phase2)
- setting = nm_setting_802_1x_get_phase2_private_key (s_compare);
+ setting = nm_setting_802_1x_get_phase2_private_key_path (s_compare);
else
- setting = nm_setting_802_1x_get_private_key (s_compare);
+ setting = nm_setting_802_1x_get_private_key_path (s_compare);
}
ASSERT (setting != NULL,
test_name, "failed to verify %s: missing %s / %s key",
ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key);
- ASSERT (setting->len == expected->len,
+ ASSERT (strlen (setting) == strlen (expected),
test_name, "failed to verify %s: unexpected %s / %s certificate length",
test_name, NM_SETTING_802_1X_SETTING_NAME, setting_key);
- ASSERT (memcmp (setting->data, expected->data, setting->len) == 0,
+ ASSERT (strcmp (setting, expected) == 0,
test_name, "failed to verify %s: %s / %s key certificate mismatch",
ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key);
@@ -1040,8 +1061,8 @@ test_read_wired_8021x_peap_mschapv2 (void)
const char *expected_identity = "David Smith";
const char *expected_password = "foobar baz";
gboolean success = FALSE;
- const GByteArray *expected_ca_cert;
- const GByteArray *read_ca_cert;
+ const char *expected_ca_cert_path;
+ const char *read_ca_cert_path;
connection = connection_from_file (TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
NULL,
@@ -1166,40 +1187,34 @@ test_read_wired_8021x_peap_mschapv2 (void)
ASSERT (tmp_8021x != NULL,
"wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: could not create temp 802.1x setting",
TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
- NM_SETTING_802_1X_SETTING_NAME,
- NM_SETTING_802_1X_CA_CERT);
+ NM_SETTING_802_1X_SETTING_NAME);
- success = nm_setting_802_1x_set_ca_cert_from_file (tmp_8021x,
- TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_ca_cert (tmp_8021x,
+ TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: could not load CA certificate",
TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
NM_SETTING_802_1X_SETTING_NAME,
NM_SETTING_802_1X_CA_CERT);
- expected_ca_cert = nm_setting_802_1x_get_ca_cert (tmp_8021x);
- ASSERT (expected_ca_cert != NULL,
+ expected_ca_cert_path = nm_setting_802_1x_get_ca_cert_path (tmp_8021x);
+ ASSERT (expected_ca_cert_path != NULL,
"wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: failed to get CA certificate",
TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
NM_SETTING_802_1X_SETTING_NAME,
NM_SETTING_802_1X_CA_CERT);
- read_ca_cert = nm_setting_802_1x_get_ca_cert (s_8021x);
- ASSERT (read_ca_cert != NULL,
+ read_ca_cert_path = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ ASSERT (read_ca_cert_path != NULL,
"wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
NM_SETTING_802_1X_SETTING_NAME,
NM_SETTING_802_1X_CA_CERT);
- ASSERT (read_ca_cert->len == expected_ca_cert->len,
- "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s certificate length",
- TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
- NM_SETTING_802_1X_SETTING_NAME,
- NM_SETTING_802_1X_CA_CERT);
-
- ASSERT (memcmp (read_ca_cert->data, expected_ca_cert->data, read_ca_cert->len) == 0,
- "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: %s / %s key certificate mismatch",
+ ASSERT (strcmp (read_ca_cert_path, expected_ca_cert_path) == 0,
+ "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s certificate path",
TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
NM_SETTING_802_1X_SETTING_NAME,
NM_SETTING_802_1X_CA_CERT);
@@ -2878,7 +2893,7 @@ test_read_wifi_wpa_eap_tls (void)
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
- const char *tmp;
+ const char *tmp, *password;
const char *expected_identity = "Bill Smith";
const char *expected_privkey_password = "test1";
@@ -2980,7 +2995,14 @@ test_read_wifi_wpa_eap_tls (void)
NM_SETTING_802_1X_CLIENT_CERT);
/* Private Key Password */
- ASSERT (nm_setting_802_1x_get_private_key_password (s_8021x) == NULL,
+ password = nm_setting_802_1x_get_private_key_password (s_8021x);
+ ASSERT (password != NULL,
+ "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s / %s key",
+ TEST_IFCFG_WIFI_WPA_EAP_TLS,
+ NM_SETTING_802_1X_SETTING_NAME,
+ NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+
+ ASSERT (strcmp (password, expected_privkey_password) == 0,
"wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key",
TEST_IFCFG_WIFI_WPA_EAP_TLS,
NM_SETTING_802_1X_SETTING_NAME,
@@ -3013,7 +3035,7 @@ test_read_wifi_wpa_eap_ttls_tls (void)
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
- const char *tmp;
+ const char *tmp, *password;
const char *expected_identity = "Chuck Shumer";
const char *expected_privkey_password = "test1";
@@ -3124,7 +3146,14 @@ test_read_wifi_wpa_eap_ttls_tls (void)
NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
/* Inner Private Key Password */
- ASSERT (nm_setting_802_1x_get_phase2_private_key_password (s_8021x) == NULL,
+ password = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
+ ASSERT (password != NULL,
+ "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s key",
+ TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
+ NM_SETTING_802_1X_SETTING_NAME,
+ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+
+ ASSERT (strcmp (password, expected_privkey_password) == 0,
"wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key",
TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
NM_SETTING_802_1X_SETTING_NAME,
@@ -3619,10 +3648,11 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
nm_setting_802_1x_add_eap_method (s_8021x, "peap");
- success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x,
- TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_ca_cert (s_8021x,
+ TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wired-dhcp-8021x-peap-mschapv2write", "failed to verify connection: %s",
(error && error->message) ? error->message : "(unknown)");
@@ -4548,27 +4578,30 @@ test_write_wifi_wpa_eap_tls (void)
nm_setting_802_1x_add_eap_method (s_8021x, "tls");
- success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_ca_cert (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-tls-write", "failed to set CA certificate '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
- success = nm_setting_802_1x_set_client_cert_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_client_cert (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-tls-write", "failed to set client certificate '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, error->message);
- success = nm_setting_802_1x_set_private_key_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY,
- "test1",
- NULL,
- &error);
+ success = nm_setting_802_1x_set_private_key (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY,
+ "test1",
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-tls-write", "failed to set private key '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, error->message);
@@ -4712,10 +4745,11 @@ test_write_wifi_wpa_eap_ttls_tls (void)
NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls",
NULL);
- success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_ca_cert (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-ttls-tls-write", "failed to set CA certificate '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
@@ -4723,29 +4757,32 @@ test_write_wifi_wpa_eap_ttls_tls (void)
/* Phase 2 TLS stuff */
/* phase2 CA cert */
- success = nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_phase2_ca_cert (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-ttls-tls-write", "failed to set inner CA certificate '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
/* phase2 client cert */
- success = nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_phase2_client_cert (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-ttls-tls-write", "failed to set inner client certificate '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, error->message);
/* phase2 private key */
- success = nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY,
- "test1",
- NULL,
- &error);
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY,
+ "test1",
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-ttls-tls-write", "failed to set private key '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, error->message);
@@ -4893,10 +4930,11 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
NM_SETTING_802_1X_PHASE2_AUTHEAP, "mschapv2",
NULL);
- success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x,
- TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
- NULL,
- &error);
+ success = nm_setting_802_1x_set_ca_cert (s_8021x,
+ TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ &error);
ASSERT (success == TRUE,
"wifi-wpa-eap-ttls-mschapv2-write", "failed to set CA certificate '%s': %s",
TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message);
diff --git a/system-settings/plugins/ifcfg-rh/utils.c b/system-settings/plugins/ifcfg-rh/utils.c
index 015769ac0a..956c53e26a 100644
--- a/system-settings/plugins/ifcfg-rh/utils.c
+++ b/system-settings/plugins/ifcfg-rh/utils.c
@@ -117,17 +117,6 @@ utils_hexstr2bin (const char *hex, size_t len)
/* End from hostap */
char *
-utils_hash_byte_array (const GByteArray *data)
-{
- unsigned char buf[SHA1_MAC_LEN];
- static const char *key = "0123456789abcdefghijklmnopqrstuvwxyz";
-
- memset (buf, 0, sizeof (buf));
- sha1_mac ((const unsigned char *) key, strlen (key), (const u_int8_t *) data->data, data->len, &buf[0]);
- return utils_bin2hexstr ((const char *) &buf[0], SHA1_MAC_LEN, SHA1_MAC_LEN * 2);
-}
-
-char *
utils_cert_path (const char *parent, const char *suffix)
{
char *name, *dir, *path;
diff --git a/system-settings/plugins/ifcfg-rh/utils.h b/system-settings/plugins/ifcfg-rh/utils.h
index 1dd7e7dcee..3424c6078d 100644
--- a/system-settings/plugins/ifcfg-rh/utils.h
+++ b/system-settings/plugins/ifcfg-rh/utils.h
@@ -29,8 +29,6 @@ char *utils_bin2hexstr (const char *bytes, int len, int final_len);
char *utils_hexstr2bin (const char *hex, size_t len);
-char *utils_hash_byte_array (const GByteArray *data);
-
char *utils_cert_path (const char *parent, const char *suffix);
char *utils_get_ifcfg_name (const char *file);
diff --git a/system-settings/plugins/ifcfg-rh/writer.c b/system-settings/plugins/ifcfg-rh/writer.c
index 02e4fa1146..763b94ed73 100644
--- a/system-settings/plugins/ifcfg-rh/writer.c
+++ b/system-settings/plugins/ifcfg-rh/writer.c
@@ -144,151 +144,187 @@ out:
return success;
}
+typedef NMSetting8021xCKScheme (*SchemeFunc)(NMSetting8021x *setting);
+typedef const char * (*PathFunc) (NMSetting8021x *setting);
+typedef const GByteArray * (*BlobFunc) (NMSetting8021x *setting);
+
typedef struct ObjectType {
const char *setting_key;
+ SchemeFunc scheme_func;
+ PathFunc path_func;
+ BlobFunc blob_func;
const char *ifcfg_key;
- const char *path_tag;
- const char *hash_tag;
const char *suffix;
} ObjectType;
static const ObjectType ca_type = {
NM_SETTING_802_1X_CA_CERT,
+ nm_setting_802_1x_get_ca_cert_scheme,
+ nm_setting_802_1x_get_ca_cert_path,
+ nm_setting_802_1x_get_ca_cert_blob,
"IEEE_8021X_CA_CERT",
- TAG_CA_CERT_PATH,
- TAG_CA_CERT_HASH,
"ca-cert.der"
};
static const ObjectType phase2_ca_type = {
NM_SETTING_802_1X_PHASE2_CA_CERT,
+ nm_setting_802_1x_get_phase2_ca_cert_scheme,
+ nm_setting_802_1x_get_phase2_ca_cert_path,
+ nm_setting_802_1x_get_phase2_ca_cert_blob,
"IEEE_8021X_INNER_CA_CERT",
- TAG_PHASE2_CA_CERT_PATH,
- TAG_PHASE2_CA_CERT_HASH,
"inner-ca-cert.der"
};
static const ObjectType client_type = {
NM_SETTING_802_1X_CLIENT_CERT,
+ nm_setting_802_1x_get_client_cert_scheme,
+ nm_setting_802_1x_get_client_cert_path,
+ nm_setting_802_1x_get_client_cert_blob,
"IEEE_8021X_CLIENT_CERT",
- TAG_CLIENT_CERT_PATH,
- TAG_CLIENT_CERT_HASH,
"client-cert.der"
};
static const ObjectType phase2_client_type = {
NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
+ nm_setting_802_1x_get_phase2_client_cert_scheme,
+ nm_setting_802_1x_get_phase2_client_cert_path,
+ nm_setting_802_1x_get_phase2_client_cert_blob,
"IEEE_8021X_INNER_CLIENT_CERT",
- TAG_PHASE2_CLIENT_CERT_PATH,
- TAG_PHASE2_CLIENT_CERT_HASH,
"inner-client-cert.der"
};
static const ObjectType pk_type = {
NM_SETTING_802_1X_PRIVATE_KEY,
+ nm_setting_802_1x_get_private_key_scheme,
+ nm_setting_802_1x_get_private_key_path,
+ nm_setting_802_1x_get_private_key_blob,
"IEEE_8021X_PRIVATE_KEY",
- TAG_PRIVATE_KEY_PATH,
- TAG_PRIVATE_KEY_HASH,
"private-key.pem"
};
static const ObjectType phase2_pk_type = {
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+ nm_setting_802_1x_get_phase2_private_key_scheme,
+ nm_setting_802_1x_get_phase2_private_key_path,
+ nm_setting_802_1x_get_phase2_private_key_blob,
"IEEE_8021X_INNER_PRIVATE_KEY",
- TAG_PHASE2_PRIVATE_KEY_PATH,
- TAG_PHASE2_PRIVATE_KEY_HASH,
"inner-private-key.pem"
};
static const ObjectType p12_type = {
NM_SETTING_802_1X_PRIVATE_KEY,
+ nm_setting_802_1x_get_private_key_scheme,
+ nm_setting_802_1x_get_private_key_path,
+ nm_setting_802_1x_get_private_key_blob,
"IEEE_8021X_PRIVATE_KEY",
- TAG_PRIVATE_KEY_PATH,
- TAG_PRIVATE_KEY_HASH,
"private-key.p12"
};
static const ObjectType phase2_p12_type = {
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+ nm_setting_802_1x_get_phase2_private_key_scheme,
+ nm_setting_802_1x_get_phase2_private_key_path,
+ nm_setting_802_1x_get_phase2_private_key_blob,
"IEEE_8021X_INNER_PRIVATE_KEY",
- TAG_PHASE2_PRIVATE_KEY_PATH,
- TAG_PHASE2_PRIVATE_KEY_HASH,
"inner-private-key.p12"
};
static gboolean
write_object (NMSetting8021x *s_8021x,
shvarFile *ifcfg,
- const GByteArray *object,
+ const GByteArray *override_data,
const ObjectType *objtype,
- gboolean *wrote,
GError **error)
{
- const char *orig_hash, *orig_file;
- char *new_hash = NULL, *new_file = NULL;
- gboolean success = FALSE;
- GError *write_error = NULL;
+ NMSetting8021xCKScheme scheme;
+ const char *path = NULL;
+ const GByteArray *blob = NULL;
- g_return_val_if_fail (objtype != NULL, FALSE);
g_return_val_if_fail (ifcfg != NULL, FALSE);
- g_return_val_if_fail (wrote != NULL, FALSE);
+ g_return_val_if_fail (objtype != NULL, FALSE);
+
+ if (override_data) {
+ /* if given explicit data to save, always use that instead of asking
+ * the setting what to do.
+ */
+ blob = override_data;
+ } else {
+ scheme = (*(objtype->scheme_func))(s_8021x);
+ switch (scheme) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ blob = (*(objtype->blob_func))(s_8021x);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = (*(objtype->path_func))(s_8021x);
+ break;
+ default:
+ break;
+ }
+ }
- *wrote = FALSE;
+ /* If certificate/private key was sent, the connection may no longer be
+ * 802.1x and thus we clear out the paths and certs.
+ */
+ if (!path && !blob) {
+ char *standard_file;
+ int ignored;
+
+ /* Since no cert/private key is now being used, delete any standard file
+ * that was created for this connection, but leave other files alone.
+ * Thus, for example,
+ * /etc/sysconfig/network-scripts/ca-cert-Test_Write_Wifi_WPA_EAP-TLS.der
+ * will be deleted, but /etc/pki/tls/cert.pem will not.
+ */
+ standard_file = utils_cert_path (ifcfg->fileName, objtype->suffix);
+ if (g_file_test (standard_file, G_FILE_TEST_EXISTS))
+ ignored = unlink (standard_file);
+ g_free (standard_file);
- if (!object) {
svSetValue (ifcfg, objtype->ifcfg_key, NULL, FALSE);
return TRUE;
}
- new_hash = utils_hash_byte_array (object);
- if (!new_hash) {
- g_set_error (error, ifcfg_plugin_error_quark (), 0,
- "Could not hash certificate/key data for %s / %s",
- NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key);
- return FALSE;
+ /* If the object path was specified, prefer that over any raw cert data that
+ * may have been sent.
+ */
+ if (path) {
+ svSetValue (ifcfg, objtype->ifcfg_key, path, FALSE);
+ return TRUE;
}
- orig_hash = g_object_get_data (G_OBJECT (s_8021x), objtype->hash_tag);
- orig_file = g_object_get_data (G_OBJECT (s_8021x), objtype->path_tag);
+ /* If it's raw certificate data, write the cert data out to the standard file */
+ if (blob) {
+ gboolean success;
+ char *new_file;
+ GError *write_error = NULL;
- if (!orig_hash || !orig_file || strcmp (new_hash, orig_hash)) {
- /* if the cert data has changed, or there wasn't a cert
- * originally, write data out to the standard file.
- */
new_file = utils_cert_path (ifcfg->fileName, objtype->suffix);
if (!new_file) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Could not create file path for %s / %s",
NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key);
- goto out;
+ return FALSE;
}
- if (!write_secret_file (new_file, (const char *) object->data, object->len, &write_error)) {
+ /* Write the raw certificate data out to the standard file so that we
+ * can use paths from now on instead of pushing around the certificate
+ * data itself.
+ */
+ success = write_secret_file (new_file, (const char *) blob->data, blob->len, &write_error);
+ if (success) {
+ svSetValue (ifcfg, objtype->ifcfg_key, new_file, FALSE);
+ return TRUE;
+ } else {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Could not write certificate/key for %s / %s: %s",
NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key,
(write_error && write_error->message) ? write_error->message : "(unknown)");
g_clear_error (&write_error);
- goto out;
}
- *wrote = TRUE;
-
- svSetValue (ifcfg, objtype->ifcfg_key, new_file, FALSE);
- g_object_set_data_full (G_OBJECT (s_8021x), objtype->path_tag, new_file, g_free);
- new_file = NULL; /* g_object_set_data_full() took ownership */
-
- g_object_set_data_full (G_OBJECT (s_8021x), objtype->hash_tag, new_hash, g_free);
- new_hash = NULL; /* g_object_set_data_full() took ownership */
- } else {
- /* cert data hasn't changed */
- svSetValue (ifcfg, objtype->ifcfg_key, orig_file, FALSE);
+ g_free (new_file);
}
- success = TRUE;
-out:
- g_free (new_hash);
- g_free (new_file);
- return success;
+ return FALSE;
}
static gboolean
@@ -297,16 +333,15 @@ write_8021x_certs (NMSetting8021x *s_8021x,
shvarFile *ifcfg,
GError **error)
{
- const GByteArray *data;
GByteArray *enc_key = NULL;
const char *password = NULL;
char *generated_pw = NULL;
- gboolean success = FALSE, is_pkcs12 = FALSE, wrote;
+ gboolean success = FALSE, is_pkcs12 = FALSE;
const ObjectType *otype = NULL;
const char *prop;
+ const GByteArray *blob = NULL;
/* CA certificate */
- data = NULL;
if (phase2) {
prop = NM_SETTING_802_1X_PHASE2_CA_CERT;
otype = &phase2_ca_type;
@@ -314,24 +349,22 @@ write_8021x_certs (NMSetting8021x *s_8021x,
prop = NM_SETTING_802_1X_CA_CERT;
otype = &ca_type;
}
- g_object_get (G_OBJECT (s_8021x), prop, &data, NULL);
- if (!write_object (s_8021x, ifcfg, data, otype, &wrote, error))
+
+ if (!write_object (s_8021x, ifcfg, NULL, otype, error))
return FALSE;
/* Private key */
if (phase2) {
- if (nm_setting_802_1x_get_phase2_private_key (s_8021x)) {
- if (nm_setting_802_1x_get_phase2_private_key_type (s_8021x) == NM_SETTING_802_1X_CK_TYPE_PKCS12)
+ if (nm_setting_802_1x_get_phase2_private_key_scheme (s_8021x) != NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+ if (nm_setting_802_1x_get_phase2_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
is_pkcs12 = TRUE;
}
- prop = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY;
password = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
} else {
- if (nm_setting_802_1x_get_private_key (s_8021x)) {
- if (nm_setting_802_1x_get_private_key_type (s_8021x) == NM_SETTING_802_1X_CK_TYPE_PKCS12)
+ if (nm_setting_802_1x_get_private_key_scheme (s_8021x) != NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+ if (nm_setting_802_1x_get_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
is_pkcs12 = TRUE;
}
- prop = NM_SETTING_802_1X_PRIVATE_KEY;
password = nm_setting_802_1x_get_private_key_password (s_8021x);
}
@@ -340,11 +373,19 @@ write_8021x_certs (NMSetting8021x *s_8021x,
else
otype = phase2 ? &phase2_pk_type : &pk_type;
- data = NULL;
- g_object_get (G_OBJECT (s_8021x), prop, &data, NULL);
- if (data && !is_pkcs12) {
+ if ((*(otype->scheme_func))(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ blob = (*(otype->blob_func))(s_8021x);
+
+ /* Only do the private key re-encrypt dance if we got the raw key data, which
+ * by definition will be unencrypted. If we're given a direct path to the
+ * private key file, it'll be encrypted, so we don't need to re-encrypt.
+ */
+ if (blob && !is_pkcs12) {
GByteArray *array;
+ /* If the private key is an unencrypted blob, re-encrypt it with a
+ * random password since we don't store unencrypted private keys on disk.
+ */
if (!password) {
/* Create a random private key */
array = crypto_random (32, error);
@@ -356,13 +397,14 @@ write_8021x_certs (NMSetting8021x *s_8021x,
g_byte_array_free (array, TRUE);
}
- /* Re-encrypt the private key if it's not PKCS#12 (which never decrypted by NM) */
- enc_key = crypto_key_to_pem (data, password, error);
+ /* Encrypt the unencrypted private key with the fake password */
+ enc_key = crypto_key_to_pem (blob, password, error);
if (!enc_key)
goto out;
}
- if (!write_object (s_8021x, ifcfg, enc_key ? enc_key : data, otype, &wrote, error))
+ /* Save the private key */
+ if (!write_object (s_8021x, ifcfg, enc_key, otype, error))
goto out;
/* Private key password */
@@ -371,11 +413,6 @@ write_8021x_certs (NMSetting8021x *s_8021x,
else
set_secret (ifcfg, "IEEE_8021X_PRIVATE_KEY_PASSWORD", password);
- if (enc_key) {
- memset (enc_key->data, 0, enc_key->len);
- g_byte_array_free (enc_key, TRUE);
- }
-
/* Client certificate */
if (is_pkcs12) {
svSetValue (ifcfg,
@@ -389,9 +426,9 @@ write_8021x_certs (NMSetting8021x *s_8021x,
prop = NM_SETTING_802_1X_CLIENT_CERT;
otype = &client_type;
}
- data = NULL;
- g_object_get (G_OBJECT (s_8021x), prop, &data, NULL);
- if (!write_object (s_8021x, ifcfg, data, otype, &wrote, error))
+
+ /* Save the client certificate */
+ if (!write_object (s_8021x, ifcfg, NULL, otype, error))
goto out;
}
@@ -402,6 +439,10 @@ out:
memset (generated_pw, 0, strlen (generated_pw));
g_free (generated_pw);
}
+ if (enc_key) {
+ memset (enc_key->data, 0, enc_key->len);
+ g_byte_array_free (enc_key, TRUE);
+ }
return success;
}