From 2cfaecf0703ad0572081b58cb853cd35a1ed280c Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <chingpang@gmail.com>
Date: Tue, 1 Oct 2013 18:41:03 +0800
Subject: [PATCH 1/2] Probe the certificate of the RADIUS server

---
 panels/network/network-dialogs.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/panels/network/network-dialogs.c b/panels/network/network-dialogs.c
index b2f8376..7e7035c 100644
--- a/panels/network/network-dialogs.c
+++ b/panels/network/network-dialogs.c
@@ -153,6 +153,11 @@ wireless_dialog_response_cb (GtkDialog *foo,
 	g_assert (connection);
 	g_assert (device);
 
+        if (nma_wifi_dialog_need_cert_probe (dialog)) {
+                nma_wifi_dialog_probe_cert (dialog);
+                return;
+        }
+
 	/* Find a similar connection and use that instead */
 	all = nm_remote_settings_list_connections (closure->settings);
 	for (iter = all; iter; iter = g_slist_next (iter)) {
-- 
2.1.4


From 164652c62ec73aa2737b6d3a7dd828bef672a472 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <chingpang@gmail.com>
Date: Wed, 11 Mar 2015 16:15:00 +0800
Subject: [PATCH 2/2] network: new entry for the subject and support server
 hash

---
 panels/network/wireless-security/eap-method-peap.c | 96 +++++++++++++++++++++-
 .../network/wireless-security/eap-method-peap.ui   | 70 ++++++++++++----
 panels/network/wireless-security/eap-method-tls.c  | 85 ++++++++++++++++++-
 panels/network/wireless-security/eap-method-tls.ui | 59 +++++++++----
 panels/network/wireless-security/eap-method-ttls.c | 96 +++++++++++++++++++++-
 .../network/wireless-security/eap-method-ttls.ui   | 62 +++++++++++---
 .../network/wireless-security/wireless-security.c  | 46 ++++++++++-
 .../network/wireless-security/wireless-security.h  |  3 +
 8 files changed, 466 insertions(+), 51 deletions(-)

diff --git a/panels/network/wireless-security/eap-method-peap.c b/panels/network/wireless-security/eap-method-peap.c
index 2a63991..066c238 100644
--- a/panels/network/wireless-security/eap-method-peap.c
+++ b/panels/network/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>")
+
 struct _EAPMethodPEAP {
 	EAPMethod parent;
 
@@ -93,6 +95,10 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
 
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_subject_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_label"));
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
@@ -121,6 +127,7 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 {
 	NMSetting8021x *s_8021x;
 	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	NMSetting8021xCKScheme cert_scheme;
 	GtkWidget *widget;
 	const char *text;
 	char *filename;
@@ -141,12 +148,21 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	if (text && strlen (text))
 		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
 
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "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 = GTK_WIDGET (gtk_builder_get_object (parent->builder, "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)) {
-		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
-		g_clear_error (&error);
+	cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+	if (filename || cert_scheme != NM_SETTING_802_1X_CK_SCHEME_HASH) {
+		if (!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);
+		}
 	}
 
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
@@ -308,6 +324,37 @@ 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_override_color (widget, GTK_STATE_FLAG_NORMAL, NULL);
+	}
+	return FALSE;
+}
+
+static gboolean
+subject_entry_focus_out_cb (GtkWidget *widget,
+                            GdkEvent  *event,
+                            gpointer user_data)
+{
+	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
+	GtkStyleContext *context;
+	GdkRGBA color;
+
+	if (!text || !strlen (text)) {
+		gtk_entry_set_text (GTK_ENTRY (widget), SUBJECT_NOTE);
+		context = gtk_widget_get_style_context (widget);
+		gtk_style_context_get_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
+		gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, &color);
+	}
+	return FALSE;
+}
+
 EAPMethodPEAP *
 eap_method_peap_new (WirelessSecurity *ws_parent,
                      NMConnection *connection,
@@ -383,6 +430,43 @@ eap_method_peap_new (WirelessSecurity *ws_parent,
 	                  (GCallback) wireless_security_changed_cb,
 	                  ws_parent);
 
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_subject_entry"));
+	if (s_8021x) {
+		const char *text = nm_setting_802_1x_get_subject_match (s_8021x);
+		if (!text) {
+			GtkStyleContext *context;
+			GdkRGBA color;
+			context = gtk_widget_get_style_context (widget);
+			gtk_style_context_get_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
+			gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, &color);
+			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,
+		                  NULL);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_note_label"));
+	gtk_widget_hide (widget);
+	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);
+			gtk_widget_show (widget);
+		}
+	}
+
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
 	if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
 		gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
@@ -395,10 +479,16 @@ eap_method_peap_new (WirelessSecurity *ws_parent,
 		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
 		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_subject_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_subject_entry"));
+		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_label"));
 		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
 		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_note_label"));
+		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_label"));
 		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
diff --git a/panels/network/wireless-security/eap-method-peap.ui b/panels/network/wireless-security/eap-method-peap.ui
index 4202237..af3d5b8 100644
--- a/panels/network/wireless-security/eap-method-peap.ui
+++ b/panels/network/wireless-security/eap-method-peap.ui
@@ -38,7 +38,7 @@
       <object class="GtkTable" id="table13">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="n_rows">5</property>
+        <property name="n_rows">7</property>
         <property name="n_columns">2</property>
         <property name="column_spacing">6</property>
         <property name="row_spacing">6</property>
@@ -69,6 +69,35 @@
           </packing>
         </child>
         <child>
+          <object class="GtkLabel" id="eap_peap_subject_label">
+            <property name="visible">True</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Subject</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_peap_subject_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_peap_subject_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <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>
           <object class="GtkLabel" id="eap_peap_ca_cert_label">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
@@ -78,8 +107,8 @@
             <property name="mnemonic_widget">eap_peap_ca_cert_button</property>
           </object>
           <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"/>
           </packing>
@@ -92,13 +121,24 @@
           <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>
         </child>
         <child>
+          <object class="GtkLabel" id="eap_peap_note_label">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">Note</property>
+          </object>
+          <packing>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkVBox" id="eap_peap_inner_auth_vbox">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
@@ -108,8 +148,8 @@
           </object>
           <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>
@@ -123,8 +163,8 @@
             <property name="mnemonic_widget">eap_peap_inner_auth_combo</property>
           </object>
           <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"/>
           </packing>
@@ -144,8 +184,8 @@
           <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>
@@ -160,8 +200,8 @@
             <property name="mnemonic_widget">eap_peap_version_combo</property>
           </object>
           <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"/>
           </packing>
@@ -181,8 +221,8 @@
           <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>
diff --git a/panels/network/wireless-security/eap-method-tls.c b/panels/network/wireless-security/eap-method-tls.c
index 2069ccb..d88ecda 100644
--- a/panels/network/wireless-security/eap-method-tls.c
+++ b/panels/network/wireless-security/eap-method-tls.c
@@ -33,6 +33,8 @@
 #include "wireless-security.h"
 #include "helpers.h"
 
+#define SUBJECT_NOTE _("<will be filled automatically>")
+
 struct _EAPMethodTLS {
 	EAPMethod parent;
 
@@ -129,6 +131,10 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
 
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_subject_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_label"));
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
@@ -143,9 +149,11 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 {
 	EAPMethodTLS *method = (EAPMethodTLS *) parent;
 	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	NMSetting8021xCKScheme cert_scheme;
 	NMSetting8021x *s_8021x;
 	GtkWidget *widget;
 	char *ca_filename, *pk_filename, *cc_filename;
+	const char *subject;
 	const char *password = NULL;
 	GError *error = NULL;
 	const char *secret_flag_prop = NULL;
@@ -233,11 +241,20 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 			g_clear_error (&error);
 		}
 	} else {
-		if (!nm_setting_802_1x_set_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
-			g_warning ("Couldn't read CA certificate '%s': %s", ca_filename, error ? error->message : "(unknown)");
-			g_clear_error (&error);
+		cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+		if (ca_filename || cert_scheme != NM_SETTING_802_1X_CK_SCHEME_HASH) {
+			if (!nm_setting_802_1x_set_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+				g_warning ("Couldn't read CA certificate '%s': %s", ca_filename, error ? error->message : "(unknown)");
+				g_clear_error (&error);
+			}
 		}
 	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_subject_entry"));
+	g_assert (widget);
+	subject = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (subject && strlen (subject)  && g_strcmp0 (subject, SUBJECT_NOTE) != 0)
+		g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, subject, NULL);
 }
 
 static void
@@ -406,6 +423,37 @@ update_secrets (EAPMethod *parent, NMConnection *connection)
 	}
 }
 
+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_override_color (widget, GTK_STATE_FLAG_NORMAL, NULL);
+	}
+	return FALSE;
+}
+
+static gboolean
+subject_entry_focus_out_cb (GtkWidget *widget,
+                            GdkEvent  *event,
+                            gpointer user_data)
+{
+	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
+	GtkStyleContext *context;
+	GdkRGBA color;
+
+	if (!text || !strlen (text)) {
+		gtk_entry_set_text (GTK_ENTRY (widget), SUBJECT_NOTE);
+		context = gtk_widget_get_style_context (widget);
+		gtk_style_context_get_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
+		gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, &color);
+	}
+	return FALSE;
+}
+
 EAPMethodTLS *
 eap_method_tls_new (WirelessSecurity *ws_parent,
                     NMConnection *connection,
@@ -458,6 +506,31 @@ eap_method_tls_new (WirelessSecurity *ws_parent,
 	                  phase2 ? nm_setting_802_1x_get_phase2_ca_cert_scheme : nm_setting_802_1x_get_ca_cert_scheme,
 	                  phase2 ? nm_setting_802_1x_get_phase2_ca_cert_path : nm_setting_802_1x_get_ca_cert_path,
 	                  FALSE, FALSE);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_subject_entry"));
+	if (s_8021x) {
+		const char *text = nm_setting_802_1x_get_subject_match (s_8021x);
+		if (!text) {
+			GtkStyleContext *context;
+			GdkRGBA color;
+			context = gtk_widget_get_style_context (widget);
+			gtk_style_context_get_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
+			gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, &color);
+			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,
+		                  NULL);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
 	setup_filepicker (parent->builder, "eap_tls_private_key_button",
 	                  _("Choose your private key"),
 	                  ws_parent, parent, s_8021x,
@@ -496,6 +569,12 @@ eap_method_tls_new (WirelessSecurity *ws_parent,
 		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_button"));
 		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_not_required_checkbox"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_subject_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_subject_entry"));
+		gtk_widget_hide (widget);
 	}
 
 	return method;
diff --git a/panels/network/wireless-security/eap-method-tls.ui b/panels/network/wireless-security/eap-method-tls.ui
index 028e73e..ee4fe1b 100644
--- a/panels/network/wireless-security/eap-method-tls.ui
+++ b/panels/network/wireless-security/eap-method-tls.ui
@@ -10,7 +10,7 @@
       <object class="GtkTable" id="table8">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="n_rows">6</property>
+        <property name="n_rows">7</property>
         <property name="n_columns">2</property>
         <property name="column_spacing">6</property>
         <property name="row_spacing">6</property>
@@ -60,6 +60,35 @@
           </packing>
         </child>
         <child>
+          <object class="GtkLabel" id="eap_tls_subject_label">
+            <property name="visible">True</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">CA _subject</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_tls_subject_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_tls_subject_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <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="y_options"/>
+          </packing>
+        </child>
+        <child>
           <object class="GtkLabel" id="eap_tls_ca_cert_label">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
@@ -69,8 +98,8 @@
             <property name="mnemonic_widget">eap_tls_ca_cert_button</property>
           </object>
           <packing>
-            <property name="top_attach">2</property>
-            <property name="bottom_attach">3</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
             <property name="x_options">GTK_FILL</property>
             <property name="y_options"/>
           </packing>
@@ -83,8 +112,8 @@
           <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">3</property>
+            <property name="bottom_attach">4</property>
             <property name="x_options">GTK_FILL</property>
             <property name="y_options">GTK_FILL</property>
           </packing>
@@ -99,8 +128,8 @@
             <property name="mnemonic_widget">eap_tls_private_key_button</property>
           </object>
           <packing>
-            <property name="top_attach">3</property>
-            <property name="bottom_attach">4</property>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
             <property name="x_options">GTK_FILL</property>
             <property name="y_options"/>
           </packing>
@@ -113,8 +142,8 @@
           <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">4</property>
+            <property name="bottom_attach">5</property>
             <property name="x_options">GTK_FILL</property>
             <property name="y_options">GTK_FILL</property>
           </packing>
@@ -129,8 +158,8 @@
             <property name="mnemonic_widget">eap_tls_private_key_password_entry</property>
           </object>
           <packing>
-            <property name="top_attach">4</property>
-            <property name="bottom_attach">5</property>
+            <property name="top_attach">5</property>
+            <property name="bottom_attach">6</property>
             <property name="x_options">GTK_FILL</property>
             <property name="y_options"/>
           </packing>
@@ -145,8 +174,8 @@
           <packing>
             <property name="left_attach">1</property>
             <property name="right_attach">2</property>
-            <property name="top_attach">4</property>
-            <property name="bottom_attach">5</property>
+            <property name="top_attach">5</property>
+            <property name="bottom_attach">6</property>
             <property name="y_options"/>
           </packing>
         </child>
@@ -163,8 +192,8 @@
           <packing>
             <property name="left_attach">1</property>
             <property name="right_attach">2</property>
-            <property name="top_attach">5</property>
-            <property name="bottom_attach">6</property>
+            <property name="top_attach">6</property>
+            <property name="bottom_attach">7</property>
             <property name="x_options">GTK_FILL</property>
             <property name="y_options"/>
           </packing>
diff --git a/panels/network/wireless-security/eap-method-ttls.c b/panels/network/wireless-security/eap-method-ttls.c
index c21744a..6cba439 100644
--- a/panels/network/wireless-security/eap-method-ttls.c
+++ b/panels/network/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>")
+
 struct _EAPMethodTTLS {
 	EAPMethod parent;
 
@@ -93,6 +95,10 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
 
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_subject_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_label"));
 	g_assert (widget);
 	gtk_size_group_add_widget (group, widget);
@@ -117,6 +123,7 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 {
 	NMSetting8021x *s_8021x;
 	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	NMSetting8021xCKScheme cert_scheme;
 	GtkWidget *widget;
 	const char *text;
 	char *filename;
@@ -136,12 +143,21 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 	if (text && strlen (text))
 		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
 
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "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 = GTK_WIDGET (gtk_builder_get_object (parent->builder, "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)) {
-		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
-		g_clear_error (&error);
+	cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+	if (filename || cert_scheme != NM_SETTING_802_1X_CK_SCHEME_HASH) {
+		if (!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);
+		}
 	}
 
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
@@ -308,6 +324,37 @@ 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_override_color (widget, GTK_STATE_FLAG_NORMAL, NULL);
+	}
+	return FALSE;
+}
+
+static gboolean
+subject_entry_focus_out_cb (GtkWidget *widget,
+                            GdkEvent  *event,
+                            gpointer user_data)
+{
+	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
+	GtkStyleContext *context;
+	GdkRGBA color;
+
+	if (!text || !strlen (text)) {
+		gtk_entry_set_text (GTK_ENTRY (widget), SUBJECT_NOTE);
+		context = gtk_widget_get_style_context (widget);
+		gtk_style_context_get_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
+		gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, &color);
+	}
+	return FALSE;
+}
+
 EAPMethodTTLS *
 eap_method_ttls_new (WirelessSecurity *ws_parent,
                      NMConnection *connection,
@@ -361,6 +408,43 @@ eap_method_ttls_new (WirelessSecurity *ws_parent,
 		}
 	}
 
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_subject_entry"));
+	if (s_8021x) {
+		const char *text = nm_setting_802_1x_get_subject_match (s_8021x);
+		if (!text) {
+			GtkStyleContext *context;
+			GdkRGBA color;
+			context = gtk_widget_get_style_context (widget);
+			gtk_style_context_get_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
+			gtk_widget_override_color (widget, GTK_STATE_FLAG_NORMAL, &color);
+			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,
+		                  NULL);
+	}
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_note_label"));
+	gtk_widget_hide (widget);
+	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);
+			gtk_widget_show (widget);
+		}
+	}
+
 	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
 	if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
 		gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
@@ -376,10 +460,16 @@ eap_method_ttls_new (WirelessSecurity *ws_parent,
 		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
 		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_subject_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_subject_entry"));
+		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_label"));
 		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
 		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_note_label"));
+		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_label"));
 		gtk_widget_hide (widget);
 		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
diff --git a/panels/network/wireless-security/eap-method-ttls.ui b/panels/network/wireless-security/eap-method-ttls.ui
index 39465cf..52e026a 100644
--- a/panels/network/wireless-security/eap-method-ttls.ui
+++ b/panels/network/wireless-security/eap-method-ttls.ui
@@ -21,7 +21,7 @@
       <object class="GtkTable" id="table10">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="n_rows">4</property>
+        <property name="n_rows">6</property>
         <property name="n_columns">2</property>
         <property name="column_spacing">6</property>
         <property name="row_spacing">6</property>
@@ -52,6 +52,35 @@
           </packing>
         </child>
         <child>
+          <object class="GtkLabel" id="eap_ttls_subject_label">
+            <property name="visible">True</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Subject</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_ttls_subject_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_ttls_subject_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <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>
           <object class="GtkLabel" id="eap_ttls_ca_cert_label">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
@@ -61,8 +90,8 @@
             <property name="mnemonic_widget">eap_ttls_ca_cert_button</property>
           </object>
           <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"/>
           </packing>
@@ -75,13 +104,24 @@
           <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>
         </child>
         <child>
+          <object class="GtkLabel" id="eap_ttls_note_label">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">Note</property>
+          </object>
+          <packing>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkLabel" id="eap_ttls_inner_auth_label">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
@@ -91,8 +131,8 @@
             <property name="mnemonic_widget">eap_ttls_inner_auth_combo</property>
           </object>
           <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"/>
           </packing>
@@ -112,8 +152,8 @@
           <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>
@@ -129,8 +169,8 @@
           </object>
           <packing>
             <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>
           </packing>
         </child>
diff --git a/panels/network/wireless-security/wireless-security.c b/panels/network/wireless-security/wireless-security.c
index a8468bc..dd8eedb 100644
--- a/panels/network/wireless-security/wireless-security.c
+++ b/panels/network/wireless-security/wireless-security.c
@@ -474,16 +474,25 @@ ws_802_1x_fill_connection (WirelessSecurity *sec,
 	GtkWidget *widget;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wireless_sec;
-	NMSetting8021x *s_8021x;
+	NMSetting8021x *s_8021x, *old_s_8021x;
+	NMSetting8021xCKScheme cert_scheme;
 	EAPMethod *eap = NULL;
 	GtkTreeModel *model;
 	GtkTreeIter iter;
+	char *subject, *cert_hash;
+	char *old_hash = NULL;
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wireless);
 
 	g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
 
+	old_s_8021x = nm_connection_get_setting_802_1x (connection);
+	if (old_s_8021x &&
+	    nm_setting_802_1x_get_ca_cert_scheme (old_s_8021x) == NM_SETTING_802_1X_CK_SCHEME_HASH) {
+		old_hash = g_strdup (nm_setting_802_1x_get_ca_cert_hash (old_s_8021x));
+	}
+
 	/* Blow away the old wireless security setting by adding a clear one */
 	s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
 	nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
@@ -492,6 +501,21 @@ ws_802_1x_fill_connection (WirelessSecurity *sec,
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
 	nm_connection_add_setting (connection, (NMSetting *) s_8021x);
 
+	if (old_hash) {
+		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+		GError *error = NULL;
+		if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+		                                    old_hash,
+		                                    NM_SETTING_802_1X_CK_SCHEME_HASH,
+		                                    &format,
+		                                    &error)) {
+			g_warning ("Couldn't set CA certificate '%s': %s", old_hash,
+			           error ? error->message : "(unknown)");
+			g_error_free (error);
+		}
+		g_free (old_hash);
+	}
+
 	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
 	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
@@ -500,6 +524,26 @@ ws_802_1x_fill_connection (WirelessSecurity *sec,
 
 	eap_method_fill_connection (eap, connection);
 	eap_method_unref (eap);
+
+	/* Fetch subject and cert_hash from connection */
+	subject = (char *)g_object_get_data (G_OBJECT (connection), NMA_SERVER_SUBJECT);
+	if (subject && !nm_setting_802_1x_get_subject_match (s_8021x))
+		g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, subject, NULL);
+
+	cert_hash = (char *)g_object_get_data (G_OBJECT (connection), NMA_SERVER_CERT_HASH);
+	cert_scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
+	if (cert_hash && cert_scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+		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_warning ("Couldn't set CA certificate '%s': %s", cert_hash, error ? error->message : "(unknown)");
+			g_error_free (error);
+		}
+	}
 }
 
 void
diff --git a/panels/network/wireless-security/wireless-security.h b/panels/network/wireless-security/wireless-security.h
index 23a725b..ede145c 100644
--- a/panels/network/wireless-security/wireless-security.h
+++ b/panels/network/wireless-security/wireless-security.h
@@ -28,6 +28,9 @@
 
 #include <nm-connection.h>
 
+#define NMA_SERVER_SUBJECT "nma-server-subject"
+#define NMA_SERVER_CERT_HASH "mna-server-cert-hash"
+
 typedef struct _WirelessSecurity WirelessSecurity;
 
 typedef void (*WSChangedFunc) (WirelessSecurity *sec, gpointer user_data);
-- 
2.1.4