1394 lines
51 KiB
Diff
1394 lines
51 KiB
Diff
|
From 1e5cdbba7d816b06ce163710d2d6bdc87fe44b51 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <chingpang@gmail.com>
|
||
|
Date: Wed, 18 Jul 2012 12:14:56 +0800
|
||
|
Subject: [PATCH 1/4] libnm-util: allow the server hash to be the CA
|
||
|
certificate
|
||
|
|
||
|
---
|
||
|
libnm-core/nm-keyfile-internal.h | 2 +
|
||
|
libnm-core/nm-keyfile-reader.c | 9 +++
|
||
|
libnm-core/nm-keyfile-writer.c | 14 +++++
|
||
|
libnm-core/nm-setting-8021x.c | 67 ++++++++++++++++++++++-
|
||
|
libnm-core/nm-setting-8021x.h | 5 +-
|
||
|
libnm-util/libnm-util.ver | 1 +
|
||
|
libnm-util/nm-setting-8021x.c | 51 ++++++++++++++++-
|
||
|
libnm-util/nm-setting-8021x.h | 6 +-
|
||
|
src/settings/plugins/ifnet/connection_parser.c | 76 +++++++++++++++++++++-----
|
||
|
src/settings/plugins/keyfile/writer.c | 7 ++-
|
||
|
10 files changed, 216 insertions(+), 22 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h
|
||
|
index f4bb079..9b28ea6 100644
|
||
|
--- a/libnm-core/nm-keyfile-internal.h
|
||
|
+++ b/libnm-core/nm-keyfile-internal.h
|
||
|
@@ -33,6 +33,7 @@
|
||
|
|
||
|
#define NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB "data:;base64,"
|
||
|
#define NM_KEYFILE_CERT_SCHEME_PREFIX_PATH "file://"
|
||
|
+#define NM_KEYFILE_CERT_SCHEME_PREFIX_HASH "hash://server/sha256/"
|
||
|
|
||
|
char *nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
|
||
|
gconstpointer pdata,
|
||
|
@@ -148,6 +149,7 @@ typedef struct {
|
||
|
NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
|
||
|
NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
|
||
|
const char * (*path_func) (NMSetting8021x *setting);
|
||
|
+ const char * (*hash_func) (NMSetting8021x *setting);
|
||
|
GBytes * (*blob_func) (NMSetting8021x *setting);
|
||
|
} NMKeyfileWriteTypeDataCert;
|
||
|
|
||
|
diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c
|
||
|
index 353804f..94492cd 100644
|
||
|
--- a/libnm-core/nm-keyfile-reader.c
|
||
|
+++ b/libnm-core/nm-keyfile-reader.c
|
||
|
@@ -881,6 +881,15 @@ handle_as_scheme (KeyfileReaderInfo *info, GBytes *bytes, NMSetting *setting, co
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
+
|
||
|
+ if ( data_len >= STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_HASH)
|
||
|
+ && g_str_has_prefix (data, NM_KEYFILE_CERT_SCHEME_PREFIX_HASH)) {
|
||
|
+ if (nm_setting_802_1x_check_cert_scheme (data, data_len + 1, NULL) == NM_SETTING_802_1X_CK_SCHEME_HASH) {
|
||
|
+ g_object_set (setting, key, bytes, NULL);
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
if ( data_len > STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)
|
||
|
&& g_str_has_prefix (data, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) {
|
||
|
const char *cdata = data + STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB);
|
||
|
diff --git a/libnm-core/nm-keyfile-writer.c b/libnm-core/nm-keyfile-writer.c
|
||
|
index ff433b2..c9ce926 100644
|
||
|
--- a/libnm-core/nm-keyfile-writer.c
|
||
|
+++ b/libnm-core/nm-keyfile-writer.c
|
||
|
@@ -362,6 +362,7 @@ typedef struct ObjectType {
|
||
|
NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
|
||
|
NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
|
||
|
const char * (*path_func) (NMSetting8021x *setting);
|
||
|
+ const char * (*hash_func) (NMSetting8021x *setting);
|
||
|
GBytes * (*blob_func) (NMSetting8021x *setting);
|
||
|
} ObjectType;
|
||
|
|
||
|
@@ -371,6 +372,7 @@ static const ObjectType objtypes[10] = {
|
||
|
nm_setting_802_1x_get_ca_cert_scheme,
|
||
|
NULL,
|
||
|
nm_setting_802_1x_get_ca_cert_path,
|
||
|
+ nm_setting_802_1x_get_ca_cert_hash,
|
||
|
nm_setting_802_1x_get_ca_cert_blob },
|
||
|
|
||
|
{ NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||
|
@@ -378,6 +380,7 @@ static const ObjectType objtypes[10] = {
|
||
|
nm_setting_802_1x_get_phase2_ca_cert_scheme,
|
||
|
NULL,
|
||
|
nm_setting_802_1x_get_phase2_ca_cert_path,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_phase2_ca_cert_blob },
|
||
|
|
||
|
{ NM_SETTING_802_1X_CLIENT_CERT,
|
||
|
@@ -385,6 +388,7 @@ static const ObjectType objtypes[10] = {
|
||
|
nm_setting_802_1x_get_client_cert_scheme,
|
||
|
NULL,
|
||
|
nm_setting_802_1x_get_client_cert_path,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_client_cert_blob },
|
||
|
|
||
|
{ NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||
|
@@ -392,6 +396,7 @@ static const ObjectType objtypes[10] = {
|
||
|
nm_setting_802_1x_get_phase2_client_cert_scheme,
|
||
|
NULL,
|
||
|
nm_setting_802_1x_get_phase2_client_cert_path,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_phase2_client_cert_blob },
|
||
|
|
||
|
{ NM_SETTING_802_1X_PRIVATE_KEY,
|
||
|
@@ -399,6 +404,7 @@ static const ObjectType objtypes[10] = {
|
||
|
nm_setting_802_1x_get_private_key_scheme,
|
||
|
nm_setting_802_1x_get_private_key_format,
|
||
|
nm_setting_802_1x_get_private_key_path,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_private_key_blob },
|
||
|
|
||
|
{ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||
|
@@ -406,6 +412,7 @@ static const ObjectType objtypes[10] = {
|
||
|
nm_setting_802_1x_get_phase2_private_key_scheme,
|
||
|
nm_setting_802_1x_get_phase2_private_key_format,
|
||
|
nm_setting_802_1x_get_phase2_private_key_path,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_phase2_private_key_blob },
|
||
|
|
||
|
{ NULL },
|
||
|
@@ -454,6 +461,12 @@ cert_writer_default (NMConnection *connection,
|
||
|
nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, path);
|
||
|
g_free (tmp);
|
||
|
g_free (path_free);
|
||
|
+ } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_HASH) {
|
||
|
+ const char *hash;
|
||
|
+ hash = cert_data->hash_func (cert_data->setting);
|
||
|
+ g_assert (hash);
|
||
|
+
|
||
|
+ nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, hash);
|
||
|
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||
|
GBytes *blob;
|
||
|
const guint8 *blob_data;
|
||
|
@@ -506,6 +519,7 @@ cert_writer (KeyfileWriterInfo *info,
|
||
|
type_data.scheme_func = objtype->scheme_func;
|
||
|
type_data.format_func = objtype->format_func;
|
||
|
type_data.path_func = objtype->path_func;
|
||
|
+ type_data.hash_func = objtype->hash_func;
|
||
|
type_data.blob_func = objtype->blob_func;
|
||
|
|
||
|
if (info->handler) {
|
||
|
diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c
|
||
|
index d53ae43..b68e119 100644
|
||
|
--- a/libnm-core/nm-setting-8021x.c
|
||
|
+++ b/libnm-core/nm-setting-8021x.c
|
||
|
@@ -480,6 +480,28 @@ nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError *
|
||
|
}
|
||
|
|
||
|
return NM_SETTING_802_1X_CK_SCHEME_PATH;
|
||
|
+
|
||
|
+ } else if ( length >= STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_HASH)
|
||
|
+ && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_HASH, STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_HASH))) {
|
||
|
+ gsize hash_length = STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_HASH) + 64;
|
||
|
+
|
||
|
+ if (data[length - 1] != '\0') {
|
||
|
+ g_set_error_literal (error,
|
||
|
+ NM_CONNECTION_ERROR,
|
||
|
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||
|
+ _("Cert Hash is not NUL terminated"));
|
||
|
+ return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (length != (hash_length + 1)) {
|
||
|
+ g_set_error_literal (error,
|
||
|
+ NM_CONNECTION_ERROR,
|
||
|
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||
|
+ _("Cert Hash is not a SHA256 hash"));
|
||
|
+ return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||
|
+ }
|
||
|
+
|
||
|
+ return NM_SETTING_802_1X_CK_SCHEME_HASH;
|
||
|
}
|
||
|
|
||
|
return NM_SETTING_802_1X_CK_SCHEME_BLOB;
|
||
|
@@ -520,7 +542,8 @@ load_and_verify_certificate (const char *cert_path,
|
||
|
*
|
||
|
* 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().
|
||
|
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path();
|
||
|
+ * if %NM_SETTING_802_1X_CK_SCHEME_HASH, use nm_setting_802_1x_get_ca_cert_hash().
|
||
|
*
|
||
|
* Returns: scheme used to store the CA certificate (blob or path)
|
||
|
**/
|
||
|
@@ -586,6 +609,34 @@ nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting)
|
||
|
return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * nm_setting_802_1x_get_ca_cert_hash:
|
||
|
+ * @setting: the #NMSetting8021x
|
||
|
+ *
|
||
|
+ * Returns the CA certificate path if the CA certificate is stored using the
|
||
|
+ * %NM_SETTING_802_1X_CK_SCHEME_HASH 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: hash of the RADIUS server
|
||
|
+ **/
|
||
|
+const char *
|
||
|
+nm_setting_802_1x_get_ca_cert_hash (NMSetting8021x *setting)
|
||
|
+{
|
||
|
+ NMSetting8021xCKScheme scheme;
|
||
|
+ gconstpointer data;
|
||
|
+
|
||
|
+ 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_HASH, NULL);
|
||
|
+
|
||
|
+ data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL);
|
||
|
+ return (const char *)data;
|
||
|
+}
|
||
|
+
|
||
|
static GBytes *
|
||
|
path_to_scheme_value (const char *path)
|
||
|
{
|
||
|
@@ -640,7 +691,8 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||
|
if (cert_path) {
|
||
|
g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
|
||
|
g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|
||
|
- || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
|
||
|
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_HASH,
|
||
|
FALSE);
|
||
|
}
|
||
|
|
||
|
@@ -656,6 +708,17 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_HASH) {
|
||
|
+ int length = strlen (cert_path);
|
||
|
+ if ( length == (STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_HASH) + 64)
|
||
|
+ && !g_str_has_prefix (cert_path, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_HASH))
|
||
|
+ return FALSE;
|
||
|
+ data = g_byte_array_sized_new (length + 1);
|
||
|
+ g_byte_array_append (data, (guint8 *) cert_path, length + 1);
|
||
|
+ priv->ca_cert = g_byte_array_free_to_bytes (data);
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+
|
||
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||
|
if (data) {
|
||
|
/* wpa_supplicant can only use raw x509 CA certs */
|
||
|
diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h
|
||
|
index 3099fbd..82be606 100644
|
||
|
--- a/libnm-core/nm-setting-8021x.h
|
||
|
+++ b/libnm-core/nm-setting-8021x.h
|
||
|
@@ -32,6 +32,7 @@
|
||
|
G_BEGIN_DECLS
|
||
|
|
||
|
#define NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH "file://"
|
||
|
+#define NM_SETTING_802_1X_CERT_SCHEME_PREFIX_HASH "hash://server/sha256/"
|
||
|
|
||
|
/**
|
||
|
* NMSetting8021xCKFormat:
|
||
|
@@ -68,7 +69,8 @@ typedef enum { /*< underscore_name=nm_setting_802_1x_ck_format >*/
|
||
|
typedef enum { /*< underscore_name=nm_setting_802_1x_ck_scheme >*/
|
||
|
NM_SETTING_802_1X_CK_SCHEME_UNKNOWN = 0,
|
||
|
NM_SETTING_802_1X_CK_SCHEME_BLOB,
|
||
|
- NM_SETTING_802_1X_CK_SCHEME_PATH
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_HASH
|
||
|
} NMSetting8021xCKScheme;
|
||
|
|
||
|
|
||
|
@@ -169,6 +171,7 @@ const char * nm_setting_802_1x_get_phase2_ca_path (NMSetting8
|
||
|
NMSetting8021xCKScheme nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting);
|
||
|
GBytes * nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting);
|
||
|
const char * nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting);
|
||
|
+const char * nm_setting_802_1x_get_ca_cert_hash (NMSetting8021x *setting);
|
||
|
gboolean nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||
|
const char *cert_path,
|
||
|
NMSetting8021xCKScheme scheme,
|
||
|
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
|
||
|
index 9d78e50..6c66e22 100644
|
||
|
--- a/libnm-util/libnm-util.ver
|
||
|
+++ b/libnm-util/libnm-util.ver
|
||
|
@@ -127,6 +127,7 @@ global:
|
||
|
nm_setting_802_1x_get_anonymous_identity;
|
||
|
nm_setting_802_1x_get_ca_cert_blob;
|
||
|
nm_setting_802_1x_get_ca_cert_path;
|
||
|
+ nm_setting_802_1x_get_ca_cert_hash;
|
||
|
nm_setting_802_1x_get_ca_cert_scheme;
|
||
|
nm_setting_802_1x_get_ca_path;
|
||
|
nm_setting_802_1x_get_client_cert_blob;
|
||
|
diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c
|
||
|
index 678d70a..87cf948 100644
|
||
|
--- a/libnm-util/nm-setting-8021x.c
|
||
|
+++ b/libnm-util/nm-setting-8021x.c
|
||
|
@@ -65,6 +65,7 @@
|
||
|
**/
|
||
|
|
||
|
#define SCHEME_PATH "file://"
|
||
|
+#define SCHEME_HASH "hash://server/sha256/"
|
||
|
|
||
|
/**
|
||
|
* nm_setting_802_1x_error_quark:
|
||
|
@@ -444,6 +445,13 @@ get_cert_scheme (GByteArray *array)
|
||
|
&& g_utf8_validate ((const char *) &array->data[STRLEN (SCHEME_PATH)], array->len - (STRLEN (SCHEME_PATH) + 1), NULL))
|
||
|
return NM_SETTING_802_1X_CK_SCHEME_PATH;
|
||
|
return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||
|
+ } else if ( array->len >= STRLEN (SCHEME_HASH)
|
||
|
+ && !memcmp (array->data, SCHEME_HASH, STRLEN (SCHEME_HASH))) {
|
||
|
+ if ( array->len > STRLEN (SCHEME_HASH) + 1
|
||
|
+ && array->data[array->len - 1] == '\0'
|
||
|
+ && array->len == (STRLEN (SCHEME_HASH) + 64 + 1))
|
||
|
+ return NM_SETTING_802_1X_CK_SCHEME_HASH;
|
||
|
+ return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
|
||
|
}
|
||
|
|
||
|
return NM_SETTING_802_1X_CK_SCHEME_BLOB;
|
||
|
@@ -483,7 +491,8 @@ load_and_verify_certificate (const char *cert_path,
|
||
|
*
|
||
|
* 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().
|
||
|
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path();
|
||
|
+ * if %NM_SETTING_802_1X_CK_SCHEME_HASH, use nm_setting_802_1x_get_ca_cert_hash().
|
||
|
*
|
||
|
* Returns: scheme used to store the CA certificate (blob or path)
|
||
|
**/
|
||
|
@@ -547,6 +556,32 @@ nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting)
|
||
|
return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert->data + strlen (SCHEME_PATH));
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * nm_setting_802_1x_get_ca_cert_hash:
|
||
|
+ * @setting: the #NMSetting8021x
|
||
|
+ *
|
||
|
+ * Returns the CA certificate path if the CA certificate is stored using the
|
||
|
+ * %NM_SETTING_802_1X_CK_SCHEME_HASH 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: hash of the RADIUS server
|
||
|
+ **/
|
||
|
+const char *
|
||
|
+nm_setting_802_1x_get_ca_cert_hash (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_HASH, NULL);
|
||
|
+
|
||
|
+ return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert->data);
|
||
|
+}
|
||
|
+
|
||
|
static GByteArray *
|
||
|
path_to_scheme_value (const char *path)
|
||
|
{
|
||
|
@@ -600,7 +635,8 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||
|
if (cert_path) {
|
||
|
g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
|
||
|
g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|
||
|
- || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
|
||
|
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_HASH,
|
||
|
FALSE);
|
||
|
}
|
||
|
|
||
|
@@ -620,6 +656,17 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_HASH) {
|
||
|
+ int length = strlen (cert_path);
|
||
|
+ if ( length == (strlen (SCHEME_HASH) + 64)
|
||
|
+ && !g_str_has_prefix (cert_path, SCHEME_HASH))
|
||
|
+ return FALSE;
|
||
|
+ data = g_byte_array_sized_new (length + 1);
|
||
|
+ g_byte_array_append (data, (guint8 *) cert_path, length + 1);
|
||
|
+ priv->ca_cert = data;
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+
|
||
|
data = load_and_verify_certificate (cert_path, scheme, &format, error);
|
||
|
if (data) {
|
||
|
/* wpa_supplicant can only use raw x509 CA certs */
|
||
|
diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h
|
||
|
index 62b4390..42c7035 100644
|
||
|
--- a/libnm-util/nm-setting-8021x.h
|
||
|
+++ b/libnm-util/nm-setting-8021x.h
|
||
|
@@ -54,6 +54,8 @@ typedef enum { /*< underscore_name=nm_setting_802_1x_ck_format >*/
|
||
|
* item data
|
||
|
* @NM_SETTING_802_1X_CK_SCHEME_PATH: certificate or key is stored as a path
|
||
|
* to a file containing the certificate or key data
|
||
|
+ * @NM_SETTING_802_1X_CK_SCHEME_HASH: certificate or key is stored as a path
|
||
|
+ * of the CA server hash
|
||
|
*
|
||
|
* #NMSetting8021xCKScheme values indicate how a certificate or private key is
|
||
|
* stored in the setting properties, either as a blob of the item's data, or as
|
||
|
@@ -62,7 +64,8 @@ typedef enum { /*< underscore_name=nm_setting_802_1x_ck_format >*/
|
||
|
typedef enum { /*< underscore_name=nm_setting_802_1x_ck_scheme >*/
|
||
|
NM_SETTING_802_1X_CK_SCHEME_UNKNOWN = 0,
|
||
|
NM_SETTING_802_1X_CK_SCHEME_BLOB,
|
||
|
- NM_SETTING_802_1X_CK_SCHEME_PATH
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_HASH
|
||
|
} NMSetting8021xCKScheme;
|
||
|
|
||
|
|
||
|
@@ -184,6 +187,7 @@ const char * nm_setting_802_1x_get_phase2_ca_path (NMSetting8
|
||
|
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);
|
||
|
+const char * nm_setting_802_1x_get_ca_cert_hash (NMSetting8021x *setting);
|
||
|
gboolean nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
|
||
|
const char *cert_path,
|
||
|
NMSetting8021xCKScheme scheme,
|
||
|
diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
|
||
|
index 888ee58..5481963 100644
|
||
|
--- a/src/settings/plugins/ifnet/connection_parser.c
|
||
|
+++ b/src/settings/plugins/ifnet/connection_parser.c
|
||
|
@@ -37,6 +37,8 @@
|
||
|
#include "connection_parser.h"
|
||
|
#include "nm-ifnet-connection.h"
|
||
|
|
||
|
+#define SCHEME_HASH "hash://server/sha256/"
|
||
|
+
|
||
|
static char *
|
||
|
connection_id_from_ifnet_name (const char *conn_name)
|
||
|
{
|
||
|
@@ -193,11 +195,18 @@ eap_tls_reader (const char *eap_method,
|
||
|
NULL, error))
|
||
|
goto done;
|
||
|
} else {
|
||
|
- if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
- ca_cert,
|
||
|
- NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
- NULL, error))
|
||
|
- goto done;
|
||
|
+ if (g_str_has_prefix (ca_cert, SCHEME_HASH))
|
||
|
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
+ ca_cert,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_HASH,
|
||
|
+ NULL, error))
|
||
|
+ goto done;
|
||
|
+ else
|
||
|
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
+ ca_cert,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
+ NULL, error))
|
||
|
+ goto done;
|
||
|
}
|
||
|
} else {
|
||
|
nm_log_warn (LOGD_SETTINGS, " missing %s for EAP method '%s'; this is insecure!",
|
||
|
@@ -302,11 +311,18 @@ eap_peap_reader (const char *eap_method,
|
||
|
|
||
|
ca_cert = get_cert (ssid, "ca_cert", basepath);
|
||
|
if (ca_cert) {
|
||
|
- if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
- ca_cert,
|
||
|
- NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
- NULL, error))
|
||
|
- goto done;
|
||
|
+ if (g_str_has_prefix (ca_cert, SCHEME_HASH))
|
||
|
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
+ ca_cert,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_HASH,
|
||
|
+ NULL, error))
|
||
|
+ goto done;
|
||
|
+ else
|
||
|
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
+ ca_cert,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
+ NULL, error))
|
||
|
+ goto done;
|
||
|
} else {
|
||
|
nm_log_warn (LOGD_SETTINGS, " missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!",
|
||
|
eap_method);
|
||
|
@@ -404,11 +420,18 @@ eap_ttls_reader (const char *eap_method,
|
||
|
/* ca cert */
|
||
|
ca_cert = get_cert (ssid, "ca_cert", basepath);
|
||
|
if (ca_cert) {
|
||
|
- if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
- ca_cert,
|
||
|
- NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
- NULL, error))
|
||
|
- goto done;
|
||
|
+ if (g_str_has_prefix (ca_cert, SCHEME_HASH))
|
||
|
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
+ ca_cert,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_HASH,
|
||
|
+ NULL, error))
|
||
|
+ goto done;
|
||
|
+ else
|
||
|
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
|
||
|
+ ca_cert,
|
||
|
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
|
||
|
+ NULL, error))
|
||
|
+ goto done;
|
||
|
} else {
|
||
|
nm_log_warn (LOGD_SETTINGS, " missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!",
|
||
|
eap_method);
|
||
|
@@ -1719,12 +1742,14 @@ error:
|
||
|
|
||
|
typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x * setting);
|
||
|
typedef const char *(*PathFunc) (NMSetting8021x * setting);
|
||
|
+typedef const char *(*HashFunc) (NMSetting8021x * setting);
|
||
|
typedef GBytes *(*BlobFunc) (NMSetting8021x * setting);
|
||
|
|
||
|
typedef struct ObjectType {
|
||
|
const char *setting_key;
|
||
|
SchemeFunc scheme_func;
|
||
|
PathFunc path_func;
|
||
|
+ HashFunc hash_func;
|
||
|
BlobFunc blob_func;
|
||
|
const char *conn_name_key;
|
||
|
const char *suffix;
|
||
|
@@ -1734,6 +1759,7 @@ 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_hash,
|
||
|
nm_setting_802_1x_get_ca_cert_blob,
|
||
|
"ca_cert",
|
||
|
"ca-cert.der"
|
||
|
@@ -1743,6 +1769,7 @@ 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,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_phase2_ca_cert_blob,
|
||
|
"ca_cert2",
|
||
|
"inner-ca-cert.der"
|
||
|
@@ -1752,6 +1779,7 @@ 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,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_client_cert_blob,
|
||
|
"client_cert",
|
||
|
"client-cert.der"
|
||
|
@@ -1761,6 +1789,7 @@ 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,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_phase2_client_cert_blob,
|
||
|
"client_cert2",
|
||
|
"inner-client-cert.der"
|
||
|
@@ -1770,6 +1799,7 @@ 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,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_private_key_blob,
|
||
|
"private_key",
|
||
|
"private-key.pem"
|
||
|
@@ -1779,6 +1809,7 @@ 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,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_phase2_private_key_blob,
|
||
|
"private_key2",
|
||
|
"inner-private-key.pem"
|
||
|
@@ -1788,6 +1819,7 @@ 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,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_private_key_blob,
|
||
|
"private_key",
|
||
|
"private-key.p12"
|
||
|
@@ -1797,6 +1829,7 @@ 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,
|
||
|
+ NULL,
|
||
|
nm_setting_802_1x_get_phase2_private_key_blob,
|
||
|
"private_key2",
|
||
|
"inner-private-key.p12"
|
||
|
@@ -1812,6 +1845,7 @@ write_object (NMSetting8021x *s_8021x,
|
||
|
NMSetting8021xCKScheme scheme;
|
||
|
const char *path = NULL;
|
||
|
GBytes *blob = NULL;
|
||
|
+ const char *hash = NULL;
|
||
|
|
||
|
g_return_val_if_fail (conn_name != NULL, FALSE);
|
||
|
g_return_val_if_fail (objtype != NULL, FALSE);
|
||
|
@@ -1829,6 +1863,9 @@ write_object (NMSetting8021x *s_8021x,
|
||
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||
|
path = (*(objtype->path_func)) (s_8021x);
|
||
|
break;
|
||
|
+ case NM_SETTING_802_1X_CK_SCHEME_HASH:
|
||
|
+ hash = (*(objtype->hash_func)) (s_8021x);
|
||
|
+ break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
@@ -1843,6 +1880,15 @@ write_object (NMSetting8021x *s_8021x,
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
+ /* If the object hash was specified, prefer that over any raw cert data that
|
||
|
+ * may have been sent.
|
||
|
+ */
|
||
|
+ if (hash) {
|
||
|
+ wpa_set_data (conn_name, (gchar *) objtype->conn_name_key,
|
||
|
+ (gchar *) hash);
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+
|
||
|
/* does not support writing encryption data now */
|
||
|
if (blob)
|
||
|
nm_log_warn (LOGD_SETTINGS, " Currently we do not support cert writing.");
|
||
|
diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c
|
||
|
index b6a8786..1d7f3ea 100644
|
||
|
--- a/src/settings/plugins/keyfile/writer.c
|
||
|
+++ b/src/settings/plugins/keyfile/writer.c
|
||
|
@@ -114,7 +114,7 @@ cert_writer (NMConnection *connection,
|
||
|
const char *setting_name = nm_setting_get_name (NM_SETTING (cert_data->setting));
|
||
|
NMSetting8021xCKScheme scheme;
|
||
|
NMSetting8021xCKFormat format;
|
||
|
- const char *path = NULL, *ext = "pem";
|
||
|
+ const char *path = NULL, *hash = NULL, *ext = "pem";
|
||
|
|
||
|
scheme = cert_data->scheme_func (cert_data->setting);
|
||
|
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||
|
@@ -159,6 +159,11 @@ cert_writer (NMConnection *connection,
|
||
|
accepted_path = tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL);
|
||
|
nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, accepted_path);
|
||
|
g_free (tmp);
|
||
|
+ } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_HASH) {
|
||
|
+ hash = cert_data->hash_func (cert_data->setting);
|
||
|
+ g_assert (hash);
|
||
|
+
|
||
|
+ nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, hash);
|
||
|
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||
|
GBytes *blob;
|
||
|
const guint8 *blob_data;
|
||
|
--
|
||
|
2.1.4
|
||
|
|
||
|
|
||
|
From 23b16038d354685923630e862dd3e260dd514983 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <chingpang@gmail.com>
|
||
|
Date: Fri, 8 Feb 2013 11:23:15 +0800
|
||
|
Subject: [PATCH 2/4] wifi: add the dbus method to probe the certificate
|
||
|
|
||
|
---
|
||
|
introspection/nm-device-wifi.xml | 23 +++++
|
||
|
src/devices/wifi/nm-device-wifi.c | 126 +++++++++++++++++++++++
|
||
|
src/devices/wifi/nm-device-wifi.h | 1 +
|
||
|
src/supplicant-manager/nm-supplicant-config.c | 25 +++++
|
||
|
src/supplicant-manager/nm-supplicant-config.h | 2 +
|
||
|
src/supplicant-manager/nm-supplicant-interface.c | 11 ++
|
||
|
src/supplicant-manager/nm-supplicant-interface.h | 5 +
|
||
|
7 files changed, 193 insertions(+)
|
||
|
|
||
|
diff --git a/introspection/nm-device-wifi.xml b/introspection/nm-device-wifi.xml
|
||
|
index d1c5313..01b2ac0 100644
|
||
|
--- a/introspection/nm-device-wifi.xml
|
||
|
+++ b/introspection/nm-device-wifi.xml
|
||
|
@@ -45,6 +45,18 @@
|
||
|
</tp:docstring>
|
||
|
</method>
|
||
|
|
||
|
+ <method name="ProbeCert">
|
||
|
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_device_probe_cert"/>
|
||
|
+ <arg name="ssid" type="ay" direction="in">
|
||
|
+ <tp:docstring>
|
||
|
+ The SSID of the AP to be probed
|
||
|
+ </tp:docstring>
|
||
|
+ </arg>
|
||
|
+ <tp:docstring>
|
||
|
+ Probe the certificate of the RADIUS server.
|
||
|
+ </tp:docstring>
|
||
|
+ </method>
|
||
|
+
|
||
|
<property name="HwAddress" type="s" access="read">
|
||
|
<tp:docstring>
|
||
|
The active hardware address of the device.
|
||
|
@@ -120,6 +132,17 @@
|
||
|
</tp:docstring>
|
||
|
</signal>
|
||
|
|
||
|
+ <signal name="CertReceived">
|
||
|
+ <arg name="cert" type="a{sv}" tp:type="String_Variant_Map">
|
||
|
+ <tp:docstring>
|
||
|
+ The certificate of the RADIUS server
|
||
|
+ </tp:docstring>
|
||
|
+ </arg>
|
||
|
+ <tp:docstring>
|
||
|
+ Emitted when wpa_supplicant replies the certificate of the RADIUS server.
|
||
|
+ </tp:docstring>
|
||
|
+ </signal>
|
||
|
+
|
||
|
<tp:flags name="NM_802_11_DEVICE_CAP" type="u">
|
||
|
<tp:docstring>
|
||
|
Flags describing the capabilities of a wireless device.
|
||
|
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
|
||
|
index 2e116f8..45945ed 100644
|
||
|
--- a/src/devices/wifi/nm-device-wifi.c
|
||
|
+++ b/src/devices/wifi/nm-device-wifi.c
|
||
|
@@ -60,6 +60,9 @@
|
||
|
static gboolean impl_device_get_access_points (NMDeviceWifi *device,
|
||
|
GPtrArray **aps,
|
||
|
GError **err);
|
||
|
+static gboolean impl_device_probe_cert (NMDeviceWifi *device,
|
||
|
+ GByteArray *ssid,
|
||
|
+ GError **err);
|
||
|
|
||
|
static gboolean impl_device_get_all_access_points (NMDeviceWifi *device,
|
||
|
GPtrArray **aps,
|
||
|
@@ -103,6 +106,7 @@ enum {
|
||
|
ACCESS_POINT_ADDED,
|
||
|
ACCESS_POINT_REMOVED,
|
||
|
SCANNING_ALLOWED,
|
||
|
+ CERT_RECEIVED,
|
||
|
|
||
|
LAST_SIGNAL
|
||
|
};
|
||
|
@@ -128,6 +132,7 @@ struct _NMDeviceWifiPrivate {
|
||
|
NMSupplicantManager *sup_mgr;
|
||
|
NMSupplicantInterface *sup_iface;
|
||
|
guint sup_timeout_id; /* supplicant association timeout */
|
||
|
+ guint sup_cert_id;
|
||
|
|
||
|
gboolean ssid_found;
|
||
|
NM80211Mode mode;
|
||
|
@@ -1658,6 +1663,118 @@ try_fill_ssid_for_hidden_ap (NMAccessPoint *ap)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+supplicant_iface_certification_cb (NMSupplicantInterface * iface,
|
||
|
+ GVariant *cert,
|
||
|
+ NMDeviceWifi * self)
|
||
|
+{
|
||
|
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||
|
+ GVariantIter *iter;
|
||
|
+ GVariant *variant;
|
||
|
+ gchar *str, *subject = NULL, *hash = NULL;
|
||
|
+ guint depth;
|
||
|
+ gboolean got_depth = FALSE;
|
||
|
+ GHashTable *cert_table;
|
||
|
+
|
||
|
+ g_variant_get (cert, "(a{sv})", &iter);
|
||
|
+ while (g_variant_iter_loop (iter, "{sv}", &str, &variant)) {
|
||
|
+ if (g_strcmp0 (str, "depth") == 0) {
|
||
|
+ depth = g_variant_get_uint32 (variant);
|
||
|
+ got_depth = TRUE;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (g_strcmp0 (str, "subject") == 0)
|
||
|
+ g_variant_get (variant, "s", &subject);
|
||
|
+
|
||
|
+ if (g_strcmp0 (str, "cert_hash") == 0)
|
||
|
+ g_variant_get (variant, "s", &hash);
|
||
|
+
|
||
|
+ }
|
||
|
+ g_variant_iter_free (iter);
|
||
|
+
|
||
|
+ if (!got_depth) {
|
||
|
+ nm_log_dbg (LOGD_WIFI_SCAN, "Depth was not set");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!subject) {
|
||
|
+ nm_log_dbg (LOGD_WIFI_SCAN, "no subject");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!hash) {
|
||
|
+ nm_log_dbg (LOGD_WIFI_SCAN, "no cert hash");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ nm_log_info (LOGD_WIFI_SCAN, "Got Server Certificate %u, subject %s, hash %s",
|
||
|
+ depth, subject, hash);
|
||
|
+
|
||
|
+ if (depth != 0)
|
||
|
+ return;
|
||
|
+
|
||
|
+ cert_table = value_hash_create ();
|
||
|
+ if (!cert_table) {
|
||
|
+ nm_log_warn (LOGD_WIFI_SCAN, "Failed to new a cert table");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ value_hash_add_uint (cert_table, "depth", depth);
|
||
|
+ value_hash_add_str (cert_table, "subject", subject);
|
||
|
+ value_hash_add_str (cert_table, "cert_hash", hash);
|
||
|
+
|
||
|
+ g_signal_emit (self, signals[CERT_RECEIVED], 0, cert_table);
|
||
|
+
|
||
|
+ g_hash_table_unref (cert_table);
|
||
|
+
|
||
|
+ if (priv->sup_cert_id > 0) {
|
||
|
+ g_signal_handler_disconnect (priv->sup_iface, priv->sup_cert_id);
|
||
|
+ priv->sup_cert_id = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ nm_supplicant_interface_disconnect (iface);
|
||
|
+}
|
||
|
+
|
||
|
+static gboolean
|
||
|
+impl_device_probe_cert (NMDeviceWifi *self,
|
||
|
+ GByteArray *ssid,
|
||
|
+ GError **err)
|
||
|
+{
|
||
|
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||
|
+ NMSupplicantConfig *config = NULL;
|
||
|
+ guint id;
|
||
|
+ gboolean ret = FALSE;
|
||
|
+
|
||
|
+ config = nm_supplicant_config_new_probe (ssid);
|
||
|
+ if (!config)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ /* Hook up signal handler to capture certification signal */
|
||
|
+ id = g_signal_connect (priv->sup_iface,
|
||
|
+ NM_SUPPLICANT_INTERFACE_CERTIFICATION,
|
||
|
+ G_CALLBACK (supplicant_iface_certification_cb),
|
||
|
+ self);
|
||
|
+ priv->sup_cert_id = id;
|
||
|
+
|
||
|
+ if (!nm_supplicant_interface_set_config (priv->sup_iface, config))
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ ret = TRUE;
|
||
|
+
|
||
|
+error:
|
||
|
+ if (!ret) {
|
||
|
+ g_set_error_literal (err,
|
||
|
+ NM_DEVICE_ERROR,
|
||
|
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||
|
+ _("Couldn't probe RADIUS server certificate"));
|
||
|
+ if (priv->sup_cert_id) {
|
||
|
+ g_signal_handler_disconnect (priv->sup_iface, priv->sup_cert_id);
|
||
|
+ priv->sup_cert_id = 0;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* merge_scanned_ap
|
||
|
*
|
||
|
@@ -3359,6 +3476,15 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
|
||
|
scanning_allowed_accumulator, NULL, NULL,
|
||
|
G_TYPE_BOOLEAN, 0);
|
||
|
|
||
|
+ signals[CERT_RECEIVED] =
|
||
|
+ g_signal_new ("cert-received",
|
||
|
+ G_OBJECT_CLASS_TYPE (object_class),
|
||
|
+ G_SIGNAL_RUN_FIRST,
|
||
|
+ G_STRUCT_OFFSET (NMDeviceWifiClass, cert_received),
|
||
|
+ NULL, NULL,
|
||
|
+ g_cclosure_marshal_VOID__BOXED,
|
||
|
+ G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT);
|
||
|
+
|
||
|
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
||
|
G_TYPE_FROM_CLASS (klass),
|
||
|
&dbus_glib_nm_device_wifi_object_info);
|
||
|
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
|
||
|
index bcba91d..fcf91c9 100644
|
||
|
--- a/src/devices/wifi/nm-device-wifi.h
|
||
|
+++ b/src/devices/wifi/nm-device-wifi.h
|
||
|
@@ -70,6 +70,7 @@ struct _NMDeviceWifiClass
|
||
|
void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap);
|
||
|
void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap);
|
||
|
gboolean (*scanning_allowed) (NMDeviceWifi *device);
|
||
|
+ void (*cert_received) (NMDeviceWifi *device, GHashTable *cert);
|
||
|
};
|
||
|
|
||
|
|
||
|
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
|
||
|
index b78a24d..8ab7b7d 100644
|
||
|
--- a/src/supplicant-manager/nm-supplicant-config.c
|
||
|
+++ b/src/supplicant-manager/nm-supplicant-config.c
|
||
|
@@ -160,6 +160,25 @@ nm_supplicant_config_add_option (NMSupplicantConfig *self,
|
||
|
return nm_supplicant_config_add_option_with_type (self, key, value, len, TYPE_INVALID, secret);
|
||
|
}
|
||
|
|
||
|
+NMSupplicantConfig *
|
||
|
+nm_supplicant_config_new_probe (const GByteArray *ssid)
|
||
|
+{
|
||
|
+ NMSupplicantConfig *probe_config;
|
||
|
+
|
||
|
+ if (!ssid)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ probe_config = (NMSupplicantConfig *)g_object_new (NM_TYPE_SUPPLICANT_CONFIG, NULL);
|
||
|
+
|
||
|
+ nm_supplicant_config_add_option (probe_config, "ssid", (char *)ssid->data, ssid->len, FALSE);
|
||
|
+ nm_supplicant_config_add_option (probe_config, "key_mgmt", "WPA-EAP", -1, FALSE);
|
||
|
+ nm_supplicant_config_add_option (probe_config, "eap", "TTLS PEAP TLS", -1, FALSE);
|
||
|
+ nm_supplicant_config_add_option (probe_config, "identity", " ", -1, FALSE);
|
||
|
+ nm_supplicant_config_add_option (probe_config, "ca_cert", "probe://", -1, FALSE);
|
||
|
+
|
||
|
+ return probe_config;
|
||
|
+}
|
||
|
+
|
||
|
static gboolean
|
||
|
nm_supplicant_config_add_blob (NMSupplicantConfig *self,
|
||
|
const char *key,
|
||
|
@@ -911,6 +930,12 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
|
||
|
if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
|
||
|
return FALSE;
|
||
|
break;
|
||
|
+ case NM_SETTING_802_1X_CK_SCHEME_HASH:
|
||
|
+ path = nm_setting_802_1x_get_ca_cert_hash (setting);
|
||
|
+ if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
|
||
|
+ return FALSE;
|
||
|
+ break;
|
||
|
+
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h
|
||
|
index 3324f63..3491fca 100644
|
||
|
--- a/src/supplicant-manager/nm-supplicant-config.h
|
||
|
+++ b/src/supplicant-manager/nm-supplicant-config.h
|
||
|
@@ -52,6 +52,8 @@ GType nm_supplicant_config_get_type (void);
|
||
|
|
||
|
NMSupplicantConfig *nm_supplicant_config_new (void);
|
||
|
|
||
|
+NMSupplicantConfig *nm_supplicant_config_new_probe (const GByteArray *ssid);
|
||
|
+
|
||
|
guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
|
||
|
|
||
|
void nm_supplicant_config_set_ap_scan (NMSupplicantConfig *self,
|
||
|
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
|
||
|
index e9775a1..dab1047 100644
|
||
|
--- a/src/supplicant-manager/nm-supplicant-interface.c
|
||
|
+++ b/src/supplicant-manager/nm-supplicant-interface.c
|
||
|
@@ -55,6 +55,7 @@ enum {
|
||
|
SCAN_DONE, /* wifi scan is complete */
|
||
|
CONNECTION_ERROR, /* an error occurred during a connection request */
|
||
|
CREDENTIALS_REQUEST, /* 802.1x identity or password requested */
|
||
|
+ CERTIFICATION, /* a RADIUS server certificate was received */
|
||
|
LAST_SIGNAL
|
||
|
};
|
||
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||
|
@@ -527,6 +528,8 @@ signal_cb (GDBusProxy *proxy,
|
||
|
g_variant_get (args, "(&o&s&s)", &path, &field, &message);
|
||
|
if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path))
|
||
|
g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message);
|
||
|
+ } else if (MATCH_SIGNAL (signal, "Certification", args, G_VARIANT_TYPE ("(a{sv})"))) {
|
||
|
+ g_signal_emit (self, signals[CERTIFICATION], 0, g_variant_ref_sink (args));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -1393,5 +1396,13 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
|
||
|
G_STRUCT_OFFSET (NMSupplicantInterfaceClass, credentials_request),
|
||
|
NULL, NULL, NULL,
|
||
|
G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
|
||
|
+ signals[CERTIFICATION] =
|
||
|
+ g_signal_new (NM_SUPPLICANT_INTERFACE_CERTIFICATION,
|
||
|
+ G_OBJECT_CLASS_TYPE (object_class),
|
||
|
+ G_SIGNAL_RUN_LAST,
|
||
|
+ G_STRUCT_OFFSET (NMSupplicantInterfaceClass, certification),
|
||
|
+ NULL, NULL,
|
||
|
+ g_cclosure_marshal_VOID__BOXED,
|
||
|
+ G_TYPE_NONE, 1, G_TYPE_VARIANT);
|
||
|
}
|
||
|
|
||
|
diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h
|
||
|
index 1b1139d..5328df4 100644
|
||
|
--- a/src/supplicant-manager/nm-supplicant-interface.h
|
||
|
+++ b/src/supplicant-manager/nm-supplicant-interface.h
|
||
|
@@ -62,6 +62,7 @@ enum {
|
||
|
#define NM_SUPPLICANT_INTERFACE_SCAN_DONE "scan-done"
|
||
|
#define NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR "connection-error"
|
||
|
#define NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST "credentials-request"
|
||
|
+#define NM_SUPPLICANT_INTERFACE_CERTIFICATION "certification"
|
||
|
|
||
|
typedef enum {
|
||
|
AP_SUPPORT_UNKNOWN = 0, /* Can't detect whether supported or not */
|
||
|
@@ -114,6 +115,10 @@ typedef struct {
|
||
|
void (*credentials_request) (NMSupplicantInterface *iface,
|
||
|
const char *field,
|
||
|
const char *message);
|
||
|
+
|
||
|
+ /* a RADIUS server certificate was received */
|
||
|
+ void (*certification) (NMSupplicantInterface * iface,
|
||
|
+ const GHashTable * ca_cert);
|
||
|
} NMSupplicantInterfaceClass;
|
||
|
|
||
|
|
||
|
--
|
||
|
2.1.4
|
||
|
|
||
|
|
||
|
From 2efdcb519b6b5e490193afe980593cdd228f4b55 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <chingpang@gmail.com>
|
||
|
Date: Fri, 8 Feb 2013 11:24:10 +0800
|
||
|
Subject: [PATCH 3/4] libnm-glib: add the function to probe the certificate
|
||
|
|
||
|
---
|
||
|
libnm-glib/libnm-glib.ver | 1 +
|
||
|
libnm-glib/nm-device-wifi.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
|
||
|
libnm-glib/nm-device-wifi.h | 5 +++-
|
||
|
3 files changed, 75 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
|
||
|
index 9219c4a..12ca784 100644
|
||
|
--- a/libnm-glib/libnm-glib.ver
|
||
|
+++ b/libnm-glib/libnm-glib.ver
|
||
|
@@ -200,6 +200,7 @@ global:
|
||
|
nm_device_wifi_get_type;
|
||
|
nm_device_wifi_new;
|
||
|
nm_device_wifi_request_scan_simple;
|
||
|
+ nm_device_wifi_probe_cert;
|
||
|
nm_device_wimax_error_get_type;
|
||
|
nm_device_wimax_error_quark;
|
||
|
nm_device_wimax_get_active_nsp;
|
||
|
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
|
||
|
index 28609c7..977539e 100644
|
||
|
--- a/libnm-glib/nm-device-wifi.c
|
||
|
+++ b/libnm-glib/nm-device-wifi.c
|
||
|
@@ -80,6 +80,7 @@ enum {
|
||
|
enum {
|
||
|
ACCESS_POINT_ADDED,
|
||
|
ACCESS_POINT_REMOVED,
|
||
|
+ CERT_RECEIVED,
|
||
|
|
||
|
LAST_SIGNAL
|
||
|
};
|
||
|
@@ -381,6 +382,49 @@ nm_device_wifi_request_scan_simple (NMDeviceWifi *device,
|
||
|
g_hash_table_unref (options);
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * nm_device_wifi_probe_cert:
|
||
|
+ * @device: a #NMDeviceWifi
|
||
|
+ * @ssid: the ssid of the AP to probe
|
||
|
+ *
|
||
|
+ * Probe the certificate of the RADIUS server
|
||
|
+ *
|
||
|
+ * Returns: if the probe is sent or not
|
||
|
+ **/
|
||
|
+gboolean
|
||
|
+nm_device_wifi_probe_cert (NMDeviceWifi *device,
|
||
|
+ const GByteArray *ssid)
|
||
|
+{
|
||
|
+ NMDeviceWifiPrivate *priv;
|
||
|
+ GError *error = NULL;
|
||
|
+ gboolean ret;
|
||
|
+
|
||
|
+ g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE);
|
||
|
+
|
||
|
+ priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
|
||
|
+
|
||
|
+ ret = dbus_g_proxy_call (priv->proxy, "ProbeCert", &error,
|
||
|
+ DBUS_TYPE_G_UCHAR_ARRAY, ssid,
|
||
|
+ G_TYPE_INVALID,
|
||
|
+ G_TYPE_INVALID);
|
||
|
+
|
||
|
+ if (!ret) {
|
||
|
+ g_warning ("%s: error probe certificate: %s", __func__, error->message);
|
||
|
+ g_error_free (error);
|
||
|
+ return FALSE;
|
||
|
+ }
|
||
|
+
|
||
|
+ return TRUE;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+cert_received_proxy (DBusGProxy *proxy, GHashTable *cert, gpointer user_data)
|
||
|
+{
|
||
|
+ NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
|
||
|
+
|
||
|
+ g_signal_emit (self, signals[CERT_RECEIVED], 0, cert);
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
clean_up_aps (NMDeviceWifi *self, gboolean notify)
|
||
|
{
|
||
|
@@ -649,6 +693,14 @@ constructed (GObject *object)
|
||
|
G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object);
|
||
|
|
||
|
priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE_WIRELESS);
|
||
|
+
|
||
|
+ dbus_g_proxy_add_signal (priv->proxy, "CertReceived",
|
||
|
+ DBUS_TYPE_G_MAP_OF_VARIANT,
|
||
|
+ G_TYPE_INVALID);
|
||
|
+ dbus_g_proxy_connect_signal (priv->proxy, "CertReceived",
|
||
|
+ G_CALLBACK (cert_received_proxy),
|
||
|
+ object, NULL);
|
||
|
+
|
||
|
register_properties (NM_DEVICE_WIFI (object));
|
||
|
|
||
|
g_signal_connect (NM_DEVICE (object),
|
||
|
@@ -836,4 +888,22 @@ nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class)
|
||
|
g_cclosure_marshal_VOID__OBJECT,
|
||
|
G_TYPE_NONE, 1,
|
||
|
G_TYPE_OBJECT);
|
||
|
+
|
||
|
+ /**
|
||
|
+ * NMDeviceWifi::cert-received:
|
||
|
+ * @device: the wifi device that received the signal
|
||
|
+ * @subject: the subject of the RADIUS server
|
||
|
+ * @hash: the hash of the RADIUS server
|
||
|
+ *
|
||
|
+ * Notifies that a certificate of a RADIUS server is received.
|
||
|
+ **/
|
||
|
+ signals[CERT_RECEIVED] =
|
||
|
+ g_signal_new ("cert-received",
|
||
|
+ G_OBJECT_CLASS_TYPE (object_class),
|
||
|
+ G_SIGNAL_RUN_FIRST,
|
||
|
+ G_STRUCT_OFFSET (NMDeviceWifiClass, cert_received),
|
||
|
+ NULL, NULL,
|
||
|
+ g_cclosure_marshal_VOID__BOXED,
|
||
|
+ G_TYPE_NONE, 1,
|
||
|
+ G_TYPE_HASH_TABLE);
|
||
|
}
|
||
|
diff --git a/libnm-glib/nm-device-wifi.h b/libnm-glib/nm-device-wifi.h
|
||
|
index 2bb432a..ac9f8dd 100644
|
||
|
--- a/libnm-glib/nm-device-wifi.h
|
||
|
+++ b/libnm-glib/nm-device-wifi.h
|
||
|
@@ -77,6 +77,7 @@ typedef struct {
|
||
|
/* Signals */
|
||
|
void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap);
|
||
|
void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap);
|
||
|
+ void (*cert_received) (NMDeviceWifi *device, GHashTable *cert);
|
||
|
|
||
|
/* Padding for future expansion */
|
||
|
void (*_reserved1) (void);
|
||
|
@@ -84,7 +85,6 @@ typedef struct {
|
||
|
void (*_reserved3) (void);
|
||
|
void (*_reserved4) (void);
|
||
|
void (*_reserved5) (void);
|
||
|
- void (*_reserved6) (void);
|
||
|
} NMDeviceWifiClass;
|
||
|
|
||
|
GType nm_device_wifi_get_type (void);
|
||
|
@@ -110,6 +110,9 @@ void nm_device_wifi_request_scan_simple (NMDeviceWifi *
|
||
|
NMDeviceWifiRequestScanFn callback,
|
||
|
gpointer user_data);
|
||
|
|
||
|
+gboolean nm_device_wifi_probe_cert (NMDeviceWifi *device,
|
||
|
+ const GByteArray *ssid);
|
||
|
+
|
||
|
G_END_DECLS
|
||
|
|
||
|
#endif /* NM_DEVICE_WIFI_H */
|
||
|
--
|
||
|
2.1.4
|
||
|
|
||
|
|
||
|
From 77adeaeafe978934280c50543ecf3ed8dce800d1 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <chingpang@gmail.com>
|
||
|
Date: Thu, 25 Apr 2013 11:13:52 +0800
|
||
|
Subject: [PATCH 4/4] wifi: Probe the Radius server with the user credential
|
||
|
|
||
|
Some servers do not accept anonymous probe.
|
||
|
---
|
||
|
introspection/nm-device-wifi.xml | 4 +--
|
||
|
libnm-glib/nm-device-wifi.c | 14 +++++++---
|
||
|
libnm-glib/nm-device-wifi.h | 2 +-
|
||
|
src/devices/wifi/nm-device-wifi.c | 39 ++++++++++++++++++++++++---
|
||
|
src/supplicant-manager/nm-supplicant-config.c | 37 +++++++++++++++++++++----
|
||
|
src/supplicant-manager/nm-supplicant-config.h | 3 ++-
|
||
|
6 files changed, 83 insertions(+), 16 deletions(-)
|
||
|
|
||
|
diff --git a/introspection/nm-device-wifi.xml b/introspection/nm-device-wifi.xml
|
||
|
index 01b2ac0..2adb7d4 100644
|
||
|
--- a/introspection/nm-device-wifi.xml
|
||
|
+++ b/introspection/nm-device-wifi.xml
|
||
|
@@ -47,9 +47,9 @@
|
||
|
|
||
|
<method name="ProbeCert">
|
||
|
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_device_probe_cert"/>
|
||
|
- <arg name="ssid" type="ay" direction="in">
|
||
|
+ <arg name="settings" type="a{sa{sv}}" direction="in">
|
||
|
<tp:docstring>
|
||
|
- The SSID of the AP to be probed
|
||
|
+ Connection settings and properties
|
||
|
</tp:docstring>
|
||
|
</arg>
|
||
|
<tp:docstring>
|
||
|
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
|
||
|
index 977539e..ff816eb 100644
|
||
|
--- a/libnm-glib/nm-device-wifi.c
|
||
|
+++ b/libnm-glib/nm-device-wifi.c
|
||
|
@@ -385,7 +385,7 @@ nm_device_wifi_request_scan_simple (NMDeviceWifi *device,
|
||
|
/**
|
||
|
* nm_device_wifi_probe_cert:
|
||
|
* @device: a #NMDeviceWifi
|
||
|
- * @ssid: the ssid of the AP to probe
|
||
|
+ * @partial: the connection settings and properties
|
||
|
*
|
||
|
* Probe the certificate of the RADIUS server
|
||
|
*
|
||
|
@@ -393,21 +393,29 @@ nm_device_wifi_request_scan_simple (NMDeviceWifi *device,
|
||
|
**/
|
||
|
gboolean
|
||
|
nm_device_wifi_probe_cert (NMDeviceWifi *device,
|
||
|
- const GByteArray *ssid)
|
||
|
+ NMConnection *partial)
|
||
|
{
|
||
|
NMDeviceWifiPrivate *priv;
|
||
|
+ GHashTable *hash = NULL;
|
||
|
GError *error = NULL;
|
||
|
gboolean ret;
|
||
|
|
||
|
g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE);
|
||
|
+ g_return_val_if_fail (partial, FALSE);
|
||
|
|
||
|
priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
|
||
|
|
||
|
+ hash = nm_connection_to_hash (partial, NM_SETTING_HASH_FLAG_ALL);
|
||
|
+ if (hash == NULL)
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
ret = dbus_g_proxy_call (priv->proxy, "ProbeCert", &error,
|
||
|
- DBUS_TYPE_G_UCHAR_ARRAY, ssid,
|
||
|
+ DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
|
||
|
G_TYPE_INVALID,
|
||
|
G_TYPE_INVALID);
|
||
|
|
||
|
+ g_hash_table_unref (hash);
|
||
|
+
|
||
|
if (!ret) {
|
||
|
g_warning ("%s: error probe certificate: %s", __func__, error->message);
|
||
|
g_error_free (error);
|
||
|
diff --git a/libnm-glib/nm-device-wifi.h b/libnm-glib/nm-device-wifi.h
|
||
|
index ac9f8dd..c69e64c 100644
|
||
|
--- a/libnm-glib/nm-device-wifi.h
|
||
|
+++ b/libnm-glib/nm-device-wifi.h
|
||
|
@@ -111,7 +111,7 @@ void nm_device_wifi_request_scan_simple (NMDeviceWifi *
|
||
|
gpointer user_data);
|
||
|
|
||
|
gboolean nm_device_wifi_probe_cert (NMDeviceWifi *device,
|
||
|
- const GByteArray *ssid);
|
||
|
+ NMConnection *partial);
|
||
|
|
||
|
G_END_DECLS
|
||
|
|
||
|
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
|
||
|
index 45945ed..a767ffb 100644
|
||
|
--- a/src/devices/wifi/nm-device-wifi.c
|
||
|
+++ b/src/devices/wifi/nm-device-wifi.c
|
||
|
@@ -50,6 +50,7 @@
|
||
|
#include "nm-setting-ip6-config.h"
|
||
|
#include "nm-platform.h"
|
||
|
#include "nm-auth-utils.h"
|
||
|
+#include "nm-core-internal.h"
|
||
|
#include "nm-settings-connection.h"
|
||
|
#include "nm-enum-types.h"
|
||
|
#include "nm-dbus-glib-types.h"
|
||
|
@@ -61,7 +62,7 @@ static gboolean impl_device_get_access_points (NMDeviceWifi *device,
|
||
|
GPtrArray **aps,
|
||
|
GError **err);
|
||
|
static gboolean impl_device_probe_cert (NMDeviceWifi *device,
|
||
|
- GByteArray *ssid,
|
||
|
+ GHashTable *settings,
|
||
|
GError **err);
|
||
|
|
||
|
static gboolean impl_device_get_all_access_points (NMDeviceWifi *device,
|
||
|
@@ -1736,16 +1737,43 @@ supplicant_iface_certification_cb (NMSupplicantInterface * iface,
|
||
|
|
||
|
static gboolean
|
||
|
impl_device_probe_cert (NMDeviceWifi *self,
|
||
|
- GByteArray *ssid,
|
||
|
+ GHashTable *settings,
|
||
|
GError **err)
|
||
|
{
|
||
|
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||
|
+ NMConnection *connection = NULL;
|
||
|
+ NMSettingWireless *setting_wifi;
|
||
|
+ GBytes *ssid;
|
||
|
+ NMSetting8021x *setting_8021x;
|
||
|
NMSupplicantConfig *config = NULL;
|
||
|
guint id;
|
||
|
gboolean ret = FALSE;
|
||
|
|
||
|
- config = nm_supplicant_config_new_probe (ssid);
|
||
|
- if (!config)
|
||
|
+ if (!settings)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ connection = nm_simple_connection_new ();
|
||
|
+ if (settings && g_hash_table_size (settings)) {
|
||
|
+ GVariant *settings_dict = nm_utils_connection_hash_to_dict (settings);
|
||
|
+
|
||
|
+ nm_connection_replace_settings (connection, settings_dict, NULL);
|
||
|
+ g_variant_unref (settings_dict);
|
||
|
+ }
|
||
|
+
|
||
|
+ setting_wifi = nm_connection_get_setting_wireless (connection);
|
||
|
+ if (setting_wifi == NULL)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ ssid = nm_setting_wireless_get_ssid (setting_wifi);
|
||
|
+ if (ssid == NULL)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ setting_8021x = nm_connection_get_setting_802_1x (connection);
|
||
|
+ if (setting_8021x == NULL)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ config = nm_supplicant_config_new_probe (ssid, setting_8021x);
|
||
|
+ if (config == NULL)
|
||
|
goto error;
|
||
|
|
||
|
/* Hook up signal handler to capture certification signal */
|
||
|
@@ -1761,6 +1789,9 @@ impl_device_probe_cert (NMDeviceWifi *self,
|
||
|
ret = TRUE;
|
||
|
|
||
|
error:
|
||
|
+ if (connection)
|
||
|
+ g_object_unref (connection);
|
||
|
+
|
||
|
if (!ret) {
|
||
|
g_set_error_literal (err,
|
||
|
NM_DEVICE_ERROR,
|
||
|
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
|
||
|
index 8ab7b7d..9cffbe1 100644
|
||
|
--- a/src/supplicant-manager/nm-supplicant-config.c
|
||
|
+++ b/src/supplicant-manager/nm-supplicant-config.c
|
||
|
@@ -161,21 +161,48 @@ nm_supplicant_config_add_option (NMSupplicantConfig *self,
|
||
|
}
|
||
|
|
||
|
NMSupplicantConfig *
|
||
|
-nm_supplicant_config_new_probe (const GByteArray *ssid)
|
||
|
+nm_supplicant_config_new_probe (GBytes *ssid, NMSetting8021x *setting)
|
||
|
{
|
||
|
NMSupplicantConfig *probe_config;
|
||
|
+ const char *identity, *password;
|
||
|
+ gboolean use_pw = FALSE;
|
||
|
+ guint32 i, num_eap;
|
||
|
+ gconstpointer data;
|
||
|
+ gsize length;
|
||
|
+
|
||
|
+ g_return_val_if_fail (ssid != NULL, NULL);
|
||
|
+ g_return_val_if_fail (setting != NULL, NULL);
|
||
|
+
|
||
|
+ data = g_bytes_get_data (ssid, &length);
|
||
|
|
||
|
- if (!ssid)
|
||
|
- return NULL;
|
||
|
+ num_eap = nm_setting_802_1x_get_num_eap_methods (setting);
|
||
|
+ for (i = 0; i < num_eap; i++) {
|
||
|
+ const char *method = nm_setting_802_1x_get_eap_method (setting, i);
|
||
|
+
|
||
|
+ if (method && (strcasecmp (method, "ttls") == 0 ||
|
||
|
+ strcasecmp (method, "peap") == 0))
|
||
|
+ use_pw = TRUE;
|
||
|
+ }
|
||
|
+
|
||
|
+ identity = nm_setting_802_1x_get_identity (setting);
|
||
|
+ if (!identity)
|
||
|
+ identity = " ";
|
||
|
|
||
|
probe_config = (NMSupplicantConfig *)g_object_new (NM_TYPE_SUPPLICANT_CONFIG, NULL);
|
||
|
|
||
|
- nm_supplicant_config_add_option (probe_config, "ssid", (char *)ssid->data, ssid->len, FALSE);
|
||
|
+ nm_supplicant_config_add_option (probe_config, "ssid", (const char *)data, length, FALSE);
|
||
|
nm_supplicant_config_add_option (probe_config, "key_mgmt", "WPA-EAP", -1, FALSE);
|
||
|
nm_supplicant_config_add_option (probe_config, "eap", "TTLS PEAP TLS", -1, FALSE);
|
||
|
- nm_supplicant_config_add_option (probe_config, "identity", " ", -1, FALSE);
|
||
|
+ nm_supplicant_config_add_option (probe_config, "identity", identity, -1, FALSE);
|
||
|
nm_supplicant_config_add_option (probe_config, "ca_cert", "probe://", -1, FALSE);
|
||
|
|
||
|
+ if (use_pw) {
|
||
|
+ password = nm_setting_802_1x_get_password(setting);
|
||
|
+ if (!password)
|
||
|
+ return NULL;
|
||
|
+ nm_supplicant_config_add_option (probe_config, "password", password, -1, TRUE);
|
||
|
+ }
|
||
|
+
|
||
|
return probe_config;
|
||
|
}
|
||
|
|
||
|
diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h
|
||
|
index 3491fca..e6149d8 100644
|
||
|
--- a/src/supplicant-manager/nm-supplicant-config.h
|
||
|
+++ b/src/supplicant-manager/nm-supplicant-config.h
|
||
|
@@ -52,7 +52,8 @@ GType nm_supplicant_config_get_type (void);
|
||
|
|
||
|
NMSupplicantConfig *nm_supplicant_config_new (void);
|
||
|
|
||
|
-NMSupplicantConfig *nm_supplicant_config_new_probe (const GByteArray *ssid);
|
||
|
+NMSupplicantConfig *nm_supplicant_config_new_probe (GBytes *ssid,
|
||
|
+ NMSetting8021x *setting);
|
||
|
|
||
|
guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
|
||
|
|
||
|
--
|
||
|
2.1.4
|
||
|
|