Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.2:ARM
NetworkManager
nm-probe-radius-server-cert.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File nm-probe-radius-server-cert.patch of Package NetworkManager
From 7f1ab67e7d78d94b28d0194e1fb70e71b70b6d21 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/3] libnm-util: allow the server hash to be the CA certificate --- libnm-util/libnm-util.ver | 1 + libnm-util/nm-setting-8021x.c | 54 ++++++++++++++++- libnm-util/nm-setting-8021x.h | 6 ++- src/settings/plugins/ifnet/connection_parser.c | 76 +++++++++++++++++++----- src/settings/plugins/keyfile/reader.c | 7 ++ src/settings/plugins/keyfile/writer.c | 14 ++++- 6 files changed, 139 insertions(+), 19 deletions(-) diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver index eb3f1f3..28cfd21 100644 --- a/libnm-util/libnm-util.ver +++ b/libnm-util/libnm-util.ver @@ -115,6 +115,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 28c0d3f..0920d73 100644 --- a/libnm-util/nm-setting-8021x.c +++ b/libnm-util/nm-setting-8021x.c @@ -64,6 +64,7 @@ **/ #define SCHEME_PATH "file://" +#define SCHEME_HASH "hash://server/sha256/" /** * nm_setting_802_1x_error_quark: @@ -388,6 +389,9 @@ get_cert_scheme (GByteArray *array) if ( (array->len > strlen (SCHEME_PATH)) && !memcmp (array->data, SCHEME_PATH, strlen (SCHEME_PATH))) return NM_SETTING_802_1X_CK_SCHEME_PATH; + else if ( (array->len > strlen (SCHEME_HASH)) + && !memcmp (array->data, SCHEME_HASH, strlen (SCHEME_HASH))) + return NM_SETTING_802_1X_CK_SCHEME_HASH; return NM_SETTING_802_1X_CK_SCHEME_BLOB; } @@ -398,7 +402,8 @@ get_cert_scheme (GByteArray *array) * * 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) **/ @@ -462,6 +467,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) { @@ -513,7 +544,8 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *self, 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); } @@ -531,6 +563,17 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *self, if (!cert_path) 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 = crypto_load_and_verify_certificate (cert_path, &format, error); if (data) { /* wpa_supplicant can only use raw x509 CA certs */ @@ -2429,6 +2472,13 @@ verify_cert (GByteArray *array, const char *prop_name, GError **error) return TRUE; } break; + case NM_SETTING_802_1X_CK_SCHEME_HASH: + /* For hash-based schemes, verify that the has is zero-terminated */ + if (array->data[array->len - 1] == '\0') { + if (g_str_has_prefix ((char *)array->data, SCHEME_HASH)) + return TRUE; + } + break; default: break; } diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h index eaca344..33fff30 100644 --- a/libnm-util/nm-setting-8021x.h +++ b/libnm-util/nm-setting-8021x.h @@ -57,6 +57,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 @@ -65,7 +67,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; @@ -185,6 +188,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 78812f9..0b7fd75 100644 --- a/src/settings/plugins/ifnet/connection_parser.c +++ b/src/settings/plugins/ifnet/connection_parser.c @@ -45,6 +45,8 @@ #include "connection_parser.h" #include "nm-ifnet-connection.h" +#define SCHEME_HASH "hash://server/sha256/" + static void update_connection_id (NMConnection *connection, const char *conn_name) { @@ -188,11 +190,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 { PLUGIN_WARN (IFNET_PLUGIN_NAME, @@ -297,11 +306,18 @@ eap_peap_reader (const char *eap_method, ca_cert = wpa_get_value (ssid, "ca_cert"); 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 { PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: missing " "IEEE_8021X_CA_CERT for EAP method '%s'; this is" @@ -399,11 +415,18 @@ eap_ttls_reader (const char *eap_method, /* ca cert */ ca_cert = wpa_get_value (ssid, "ca_cert"); 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 { PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: missing " "IEEE_8021X_CA_CERT for EAP method '%s'; this is" @@ -1751,12 +1774,14 @@ error: typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x * setting); typedef const char *(*PathFunc) (NMSetting8021x * setting); +typedef const char *(*HashFunc) (NMSetting8021x * setting); typedef const GByteArray *(*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; @@ -1766,6 +1791,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" @@ -1775,6 +1801,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" @@ -1784,6 +1811,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" @@ -1793,6 +1821,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" @@ -1802,6 +1831,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" @@ -1811,6 +1841,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" @@ -1820,6 +1851,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" @@ -1829,6 +1861,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" @@ -1843,6 +1876,7 @@ write_object (NMSetting8021x *s_8021x, { NMSetting8021xCKScheme scheme; const char *path = NULL; + const char *hash = NULL; const GByteArray *blob = NULL; g_return_val_if_fail (conn_name != NULL, FALSE); @@ -1861,6 +1895,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; } @@ -1875,6 +1912,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) { PLUGIN_WARN (IFNET_PLUGIN_NAME, diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c index c7889cf..85090b8 100644 --- a/src/settings/plugins/keyfile/reader.c +++ b/src/settings/plugins/keyfile/reader.c @@ -871,6 +871,7 @@ get_cert_path (const char *keyfile_path, GByteArray *cert_path) } #define SCHEME_PATH "file://" +#define SCHEME_HASH "hash://server/sha256/" static const char *certext[] = { ".pem", ".cert", ".crt", ".cer", ".p12", ".der", ".key" }; @@ -895,6 +896,12 @@ handle_as_scheme (GByteArray *array, NMSetting *setting, const char *key) && (array->data[array->len - 1] == '\0')) { g_object_set (setting, key, array, NULL); return TRUE; + } else if ( (array->len > strlen (SCHEME_HASH)) + && g_str_has_prefix ((const char *) array->data, SCHEME_HASH) + && (array->data[array->len - 1] == '\0')) { + /* It's the HASH scheme, can just set plain data */ + g_object_set (setting, key, array, NULL); + return TRUE; } return FALSE; } diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c index bbd6a7c..bc90fbd 100644 --- a/src/settings/plugins/keyfile/writer.c +++ b/src/settings/plugins/keyfile/writer.c @@ -565,6 +565,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); const GByteArray * (*blob_func) (NMSetting8021x *setting); } ObjectType; @@ -575,6 +576,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, @@ -583,6 +585,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, @@ -591,6 +594,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, @@ -599,6 +603,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, @@ -607,6 +612,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, @@ -615,6 +621,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 }, @@ -693,7 +700,7 @@ cert_writer (GKeyFile *file, const char *setting_name = nm_setting_get_name (setting); NMSetting8021xCKScheme scheme; NMSetting8021xCKFormat format; - const char *path = NULL, *ext = "pem"; + const char *path = NULL, *hash = NULL, *ext = "pem"; const ObjectType *objtype = NULL; int i; @@ -755,6 +762,11 @@ cert_writer (GKeyFile *file, g_error_free (error); } g_free (new_path); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_HASH) { + hash = objtype->hash_func (NM_SETTING_802_1X (setting)); + g_assert (hash); + + g_key_file_set_string (file, setting_name, key, hash); } else g_assert_not_reached (); } -- 1.7.7 From 8de0c8b23577663cc622e04e3ff4c5fe01e11b9b Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin <chingpang@gmail.com> Date: Wed, 18 Jul 2012 12:17:17 +0800 Subject: [PATCH 2/3] wifi: add the dbus method to probe the certificate --- introspection/nm-device-wifi.xml | 23 +++++ src/nm-device-wifi.c | 99 ++++++++++++++++++++++ src/nm-device-wifi.h | 2 + src/supplicant-manager/nm-supplicant-config.c | 24 +++++ src/supplicant-manager/nm-supplicant-config.h | 2 + src/supplicant-manager/nm-supplicant-interface.c | 32 +++++++ src/supplicant-manager/nm-supplicant-interface.h | 4 + 7 files changed, 186 insertions(+), 0 deletions(-) diff --git a/introspection/nm-device-wifi.xml b/introspection/nm-device-wifi.xml index fb50762..fdff623 100644 --- a/introspection/nm-device-wifi.xml +++ b/introspection/nm-device-wifi.xml @@ -14,6 +14,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. @@ -81,6 +93,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/nm-device-wifi.c b/src/nm-device-wifi.c index ed964a5..3fd9fc7 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -59,10 +59,14 @@ #include "nm-settings-connection.h" #include "nm-enum-types.h" #include "wifi-utils.h" +#include "nm-dbus-glib-types.h" 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); #include "nm-device-wifi-glue.h" @@ -99,6 +103,7 @@ enum { HIDDEN_AP_FOUND, PROPERTIES_CHANGED, SCANNING_ALLOWED, + CERT_RECEIVED, LAST_SIGNAL }; @@ -113,6 +118,7 @@ typedef struct Supplicant { guint sig_ids[SUP_SIG_ID_LEN]; guint iface_error_id; + guint iface_cert_id; /* Timeouts and idles */ guint iface_con_error_cb_id; @@ -1661,6 +1667,89 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" #define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5] +static void +supplicant_iface_certification_cb (NMSupplicantInterface * iface, + GHashTable *cert, + NMDeviceWifi * self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GValue *value; + const char *subject, *hash; + guint depth; + + value = g_hash_table_lookup (cert, "depth"); + if (!value || !G_VALUE_HOLDS_UINT(value)) { + nm_log_dbg (LOGD_WIFI_SCAN, "Depth was not set"); + return; + } + depth = g_value_get_uint (value); + + value = g_hash_table_lookup (cert, "subject"); + if (!value || !G_VALUE_HOLDS_STRING(value)) + return; + subject = g_value_get_string (value); + + value = g_hash_table_lookup (cert, "cert_hash"); + if (!value || !G_VALUE_HOLDS_STRING(value)) + return; + hash = g_value_get_string (value); + + nm_log_info (LOGD_WIFI_SCAN, "Got Server Certificate %u, subject %s, hash %s", depth, subject, hash); + + if (depth != 0) + return; + + g_signal_emit (self, signals[CERT_RECEIVED], 0, cert); + + if (priv->supplicant.iface_cert_id > 0) { + g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_cert_id); + priv->supplicant.iface_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->supplicant.iface, + "certification", + G_CALLBACK (supplicant_iface_certification_cb), + self); + priv->supplicant.iface_cert_id = id; + + if (!nm_supplicant_interface_set_config (priv->supplicant.iface, config)) + goto error; + + ret = TRUE; + +error: + if (!ret) { + g_set_error_literal (err, + NM_WIFI_ERROR, + NM_WIFI_ERROR_INVALID_CERT_PROBE, + "Couldn't probe RADIUS server certificate"); + if (priv->supplicant.iface_cert_id) { + g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_cert_id); + priv->supplicant.iface_cert_id = 0; + } + } + + return ret; +} + /* * merge_scanned_ap * @@ -3526,6 +3615,16 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) _nm_marshal_BOOLEAN__VOID, 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); + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_wifi_object_info); dbus_g_error_domain_register (NM_WIFI_ERROR, NULL, NM_TYPE_WIFI_ERROR); diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h index 1e665fc..b45b0df 100644 --- a/src/nm-device-wifi.h +++ b/src/nm-device-wifi.h @@ -46,6 +46,7 @@ typedef enum { NM_WIFI_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, /*< nick=AccessPointNotFound >*/ + NM_WIFI_ERROR_INVALID_CERT_PROBE, /*< nick=InvalidCertProbe >*/ } NMWifiError; #define NM_DEVICE_WIFI_HW_ADDRESS "hw-address" @@ -83,6 +84,7 @@ struct _NMDeviceWifiClass void (*hidden_ap_found) (NMDeviceWifi *device, NMAccessPoint *ap); void (*properties_changed) (NMDeviceWifi *device, GHashTable *properties); 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 a8e4ab9..0b87ddd 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -174,6 +174,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, @@ -912,6 +931,11 @@ 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 a8d3047..c0356c5 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 f8ad8f1..2c69d31 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -64,6 +64,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 }; @@ -503,6 +504,17 @@ wpas_iface_scan_done (DBusGProxy *proxy, } static void +wpas_iface_got_certification (DBusGProxy *proxy, + const GHashTable *cert_table, + gpointer user_data) +{ + g_signal_emit (user_data, + signals[CERTIFICATION], + 0, + cert_table); +} + +static void wpas_iface_properties_changed (DBusGProxy *proxy, GHashTable *props, gpointer user_data) @@ -717,6 +729,18 @@ interface_add_done (NMSupplicantInterface *self, char *path) self, NULL); + dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->iface_proxy, "Certification", + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "Certification", + G_CALLBACK (wpas_iface_got_certification), + self, + NULL); + priv->props_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), WPAS_DBUS_SERVICE, path, @@ -1488,5 +1512,13 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) NULL, NULL, _nm_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); + signals[CERTIFICATION] = + g_signal_new ("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, DBUS_TYPE_G_MAP_OF_VARIANT); } diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 608ee05..b304546 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -107,6 +107,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; -- 1.7.7 From b8cc0eff9d479e96a7c64c51128c91fcf7d07f41 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin <chingpang@gmail.com> Date: Wed, 18 Jul 2012 12:26:19 +0800 Subject: [PATCH 3/3] libnm-glib: add the function to probe the certificate --- libnm-glib/libnm-glib.ver | 1 + libnm-glib/nm-device-wifi.c | 69 +++++++++++++++++++++++++++++++++++++++++++ libnm-glib/nm-device-wifi.h | 5 ++- 3 files changed, 74 insertions(+), 1 deletions(-) diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 427e248..e12c524 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -139,6 +139,7 @@ global: nm_device_wifi_get_permanent_hw_address; nm_device_wifi_get_type; nm_device_wifi_new; + 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 6975898..566e6f0 100644 --- a/libnm-glib/nm-device-wifi.c +++ b/libnm-glib/nm-device-wifi.c @@ -79,6 +79,7 @@ enum { enum { ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED, + CERT_RECEIVED, LAST_SIGNAL }; @@ -342,6 +343,49 @@ access_point_removed (NMObject *self_obj, NMObject *ap_obj) g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap); } +/** + * 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) { @@ -593,6 +637,13 @@ constructed (GObject *object) nm_object_get_path (NM_OBJECT (object)), 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), @@ -760,4 +811,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 13f1cb8..45fa56c 100644 --- a/libnm-glib/nm-device-wifi.h +++ b/libnm-glib/nm-device-wifi.h @@ -78,6 +78,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); @@ -85,7 +86,6 @@ typedef struct { void (*_reserved3) (void); void (*_reserved4) (void); void (*_reserved5) (void); - void (*_reserved6) (void); } NMDeviceWifiClass; GType nm_device_wifi_get_type (void); @@ -104,6 +104,9 @@ NMAccessPoint * nm_device_wifi_get_access_point_by_path (NMDeviceWifi * const GPtrArray * nm_device_wifi_get_access_points (NMDeviceWifi *device); +gboolean nm_device_wifi_probe_cert (NMDeviceWifi *device, + const GByteArray *ssid); + G_END_DECLS #endif /* NM_DEVICE_WIFI_H */ -- 1.7.7
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor