File nma-wpa-eap-probe-ca-cert.patch of Package NetworkManager-gnome.import5373

diff --git a/src/applet-device-wifi.c b/src/applet-device-wifi.c
index 39c2f91..576a765 100644
--- a/src/applet-device-wifi.c
+++ b/src/applet-device-wifi.c
@@ -1428,6 +1428,11 @@ wireless_dialog_response_cb (GtkDialog *foo,
 	g_assert (connection);
 	g_assert (device);
 
+	if (nma_wireless_dialog_need_ca_cert_probe (dialog)) {
+		nma_wireless_dialog_probe_ca_cert (dialog);
+		return;
+	}
+
 	/* If it's a system connection we just need to tell NM to activate it */
 	if (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM) {
 		service = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
@@ -1661,6 +1666,11 @@ get_secrets_dialog_response_cb (GtkDialog *foo,
 		goto done;
 	}
 
+	if (nma_wireless_dialog_need_ca_cert_probe (dialog)) {
+		nma_wireless_dialog_probe_ca_cert (dialog);
+		return;
+	}
+
 	/* Second-guess which setting NM wants secrets for. */
 	s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY));
 	if (!s_wireless_sec) {
diff --git a/src/applet.glade b/src/applet.glade
index 5d1763d..c194cfa 100644
--- a/src/applet.glade
+++ b/src/applet.glade
@@ -1135,7 +1135,7 @@ Shared Key</property>
         <child>
           <widget class="GtkTable" id="table10">
             <property name="visible">True</property>
-            <property name="n_rows">4</property>
+            <property name="n_rows">6</property>
             <property name="n_columns">2</property>
             <property name="column_spacing">12</property>
             <property name="row_spacing">6</property>
@@ -1172,8 +1172,8 @@ Shared Key</property>
                 <property name="mnemonic_widget">eap_ttls_ca_cert_button</property>
               </widget>
               <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options"></property>
               </packing>
@@ -1185,8 +1185,8 @@ Shared Key</property>
               <packing>
                 <property name="left_attach">1</property>
                 <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options">GTK_FILL</property>
               </packing>
@@ -1200,8 +1200,8 @@ Shared Key</property>
                 <property name="mnemonic_widget">eap_ttls_inner_auth_combo</property>
               </widget>
               <packing>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options"></property>
               </packing>
@@ -1214,8 +1214,8 @@ Shared Key</property>
               <packing>
                 <property name="left_attach">1</property>
                 <property name="right_attach">2</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options">GTK_FILL</property>
               </packing>
@@ -1231,9 +1231,67 @@ Shared Key</property>
               </widget>
               <packing>
                 <property name="right_attach">2</property>
+                <property name="top_attach">5</property>
+                <property name="bottom_attach">6</property>
+                <property name="x_options">GTK_FILL</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="eap_ttls_subject_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Subject:</property>
+                <property name="use_underline">False</property>
+                <property name="use_markup">False</property>
+                <property name="justify">GTK_JUSTIFY_LEFT</property>
+                <property name="wrap">False</property>
+                <property name="selectable">False</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0.5</property>
+                <property name="xpad">0</property>
+                <property name="ypad">0</property>
+                <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+                <property name="width_chars">-1</property>
+                <property name="single_line_mode">False</property>
+                <property name="angle">0</property>
+              </widget>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="right_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="x_options">fill</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="eap_ttls_subject_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="editable">True</property>
+                <property name="visibility">True</property>
+                <property name="max_length">0</property>
+                <property name="text" translatable="yes"></property>
+                <property name="has_frame">True</property>
+                <property name="activates_default">False</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="eap_ttls_note_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Note</property>
+                <property name="track_visited_links">False</property>
+              </widget>
+              <packing>
+                <property name="right_attach">2</property>
                 <property name="top_attach">3</property>
                 <property name="bottom_attach">4</property>
-                <property name="x_options">GTK_FILL</property>
               </packing>
             </child>
           </widget>
@@ -1652,7 +1710,7 @@ Shared Key</property>
         <child>
           <widget class="GtkTable" id="table13">
             <property name="visible">True</property>
-            <property name="n_rows">5</property>
+            <property name="n_rows">7</property>
             <property name="n_columns">2</property>
             <property name="column_spacing">12</property>
             <property name="row_spacing">6</property>
@@ -1689,8 +1747,8 @@ Shared Key</property>
                 <property name="mnemonic_widget">eap_peap_ca_cert_button</property>
               </widget>
               <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options"></property>
               </packing>
@@ -1702,8 +1760,8 @@ Shared Key</property>
               <packing>
                 <property name="left_attach">1</property>
                 <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options">GTK_FILL</property>
               </packing>
@@ -1718,8 +1776,8 @@ Shared Key</property>
               </widget>
               <packing>
                 <property name="right_attach">2</property>
-                <property name="top_attach">4</property>
-                <property name="bottom_attach">5</property>
+                <property name="top_attach">6</property>
+                <property name="bottom_attach">7</property>
                 <property name="x_options">GTK_FILL</property>
               </packing>
             </child>
@@ -1732,8 +1790,8 @@ Shared Key</property>
                 <property name="mnemonic_widget">eap_peap_inner_auth_combo</property>
               </widget>
               <packing>
-                <property name="top_attach">3</property>
-                <property name="bottom_attach">4</property>
+                <property name="top_attach">5</property>
+                <property name="bottom_attach">6</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options"></property>
               </packing>
@@ -1746,8 +1804,8 @@ Shared Key</property>
               <packing>
                 <property name="left_attach">1</property>
                 <property name="right_attach">2</property>
-                <property name="top_attach">3</property>
-                <property name="bottom_attach">4</property>
+                <property name="top_attach">5</property>
+                <property name="bottom_attach">6</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options">GTK_FILL</property>
               </packing>
@@ -1761,8 +1819,8 @@ Shared Key</property>
                 <property name="mnemonic_widget">eap_peap_version_combo</property>
               </widget>
               <packing>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options"></property>
               </packing>
@@ -1777,12 +1835,70 @@ Version 1</property>
               <packing>
                 <property name="left_attach">1</property>
                 <property name="right_attach">2</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
                 <property name="x_options">GTK_FILL</property>
                 <property name="y_options">GTK_FILL</property>
               </packing>
             </child>
+            <child>
+              <widget class="GtkLabel" id="eap_peap_subject_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Subject:</property>
+                <property name="use_underline">False</property>
+                <property name="use_markup">False</property>
+                <property name="justify">GTK_JUSTIFY_LEFT</property>
+                <property name="wrap">False</property>
+                <property name="selectable">False</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0.5</property>
+                <property name="xpad">0</property>
+                <property name="ypad">0</property>
+                <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+                <property name="width_chars">-1</property>
+                <property name="single_line_mode">False</property>
+                <property name="angle">0</property>
+              </widget>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="right_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="x_options">fill</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="eap_peap_subject_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="editable">True</property>
+                <property name="visibility">True</property>
+                <property name="max_length">0</property>
+                <property name="text" translatable="yes"></property>
+                <property name="has_frame">True</property>
+                <property name="activates_default">False</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="eap_peap_note_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Note</property>
+                <property name="track_visited_links">False</property>
+              </widget>
+              <packing>
+                <property name="right_attach">2</property>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+              </packing>
+            </child>
           </widget>
         </child>
         <child>
diff --git a/src/gconf-helpers/gconf-helpers.c b/src/gconf-helpers/gconf-helpers.c
index 2e0db07..0858736 100644
--- a/src/gconf-helpers/gconf-helpers.c
+++ b/src/gconf-helpers/gconf-helpers.c
@@ -1719,6 +1719,7 @@ typedef struct ReadFromGConfInfo {
 } ReadFromGConfInfo;
 
 #define FILE_TAG "file://"
+#define HASH_TAG "hash://server/sha256/"
 
 static void
 read_one_setting_value_from_gconf (NMSetting *setting,
@@ -1770,9 +1771,14 @@ read_one_setting_value_from_gconf (NMSetting *setting,
 		if (nm_gconf_get_string_helper (info->client, info->dir, key, setting_name, &str_val)) {
 			GByteArray *ba_val;
 
-			ba_val = g_byte_array_sized_new (strlen (FILE_TAG) + strlen (str_val) + 1);
-			g_byte_array_append (ba_val, (const guint8 *) FILE_TAG, strlen (FILE_TAG));
-			g_byte_array_append (ba_val, (const guint8 *) str_val, strlen (str_val) + 1);  /* +1 for the trailing NULL */
+			if (g_str_has_prefix (str_val, HASH_TAG)) {
+				ba_val = g_byte_array_sized_new (strlen (str_val) + 1);
+				g_byte_array_append (ba_val, (const guint8 *) str_val, strlen (str_val) + 1);
+			} else {
+				ba_val = g_byte_array_sized_new (strlen (FILE_TAG) + strlen (str_val) + 1);
+				g_byte_array_append (ba_val, (const guint8 *) FILE_TAG, strlen (FILE_TAG));
+				g_byte_array_append (ba_val, (const guint8 *) str_val, strlen (str_val) + 1);  /* +1 for the trailing NULL */
+			}
 			g_object_set (setting, key, ba_val, NULL);
 			g_byte_array_free (ba_val, TRUE);
 			g_free (str_val);
@@ -2188,6 +2194,7 @@ out:
 typedef NMSetting8021xCKScheme (*SchemeFunc)  (NMSetting8021x *setting);
 typedef const char *           (*PathFunc)    (NMSetting8021x *setting);
 typedef const GByteArray *     (*BlobFunc)    (NMSetting8021x *setting);
+typedef const char *           (*HashFunc)    (NMSetting8021x *setting);
 typedef NMSetting8021xCKFormat (*FormatFunc)  (NMSetting8021x *setting);
 typedef const char *           (*PasswordFunc)(NMSetting8021x *setting);
 
@@ -2197,6 +2204,7 @@ typedef struct ObjectType {
 	SchemeFunc scheme_func;
 	PathFunc path_func;
 	BlobFunc blob_func;
+	HashFunc hash_func;
 	FormatFunc format_func;
 	PasswordFunc password_func;
 	const char *privkey_password_key;
@@ -2209,6 +2217,7 @@ static const ObjectType ca_type = {
 	nm_setting_802_1x_get_ca_cert_scheme,
 	nm_setting_802_1x_get_ca_cert_path,
 	nm_setting_802_1x_get_ca_cert_blob,
+	nm_setting_802_1x_get_ca_cert_hash,
 	NULL,
 	NULL,
 	NULL,
@@ -2224,6 +2233,7 @@ static const ObjectType phase2_ca_type = {
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	"inner-ca-cert.der"
 };
 
@@ -2236,6 +2246,7 @@ static const ObjectType client_type = {
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	"client-cert.der"
 };
 
@@ -2248,6 +2259,7 @@ static const ObjectType phase2_client_type = {
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	"inner-client-cert.der"
 };
 
@@ -2257,6 +2269,7 @@ static const ObjectType pk_type = {
 	nm_setting_802_1x_get_private_key_scheme,
 	nm_setting_802_1x_get_private_key_path,
 	nm_setting_802_1x_get_private_key_blob,
+	NULL,
 	nm_setting_802_1x_get_private_key_format,
 	nm_setting_802_1x_get_private_key_password,
 	NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
@@ -2269,6 +2282,7 @@ static const ObjectType phase2_pk_type = {
 	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,
+	NULL,
 	nm_setting_802_1x_get_phase2_private_key_format,
 	nm_setting_802_1x_get_phase2_private_key_password,
 	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
@@ -2281,6 +2295,7 @@ static const ObjectType p12_type = {
 	nm_setting_802_1x_get_private_key_scheme,
 	nm_setting_802_1x_get_private_key_path,
 	nm_setting_802_1x_get_private_key_blob,
+	NULL,
 	nm_setting_802_1x_get_private_key_format,
 	nm_setting_802_1x_get_private_key_password,
 	NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
@@ -2293,6 +2308,7 @@ static const ObjectType phase2_p12_type = {
 	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,
+	NULL,
 	nm_setting_802_1x_get_phase2_private_key_format,
 	nm_setting_802_1x_get_phase2_private_key_password,
 	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
@@ -2335,6 +2351,9 @@ write_object (GConfClient *client,
 		case NM_SETTING_802_1X_CK_SCHEME_PATH:
 			path = (*(objtype->path_func))(s_8021x);
 			break;
+		case NM_SETTING_802_1X_CK_SCHEME_HASH:
+			path = (*(objtype->hash_func))(s_8021x);
+			break;
 		default:
 			break;
 		}
diff --git a/src/wireless-dialog.c b/src/wireless-dialog.c
index 621526f..d6cc4c2 100644
--- a/src/wireless-dialog.c
+++ b/src/wireless-dialog.c
@@ -37,6 +37,7 @@
 #include <nm-setting-connection.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-ip4-config.h>
+#include <nm-setting-8021x.h>
 
 #include "applet.h"
 #include "applet-dialogs.h"
@@ -83,6 +84,10 @@ typedef struct {
 	GetSecretsInfo *secrets_info;
 
 	gboolean disposed;
+
+	/* For Server certificate probe */
+	guint ca_cert_id;
+	guint timeout_id;
 } NMAWirelessDialogPrivate;
 
 #define D_NAME_COLUMN		0
@@ -115,6 +120,228 @@ nma_wireless_dialog_get_nag_ignored (NMAWirelessDialog *self)
 	return NMA_WIRELESS_DIALOG_GET_PRIVATE (self)->nag_ignored;
 }
 
+gboolean
+nma_wireless_dialog_need_ca_cert_probe (NMAWirelessDialog *self)
+{
+	NMAWirelessDialogPrivate *priv;
+	NMSetting8021x *s_8021x;
+	NMSetting8021xCKScheme cert_scheme;
+	int i, num_eap;
+	const char *subject;
+	gboolean need_ca = FALSE;
+
+	g_return_val_if_fail (self != NULL, FALSE);
+
+	priv = NMA_WIRELESS_DIALOG_GET_PRIVATE (self);
+
+	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_802_1X));
+	if (!s_8021x)
+		return FALSE;
+
+	num_eap = nm_setting_802_1x_get_num_eap_methods (s_8021x);
+	for (i = 0; i < num_eap; i++) {
+		const char *eap;
+		eap = nm_setting_802_1x_get_eap_method (s_8021x, i);
+		if (g_strcmp0 (eap, "ttls") == 0 || g_strcmp0 (eap, "peap") == 0) {
+			need_ca = TRUE;
+			break;
+		}
+	}
+
+	if (!need_ca)
+		return FALSE;
+
+	subject = nm_setting_802_1x_get_subject_match (s_8021x);
+	cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+
+	if (!subject || cert_scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN)
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean
+show_probe_result_dialog (GtkWindow *parent,
+                          NMConnection *connection,
+                          NMSetting8021x *s_8021x,
+                          const char *subject,
+                          const char *cert_hash)
+{
+	NMSettingConnection *s_con;
+	GtkWidget *notify_dialog, *content;
+	GtkWidget *table;
+	GtkWidget *context, *label, *entry;
+	char *id, *string;
+	int response_id;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	id = (char *) nm_setting_connection_get_id (s_con);
+
+	notify_dialog = gtk_dialog_new_with_buttons (id, parent,
+	                                             GTK_DIALOG_MODAL,
+	                                             GTK_STOCK_NO, GTK_RESPONSE_NO,
+	                                             GTK_STOCK_YES, GTK_RESPONSE_YES,
+	                                             NULL);
+	content = gtk_dialog_get_content_area (GTK_DIALOG (notify_dialog));
+
+	table = gtk_table_new (2, 3, FALSE);
+	gtk_table_set_row_spacings (GTK_TABLE (table), 10);
+	gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+	gtk_container_add (GTK_CONTAINER (content), table);
+
+	entry = gtk_entry_new ();
+	gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE);
+	if (!cert_hash) {
+		string = g_strdup_printf (_("<span weight=\"bold\" size=\"larger\">Server Certificate Probed</span>\n\nThe subject of <b>%s</b> is going to be filled with the probe result. Do you agree?"), id);
+		label = gtk_label_new (_("Subject:"));
+		gtk_entry_set_text (GTK_ENTRY (entry), subject);
+	} else {
+		string = g_strdup_printf (_("<span weight=\"bold\" size=\"larger\">Server Certificate Probed</span>\n\nThe CA certificate of <b>%s</b> is going to be filled with the probed server hash. Do you agree?"), id);
+		label = gtk_label_new (_("CA Certificate:"));
+		gtk_entry_set_text (GTK_ENTRY (entry), cert_hash);
+	}
+	context = gtk_label_new (string);
+	g_free (string);
+	gtk_label_set_line_wrap (GTK_LABEL (context), TRUE);
+	gtk_label_set_use_markup (GTK_LABEL (context), TRUE);
+	gtk_table_attach (GTK_TABLE (table), context, 0, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (GTK_TABLE (table), entry, 1, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+
+	gtk_widget_show_all (notify_dialog);
+
+	response_id = gtk_dialog_run (GTK_DIALOG (notify_dialog));
+
+	gtk_widget_destroy (notify_dialog);
+
+	if (response_id == GTK_RESPONSE_YES)
+		return TRUE;
+
+	return FALSE;
+}
+
+static void
+wireless_ca_cert_cb (NMDeviceWifi *wifi,
+                     GHashTable *ca_cert,
+                     gpointer user_data)
+{
+	NMAWirelessDialog *self = NMA_WIRELESS_DIALOG (user_data);
+	NMAWirelessDialogPrivate *priv;
+	NMSetting8021x *s_8021x;
+	const char *subject = NULL, *hash = NULL;
+	gboolean response = FALSE;
+
+	priv = NMA_WIRELESS_DIALOG_GET_PRIVATE (self);
+
+	g_signal_handler_disconnect (NM_DEVICE_WIFI (priv->device), priv->ca_cert_id);
+	if (priv->timeout_id) {
+		g_source_remove (priv->timeout_id);
+		priv->timeout_id = 0;
+	}
+
+	subject = (const char *)g_hash_table_lookup (ca_cert, "subject");
+	hash = (const char *)g_hash_table_lookup (ca_cert, "hash");
+
+	if (!subject || !hash)
+		goto out;
+
+	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_802_1X));
+	if (s_8021x) {
+		NMSetting8021xCKScheme cert_scheme;
+		char *hash_path = NULL;
+		gboolean ret;
+		GError *error = NULL;
+
+		cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+		if (cert_scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN)
+			hash_path = g_strconcat ("hash://server/sha256/", hash, NULL);
+
+		ret = show_probe_result_dialog (GTK_WINDOW (self),
+		                                priv->connection,
+		                                s_8021x,
+		                                subject,
+		                                hash_path);
+		if (!ret) {
+			g_free (hash_path);
+			goto out;
+		}
+
+		if (!nm_setting_802_1x_get_subject_match (s_8021x))
+			g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, subject, NULL);
+		if (hash_path) {
+			NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+			nm_setting_802_1x_set_ca_cert (s_8021x,
+			                               hash_path,
+			                               NM_SETTING_802_1X_CK_SCHEME_HASH,
+			                               &format,
+			                               &error);
+			g_free (hash_path);
+			if (error) {
+				g_warning ("Failed to set certificate hash: (%d) %s", error->code, error->message);
+				g_error_free (error);
+				goto out;
+			}
+		}
+		response = TRUE;
+	}
+out:
+	if (response)
+		gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+	else
+		gtk_widget_show (GTK_WIDGET (self));
+}
+
+static gboolean
+wireless_ca_cert_timeout_cb (gpointer user_data)
+{
+	NMAWirelessDialog *self = (NMAWirelessDialog *)user_data;
+	NMAWirelessDialogPrivate *priv;
+
+	priv = NMA_WIRELESS_DIALOG_GET_PRIVATE (self);
+
+	priv->timeout_id = 0;
+
+	g_signal_handler_disconnect (NM_DEVICE_WIFI (priv->device), priv->ca_cert_id);
+
+	gtk_widget_show (GTK_WIDGET (self));
+
+	return FALSE;
+}
+
+gboolean
+nma_wireless_dialog_probe_ca_cert (NMAWirelessDialog *self)
+{
+	NMAWirelessDialogPrivate *priv;
+	NMSettingWireless *s_wireless;
+	NMDeviceWifi *wifi;
+	guint id;
+
+	g_return_val_if_fail (self != NULL, FALSE);
+
+	priv = NMA_WIRELESS_DIALOG_GET_PRIVATE (self);
+        wifi = NM_DEVICE_WIFI (priv->device);
+
+	s_wireless = (NMSettingWireless *) nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_WIRELESS);
+	if (!nm_device_wifi_probe_ca_cert (wifi, nm_setting_wireless_get_ssid (s_wireless)))
+		return FALSE;
+
+	id = g_timeout_add_seconds (30,
+	                            (GSourceFunc)wireless_ca_cert_timeout_cb,
+	                            (gpointer)self);
+	if (id <= 0) {
+		g_warning ("Failed to add timeout for server certificate probe");
+		return FALSE;
+	}
+	priv->timeout_id = id;
+
+	id = g_signal_connect (wifi, "ca-cert-received", G_CALLBACK (wireless_ca_cert_cb), self);
+	priv->ca_cert_id = id;
+
+	gtk_widget_hide (GTK_WIDGET (self));
+
+	return TRUE;
+}
+
 static void
 model_free (GtkTreeModel *model, guint col)
 {
diff --git a/src/wireless-dialog.h b/src/wireless-dialog.h
index 3b9ee4d..16f6160 100644
--- a/src/wireless-dialog.h
+++ b/src/wireless-dialog.h
@@ -66,5 +66,9 @@ void nma_wireless_dialog_set_nag_ignored (NMAWirelessDialog *dialog, gboolean ig
 
 gboolean nma_wireless_dialog_get_nag_ignored (NMAWirelessDialog *dialog);
 
+gboolean nma_wireless_dialog_need_ca_cert_probe (NMAWirelessDialog *dialog);
+
+gboolean nma_wireless_dialog_probe_ca_cert (NMAWirelessDialog *dialog);
+
 #endif	/* WIRELESS_DIALOG_H */
 
diff --git a/src/wireless-security/eap-method-peap.c b/src/wireless-security/eap-method-peap.c
index 49faf12..fdab1cc 100644
--- a/src/wireless-security/eap-method-peap.c
+++ b/src/wireless-security/eap-method-peap.c
@@ -35,6 +35,8 @@
 #define I_NAME_COLUMN   0
 #define I_METHOD_COLUMN 1
 
+#define SUBJECT_NOTE _("<will be filled automatically>")
+
 static void
 destroy (EAPMethod *parent)
 {
@@ -98,6 +100,10 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
 
+	widget = glade_xml_get_widget (parent->xml, "eap_peap_subject_label");
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
 	widget = glade_xml_get_widget (parent->xml, "eap_peap_inner_auth_combo");
 	g_assert (widget);
 
@@ -138,10 +144,16 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	if (text && strlen (text))
 		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
 
+	widget = glade_xml_get_widget (parent->xml, "eap_peap_subject_entry");
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (text && strlen (text) && g_strcmp0 (text, SUBJECT_NOTE) != 0)
+		g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, text, NULL);
+
 	widget = glade_xml_get_widget (parent->xml, "eap_peap_ca_cert_button");
 	g_assert (widget);
 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
-	if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+	if (filename && !nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
 		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
 		g_clear_error (&error);
 	}
@@ -305,6 +317,43 @@ update_secrets (EAPMethod *parent, NMConnection *connection)
 	                                         I_METHOD_COLUMN);
 }
 
+static gboolean
+subject_entry_focus_in_cb (GtkWidget *widget,
+                           GdkEvent  *event,
+                           gpointer user_data)
+{
+	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (g_strcmp0 (text, SUBJECT_NOTE) == 0) {
+		gtk_entry_set_text (GTK_ENTRY (widget), "");
+		gtk_widget_modify_text (GTK_WIDGET (widget), GTK_STATE_NORMAL, NULL);
+	}
+	return FALSE;
+}
+
+static gboolean
+subject_entry_focus_out_cb (GtkWidget *widget,
+                            GdkEvent  *event,
+                            gpointer user_data)
+{
+	NMSetting8021x *s_8021x = (NMSetting8021x *)user_data;
+	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
+	GtkStyle *style;
+
+	if (!text || !strlen (text)) {
+		/* Since we save/restore the subject in ws_802_1x_fill_connection()
+		 * to prevent the probed result from being erased, we have to clear
+		 * the subject here to trigger the probe later. */
+		g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, NULL, NULL);
+		gtk_entry_set_text (GTK_ENTRY (widget), SUBJECT_NOTE);
+		style = gtk_widget_get_style (widget);
+		gtk_widget_modify_text (GTK_WIDGET (widget),
+		                        GTK_STATE_NORMAL,
+		                        &style->text[GTK_STATE_INSENSITIVE]);
+	}
+
+	return FALSE;
+}
+
 EAPMethodPEAP *
 eap_method_peap_new (const char *glade_file,
                      WirelessSecurity *parent,
@@ -406,6 +455,43 @@ eap_method_peap_new (const char *glade_file,
 	                  (GCallback) wireless_security_changed_cb,
 	                  parent);
 
+	widget = glade_xml_get_widget (xml, "eap_peap_subject_entry");
+	if (s_8021x) {
+		const char *text = nm_setting_802_1x_get_subject_match (s_8021x);
+		if (!text) {
+			GtkStyle *style;
+			style = gtk_widget_get_style (widget);
+			gtk_widget_modify_text (widget,
+			                        GTK_STATE_NORMAL,
+			                        &style->text[GTK_STATE_INSENSITIVE]);
+			gtk_entry_set_text (GTK_ENTRY (widget), SUBJECT_NOTE);
+		} else {
+			gtk_entry_set_text (GTK_ENTRY (widget), text);
+		}
+		g_signal_connect (G_OBJECT (widget), "focus-in-event",
+		                  (GCallback) subject_entry_focus_in_cb,
+		                  NULL);
+		g_signal_connect (G_OBJECT (widget), "focus-out-event",
+		                  (GCallback) subject_entry_focus_out_cb,
+		                  s_8021x);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  parent);
+
+	widget = glade_xml_get_widget (xml, "eap_peap_note_label");
+	if (s_8021x) {
+		NMSetting8021xCKScheme cert_scheme;
+		cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+		if (cert_scheme == NM_SETTING_802_1X_CK_SCHEME_HASH) {
+			gtk_label_set_text (GTK_LABEL (widget),
+			                    _("<b>Note:</b> Server hash is used instead of CA certificate"));
+			gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+		} else {
+			gtk_widget_hide (widget);
+		}
+	}
+
 	return method;
 }
 
diff --git a/src/wireless-security/eap-method-ttls.c b/src/wireless-security/eap-method-ttls.c
index 4d9b9bc..68f94d1 100644
--- a/src/wireless-security/eap-method-ttls.c
+++ b/src/wireless-security/eap-method-ttls.c
@@ -35,6 +35,8 @@
 #define I_NAME_COLUMN   0
 #define I_METHOD_COLUMN 1
 
+#define SUBJECT_NOTE _("<will be filled automatically>")
+
 static void
 destroy (EAPMethod *parent)
 {
@@ -86,6 +88,10 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
 
+	widget = glade_xml_get_widget (parent->xml, "eap_ttls_subject_label");
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
 	widget = glade_xml_get_widget (parent->xml, "eap_ttls_ca_cert_label");
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
@@ -133,10 +139,16 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	if (text && strlen (text))
 		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
 
+	widget = glade_xml_get_widget (parent->xml, "eap_ttls_subject_entry");
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (text && strlen (text) && g_strcmp0 (text, SUBJECT_NOTE) != 0)
+		g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, text, NULL);
+
 	widget = glade_xml_get_widget (parent->xml, "eap_ttls_ca_cert_button");
 	g_assert (widget);
 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
-	if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+	if (filename && !nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
 		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
 		g_clear_error (&error);
 	}
@@ -304,6 +316,43 @@ update_secrets (EAPMethod *parent, NMConnection *connection)
 	                                         I_METHOD_COLUMN);
 }
 
+static gboolean
+subject_entry_focus_in_cb (GtkWidget *widget,
+                           GdkEvent  *event,
+                           gpointer user_data)
+{
+	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (g_strcmp0 (text, SUBJECT_NOTE) == 0) {
+		gtk_entry_set_text (GTK_ENTRY (widget), "");
+		gtk_widget_modify_text (GTK_WIDGET (widget), GTK_STATE_NORMAL, NULL);
+	}
+	return FALSE;
+}
+
+static gboolean
+subject_entry_focus_out_cb (GtkWidget *widget,
+                            GdkEvent  *event,
+                            gpointer user_data)
+{
+	NMSetting8021x *s_8021x = (NMSetting8021x *)user_data;
+	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
+	GtkStyle *style;
+
+	if (!text || !strlen (text)) {
+		/* Since we save/restore the subject in ws_802_1x_fill_connection()
+		 * to prevent the probed result from being erased, we have to clear
+		 * the subject here to trigger the probe later. */
+		g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, NULL, NULL);
+		gtk_entry_set_text (GTK_ENTRY (widget), SUBJECT_NOTE);
+		style = gtk_widget_get_style (widget);
+		gtk_widget_modify_text (GTK_WIDGET (widget),
+		                        GTK_STATE_NORMAL,
+		                        &style->text[GTK_STATE_INSENSITIVE]);
+	}
+
+	return FALSE;
+}
+
 EAPMethodTTLS *
 eap_method_ttls_new (const char *glade_file,
                      WirelessSecurity *parent,
@@ -383,6 +432,44 @@ eap_method_ttls_new (const char *glade_file,
 	                  (GCallback) wireless_security_changed_cb,
 	                  parent);
 
+	widget = glade_xml_get_widget (xml, "eap_ttls_subject_entry");
+	if (s_8021x) {
+		const char *text = nm_setting_802_1x_get_subject_match (s_8021x);
+		if (!text) {
+			GtkStyle *style;
+			style = gtk_widget_get_style (widget);
+			gtk_widget_modify_text (widget,
+			                        GTK_STATE_NORMAL,
+			                        &style->text[GTK_STATE_INSENSITIVE]);
+			gtk_entry_set_text (GTK_ENTRY (widget), SUBJECT_NOTE);
+		} else {
+			gtk_entry_set_text (GTK_ENTRY (widget), text);
+		}
+		g_signal_connect (G_OBJECT (widget), "focus-in-event",
+		                  (GCallback) subject_entry_focus_in_cb,
+		                  NULL);
+		g_signal_connect (G_OBJECT (widget), "focus-out-event",
+		                  (GCallback) subject_entry_focus_out_cb,
+		                  s_8021x);
+
+	}
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  parent);
+
+	widget = glade_xml_get_widget (xml, "eap_ttls_note_label");
+	if (s_8021x) {
+		NMSetting8021xCKScheme cert_scheme;
+		cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+		if (cert_scheme == NM_SETTING_802_1X_CK_SCHEME_HASH) {
+			gtk_label_set_text (GTK_LABEL (widget),
+			                    _("<b>Note:</b> Server hash is used instead of CA certificate"));
+			gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+		} else {
+			gtk_widget_hide (widget);
+		}
+	}
+
 	widget = inner_auth_combo_init (method, glade_file, connection, s_8021x);
 	inner_auth_combo_changed_cb (widget, (gpointer) method);
 
diff --git a/src/wireless-security/wireless-security.c b/src/wireless-security/wireless-security.c
index 1a51e6b..96a2841 100644
--- a/src/wireless-security/wireless-security.c
+++ b/src/wireless-security/wireless-security.c
@@ -393,6 +393,7 @@ ws_802_1x_fill_connection (WirelessSecurity *sec,
 	EAPMethod *eap = NULL;
 	GtkTreeModel *model;
 	GtkTreeIter iter;
+	char *subject = NULL, *cert_hash = NULL;
 
 	s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS));
 	g_assert (s_wireless);
@@ -403,10 +404,36 @@ ws_802_1x_fill_connection (WirelessSecurity *sec,
 	s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
 	nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
 
+	/* Fetch the server info */
+	s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X));
+	if (s_8021x) {
+		subject = g_strdup (nm_setting_802_1x_get_subject_match (s_8021x));
+		if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_HASH)
+			cert_hash = g_strdup (nm_setting_802_1x_get_ca_cert_hash (s_8021x));
+	}
+
 	/* Blow away the old 802.1x setting by adding a clear one */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
 	nm_connection_add_setting (connection, (NMSetting *) s_8021x);
 
+	/* Restore the server info */
+	if (subject) {
+		g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, subject, NULL);
+		g_free (subject);
+	}
+	if (cert_hash) {
+		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+		GError *error = NULL;
+		if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+		                                    cert_hash,
+		                                    NM_SETTING_802_1X_CK_SCHEME_HASH,
+		                                    &format,
+		                                    &error)) {
+			g_error_free (error);
+		}
+		g_free (cert_hash);
+	}
+
 	widget = glade_xml_get_widget (sec->xml, combo_name);
 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
 	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
openSUSE Build Service is sponsored by