File nm-settings-subject-match.patch of Package NetworkManager.import5373

diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index 6c2b9fc..d477381 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -26,10 +26,15 @@ global:
 	nm_connection_to_hash;
 	nm_connection_update_secrets;
 	nm_connection_verify;
+	nm_setting_802_1x_add_altsubject_match;
 	nm_setting_802_1x_add_eap_method;
+	nm_setting_802_1x_add_phase2_altsubject_match;
+	nm_setting_802_1x_clear_altsubject_matches;
 	nm_setting_802_1x_clear_eap_methods;
+	nm_setting_802_1x_clear_phase2_altsubject_matches;
 	nm_setting_802_1x_error_get_type;
 	nm_setting_802_1x_error_quark;
+	nm_setting_802_1x_get_altsubject_match;
 	nm_setting_802_1x_get_anonymous_identity;
 	nm_setting_802_1x_get_ca_cert;
 	nm_setting_802_1x_get_ca_cert_blob;
@@ -46,11 +51,14 @@ global:
 	nm_setting_802_1x_set_client_cert;
 	nm_setting_802_1x_get_eap_method;
 	nm_setting_802_1x_get_identity;
+	nm_setting_802_1x_get_num_altsubject_matches;
 	nm_setting_802_1x_get_num_eap_methods;
+	nm_setting_802_1x_get_num_phase2_altsubject_matches;
 	nm_setting_802_1x_get_password;
 	nm_setting_802_1x_get_phase1_fast_provisioning;
 	nm_setting_802_1x_get_phase1_peaplabel;
 	nm_setting_802_1x_get_phase1_peapver;
+	nm_setting_802_1x_get_phase2_altsubject_match;
 	nm_setting_802_1x_get_phase2_auth;
 	nm_setting_802_1x_get_phase2_autheap;
 	nm_setting_802_1x_get_phase2_ca_cert;
@@ -75,6 +83,7 @@ global:
 	nm_setting_802_1x_get_phase2_private_key_scheme;
 	nm_setting_802_1x_get_phase2_private_key_type;
 	nm_setting_802_1x_set_phase2_private_key;
+	nm_setting_802_1x_get_phase2_subject_match;
 	nm_setting_802_1x_get_pin;
 	nm_setting_802_1x_get_private_key;
 	nm_setting_802_1x_get_private_key_blob;
@@ -86,10 +95,13 @@ global:
 	nm_setting_802_1x_get_private_key_type;
 	nm_setting_802_1x_set_private_key;
 	nm_setting_802_1x_get_psk;
+	nm_setting_802_1x_get_subject_match;
 	nm_setting_802_1x_get_system_ca_certs;
 	nm_setting_802_1x_get_type;
 	nm_setting_802_1x_new;
+	nm_setting_802_1x_remove_altsubject_match;
 	nm_setting_802_1x_remove_eap_method;
+	nm_setting_802_1x_remove_phase2_altsubject_match;
 	nm_setting_bluetooth_error_get_type;
 	nm_setting_bluetooth_error_quark;
 	nm_setting_bluetooth_get_type;
diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c
index eea6ba5..a322aa7 100644
--- a/libnm-util/nm-setting-8021x.c
+++ b/libnm-util/nm-setting-8021x.c
@@ -115,6 +115,8 @@ typedef struct {
 	char *anonymous_identity;
 	GByteArray *ca_cert;
 	char *ca_path;
+	char *subject_match;
+	GSList *altsubject_matches;
 	GByteArray *client_cert;
 	char *phase1_peapver;
 	char *phase1_peaplabel;
@@ -123,6 +125,8 @@ typedef struct {
 	char *phase2_autheap;
 	GByteArray *phase2_ca_cert;
 	char *phase2_ca_path;
+	char *phase2_subject_match;
+	GSList *phase2_altsubject_matches;
 	GByteArray *phase2_client_cert;
 	char *password;
 	char *pin;
@@ -141,6 +145,8 @@ enum {
 	PROP_ANONYMOUS_IDENTITY,
 	PROP_CA_CERT,
 	PROP_CA_PATH,
+	PROP_SUBJECT_MATCH,
+	PROP_ALTSUBJECT_MATCHES,
 	PROP_CLIENT_CERT,
 	PROP_PHASE1_PEAPVER,
 	PROP_PHASE1_PEAPLABEL,
@@ -149,6 +155,8 @@ enum {
 	PROP_PHASE2_AUTHEAP,
 	PROP_PHASE2_CA_CERT,
 	PROP_PHASE2_CA_PATH,
+	PROP_PHASE2_SUBJECT_MATCH,
+	PROP_PHASE2_ALTSUBJECT_MATCHES,
 	PROP_PHASE2_CLIENT_CERT,
 	PROP_PASSWORD,
 	PROP_PRIVATE_KEY,
@@ -616,6 +624,135 @@ nm_setting_802_1x_set_ca_cert_from_file (NMSetting8021x *setting,
 }
 
 /**
+ * nm_setting_802_1x_get_subject_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:subject-match property. This is the
+ * substring to be matched against the subject of the authentication
+ * server certificate, or NULL no subject verification is to be
+ * performed.
+ **/
+const char *
+nm_setting_802_1x_get_subject_match (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->subject_match;
+}
+
+/**
+ * nm_setting_802_1x_get_num_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the number of entries in the
+ * #NMSetting8021x:altsubject-matches property of this setting.
+ *
+ * Returns: the number of altsubject-matches entries.
+ **/
+guint32
+nm_setting_802_1x_get_num_altsubject_matches (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
+
+	return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->altsubject_matches);
+}
+
+/**
+ * nm_setting_802_1x_get_altsubject_match:
+ * @setting: the #NMSettingConnection
+ * @i: the zero-based index of the array of altSubjectName matches
+ *
+ * Returns the altSubjectName match at index @i.
+ *
+ * Returns: the altSubjectName match at index @i
+ **/
+const char *
+nm_setting_802_1x_get_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+	NMSetting8021xPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	g_return_val_if_fail (i <= g_slist_length (priv->altsubject_matches), NULL);
+
+	return (const char *) g_slist_nth_data (priv->altsubject_matches, i);
+}
+
+/**
+ * nm_setting_802_1x_add_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @altsubject_match: the altSubjectName to allow for this connection
+ *
+ * Adds an allowed alternate subject name match.  Until at least one
+ * match is added, the altSubjectName of the remote authentication
+ * server is not verified.
+ *
+ * Returns: TRUE if the alternative subject name match was
+ *  successfully added, FALSE if it was already allowed.
+ **/
+gboolean
+nm_setting_802_1x_add_altsubject_match (NMSetting8021x *setting,
+										const char *altsubject_match)
+{
+	NMSetting8021xPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+	g_return_val_if_fail (altsubject_match != NULL, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	for (iter = priv->altsubject_matches; iter; iter = g_slist_next (iter)) {
+		if (!strcmp (altsubject_match, (char *) iter->data))
+			return FALSE;
+	}
+
+	priv->altsubject_matches = g_slist_append (priv->altsubject_matches, g_strdup (altsubject_match));
+	return TRUE;
+}
+
+/**
+ * nm_setting_802_1x_remove_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the altSubjectName match to remove
+ *
+ * Removes the allowed altSubjectName at the specified index.
+ **/
+void
+nm_setting_802_1x_remove_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+	NMSetting8021xPrivate *priv;
+	GSList *elt;
+
+	g_return_if_fail (NM_IS_SETTING_802_1X (setting));
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	elt = g_slist_nth (priv->altsubject_matches, i);
+	g_return_if_fail (elt != NULL);
+
+	g_free (elt->data);
+	priv->altsubject_matches = g_slist_delete_link (priv->altsubject_matches, elt);
+}
+
+/**
+ * nm_setting_802_1x_clear_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Clears all altSubjectName matches.
+ **/
+void
+nm_setting_802_1x_clear_altsubject_matches (NMSetting8021x *setting)
+{
+	NMSetting8021xPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_802_1X (setting));
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	nm_utils_slist_free (priv->altsubject_matches, g_free);
+	priv->altsubject_matches = NULL;
+}
+
+/**
  * nm_setting_802_1x_get_client_cert_scheme:
  * @setting: the #NMSetting8021x
  *
@@ -1156,6 +1293,137 @@ nm_setting_802_1x_set_phase2_ca_cert_from_file (NMSetting8021x *setting,
 	return success;
 }
 
+/*
+ * nm_setting_802_1x_get_phase2_subject_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:phase2-subject-match property. This is
+ * the substring to be matched against the subject of the "phase 2"
+ * authentication server certificate, or NULL no subject verification
+ * is to be performed.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_subject_match (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_subject_match;
+}
+
+/**
+ * nm_setting_802_1x_get_num_phase2_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the number of entries in the
+ * #NMSetting8021x:phase2-altsubject-matches property of this setting.
+ *
+ * Returns: the number of phase2-altsubject-matches entries.
+ **/
+guint32
+nm_setting_802_1x_get_num_phase2_altsubject_matches (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
+
+	return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_altsubject_matches);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_altsubject_match:
+ * @setting: the #NMSettingConnection
+ * @i: the zero-based index of the array of "phase 2" altSubjectName matches
+ *
+ * Returns the "phase 2" altSubjectName match at index @i.
+ *
+ * Returns: the "phase 2" altSubjectName match at index @i
+ **/
+const char *
+nm_setting_802_1x_get_phase2_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+	NMSetting8021xPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	g_return_val_if_fail (i <= g_slist_length (priv->phase2_altsubject_matches), NULL);
+
+	return (const char *) g_slist_nth_data (priv->phase2_altsubject_matches, i);
+}
+
+/**
+ * nm_setting_802_1x_add_phase2_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @altsubject_match: the "phase 2" altSubjectName to allow for this
+ * connection
+ *
+ * Adds an allowed alternate subject name match for "phase 2".  Until
+ * at least one match is added, the altSubjectName of the "phase 2"
+ * remote authentication server is not verified.
+ *
+ * Returns: TRUE if the "phase 2" alternative subject name match was
+ *  successfully added, FALSE if it was already allowed.
+ **/
+gboolean
+nm_setting_802_1x_add_phase2_altsubject_match (NMSetting8021x *setting,
+											   const char *phase2_altsubject_match)
+{
+	NMSetting8021xPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+	g_return_val_if_fail (phase2_altsubject_match != NULL, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next (iter)) {
+		if (!strcmp (phase2_altsubject_match, (char *) iter->data))
+			return FALSE;
+	}
+
+	priv->phase2_altsubject_matches = g_slist_append (priv->altsubject_matches,
+													  g_strdup (phase2_altsubject_match));
+	return TRUE;
+}
+
+/**
+ * nm_setting_802_1x_remove_phase2_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the "phase 2" altSubjectName match to remove
+ *
+ * Removes the allowed "phase 2" altSubjectName at the specified index.
+ **/
+void
+nm_setting_802_1x_remove_phase2_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+	NMSetting8021xPrivate *priv;
+	GSList *elt;
+
+	g_return_if_fail (NM_IS_SETTING_802_1X (setting));
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	elt = g_slist_nth (priv->phase2_altsubject_matches, i);
+	g_return_if_fail (elt != NULL);
+
+	g_free (elt->data);
+	priv->phase2_altsubject_matches = g_slist_delete_link (priv->phase2_altsubject_matches, elt);
+}
+
+/**
+ * nm_setting_802_1x_clear_phase2_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Clears all "phase 2" altSubjectName matches.
+ **/
+void
+nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting)
+{
+	NMSetting8021xPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_802_1X (setting));
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	nm_utils_slist_free (priv->phase2_altsubject_matches, g_free);
+	priv->phase2_altsubject_matches = NULL;
+}
+
 /**
  * nm_setting_802_1x_get_phase2_client_cert_scheme:
  * @setting: the #NMSetting8021x
@@ -2670,15 +2938,19 @@ finalize (GObject *object)
 	g_free (priv->identity);
 	g_free (priv->anonymous_identity);
 	g_free (priv->ca_path);
+	g_free (priv->subject_match);
 	g_free (priv->phase1_peapver);
 	g_free (priv->phase1_peaplabel);
 	g_free (priv->phase1_fast_provisioning);
 	g_free (priv->phase2_auth);
 	g_free (priv->phase2_autheap);
 	g_free (priv->phase2_ca_path);
+	g_free (priv->phase2_subject_match);
 	g_free (priv->password);
 
 	nm_utils_slist_free (priv->eap, g_free);
+	nm_utils_slist_free (priv->altsubject_matches, g_free);
+	nm_utils_slist_free (priv->phase2_altsubject_matches, g_free);
 
 	if (priv->ca_cert)
 		g_byte_array_free (priv->ca_cert, TRUE);
@@ -2753,6 +3025,14 @@ set_property (GObject *object, guint prop_id,
 		g_free (priv->ca_path);
 		priv->ca_path = g_value_dup_string (value);
 		break;
+	case PROP_SUBJECT_MATCH:
+		g_free (priv->subject_match);
+		priv->subject_match = g_value_dup_string (value);
+		break;
+	case PROP_ALTSUBJECT_MATCHES:
+		nm_utils_slist_free (priv->altsubject_matches, g_free);
+		priv->altsubject_matches = g_value_dup_boxed (value);
+		break;
 	case PROP_CLIENT_CERT:
 		if (priv->client_cert) {
 			g_byte_array_free (priv->client_cert, TRUE);
@@ -2801,6 +3081,14 @@ set_property (GObject *object, guint prop_id,
 		g_free (priv->phase2_ca_path);
 		priv->phase2_ca_path = g_value_dup_string (value);
 		break;
+	case PROP_PHASE2_SUBJECT_MATCH:
+		g_free (priv->phase2_subject_match);
+		priv->phase2_subject_match = g_value_dup_string (value);
+		break;
+	case PROP_PHASE2_ALTSUBJECT_MATCHES:
+		nm_utils_slist_free (priv->phase2_altsubject_matches, g_free);
+		priv->phase2_altsubject_matches = g_value_dup_boxed (value);
+		break;
 	case PROP_PHASE2_CLIENT_CERT:
 		if (priv->phase2_client_cert) {
 			g_byte_array_free (priv->phase2_client_cert, TRUE);
@@ -2881,6 +3169,12 @@ get_property (GObject *object, guint prop_id,
 	case PROP_CA_PATH:
 		g_value_set_string (value, priv->ca_path);
 		break;
+	case PROP_SUBJECT_MATCH:
+		g_value_set_string (value, priv->subject_match);
+		break;
+	case PROP_ALTSUBJECT_MATCHES:
+		g_value_set_boxed (value, priv->altsubject_matches);
+		break;
 	case PROP_CLIENT_CERT:
 		g_value_set_boxed (value, priv->client_cert);
 		break;
@@ -2905,6 +3199,12 @@ get_property (GObject *object, guint prop_id,
 	case PROP_PHASE2_CA_PATH:
 		g_value_set_string (value, priv->phase2_ca_path);
 		break;
+	case PROP_PHASE2_SUBJECT_MATCH:
+		g_value_set_string (value, priv->phase2_subject_match);
+		break;
+	case PROP_PHASE2_ALTSUBJECT_MATCHES:
+		g_value_set_boxed (value, priv->phase2_altsubject_matches);
+		break;
 	case PROP_PHASE2_CLIENT_CERT:
 		g_value_set_boxed (value, priv->phase2_client_cert);
 		break;
@@ -3054,6 +3354,47 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
 
 	/**
+	 * NMSetting8021x:subject-match:
+	 *
+	 * Substring to be matched against the subject of the certificate
+	 * presented by the authentication server. When unset, no
+	 * verification of the authentication server certificate's subject
+	 * is performed.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SUBJECT_MATCH,
+		 g_param_spec_string (NM_SETTING_802_1X_SUBJECT_MATCH,
+							  "Subject match",
+							  "Substring to be matched against the subject of "
+							  "the certificate presented by the authentication "
+							  "server. When unset, no verification of the "
+							  "authentication server certificate's subject is "
+							  "performed.",
+							  NULL,
+							  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSetting8021x:altsubject-matches:
+	 *
+	 * List of strings to be matched against the altSubjectName of the
+	 * certificate presented by the authentication server. If the list
+	 * is empty, no verification of the server certificate's
+	 * altSubjectName is performed.
+	 **/
+	 g_object_class_install_property
+		 (object_class, PROP_ALTSUBJECT_MATCHES,
+		  _nm_param_spec_specialized (NM_SETTING_802_1X_ALTSUBJECT_MATCHES,
+									  "altSubjectName matches",
+									  "List of strings to be matched against "
+									  "the altSubjectName of the certificate "
+									  "presented by the authentication server. "
+									  "If the list is empty, no verification "
+									  "of the server certificate's "
+									  "altSubjectName is performed.",
+									  DBUS_TYPE_G_LIST_OF_STRING,
+									  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
 	 * NMSetting8021x:client-cert:
 	 *
 	 * Contains the client certificate if used by the EAP method specified in
@@ -3246,6 +3587,51 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
 
 	/**
+	 * NMSetting8021x:phase2-subject-match:
+	 *
+	 * Substring to be matched against the subject of the certificate
+	 * presented by the authentication server during the inner "phase
+	 * 2" authentication. When unset, no verification of the
+	 * authentication server certificate's subject is performed.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_SUBJECT_MATCH,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH,
+							  "Phase2 subject match",
+							  "Substring to be matched against the subject of "
+							  "the certificate presented by the authentication "
+							  "server during the inner 'phase2' "
+							  "authentication. When unset, no verification of "
+							  "the authentication server certificate's subject "
+							  "is performed.",
+							  NULL,
+							  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSetting8021x:phase2-altsubject-matches:
+	 *
+	 * List of strings to be matched against the altSubjectName of the
+	 * certificate presented by the authentication server during the
+	 * inner "phase 2" authentication. If the list is empty, no
+	 * verification of the server certificate's altSubjectName is
+	 * performed.
+	 **/
+	 g_object_class_install_property
+		 (object_class, PROP_PHASE2_ALTSUBJECT_MATCHES,
+		  _nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES,
+									  "altSubjectName matches",
+									  "List of strings to be matched against "
+									  "List of strings to be matched against "
+									  "the altSubjectName of the certificate "
+									  "presented by the authentication server "
+									  "during the inner 'phase 2' "
+									  "authentication. If the list is empty, no "
+									  "verification of the server certificate's "
+									  "altSubjectName is performed.",
+									  DBUS_TYPE_G_LIST_OF_STRING,
+									  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
 	 * NMSetting8021x:phase2-client-cert:
 	 *
 	 * Contains the client certificate if used by the EAP method specified in
diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h
index 7ee868a..930c1da 100644
--- a/libnm-util/nm-setting-8021x.h
+++ b/libnm-util/nm-setting-8021x.h
@@ -71,6 +71,8 @@ GQuark nm_setting_802_1x_error_quark (void);
 #define NM_SETTING_802_1X_ANONYMOUS_IDENTITY "anonymous-identity"
 #define NM_SETTING_802_1X_CA_CERT "ca-cert"
 #define NM_SETTING_802_1X_CA_PATH "ca-path"
+#define NM_SETTING_802_1X_SUBJECT_MATCH "subject-match"
+#define NM_SETTING_802_1X_ALTSUBJECT_MATCHES "altsubject-matches"
 #define NM_SETTING_802_1X_CLIENT_CERT "client-cert"
 #define NM_SETTING_802_1X_PHASE1_PEAPVER "phase1-peapver"
 #define NM_SETTING_802_1X_PHASE1_PEAPLABEL "phase1-peaplabel"
@@ -79,6 +81,8 @@ GQuark nm_setting_802_1x_error_quark (void);
 #define NM_SETTING_802_1X_PHASE2_AUTHEAP "phase2-autheap"
 #define NM_SETTING_802_1X_PHASE2_CA_CERT "phase2-ca-cert"
 #define NM_SETTING_802_1X_PHASE2_CA_PATH "phase2-ca-path"
+#define NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH "phase2-subject-match"
+#define NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES "phase2-altsubject-matches"
 #define NM_SETTING_802_1X_PHASE2_CLIENT_CERT "phase2-client-cert"
 #define NM_SETTING_802_1X_PASSWORD "password"
 #define NM_SETTING_802_1X_PRIVATE_KEY "private-key"
@@ -154,6 +158,17 @@ gboolean               nm_setting_802_1x_set_ca_cert                 (NMSetting8
                                                                       NMSetting8021xCKFormat *out_format,
                                                                       GError **error);
 
+const char *      nm_setting_802_1x_get_subject_match                (NMSetting8021x *setting);
+
+guint32           nm_setting_802_1x_get_num_altsubject_matches       (NMSetting8021x *setting);
+const char *      nm_setting_802_1x_get_altsubject_match             (NMSetting8021x *setting,
+																	  guint32 i);
+gboolean          nm_setting_802_1x_add_altsubject_match             (NMSetting8021x *setting,
+																	  const char *altsubject_match);
+void              nm_setting_802_1x_remove_altsubject_match          (NMSetting8021x *setting,
+																	  guint32 i);
+void              nm_setting_802_1x_clear_altsubject_matches         (NMSetting8021x *setting);
+
 NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme      (NMSetting8021x *setting);
 const GByteArray *     nm_setting_802_1x_get_client_cert_blob        (NMSetting8021x *setting);
 const char *           nm_setting_802_1x_get_client_cert_path        (NMSetting8021x *setting);
@@ -182,6 +197,17 @@ gboolean               nm_setting_802_1x_set_phase2_ca_cert          (NMSetting8
                                                                       NMSetting8021xCKFormat *out_format,
                                                                       GError **error);
 
+const char *      nm_setting_802_1x_get_phase2_subject_match         (NMSetting8021x *setting);
+
+guint32           nm_setting_802_1x_get_num_phase2_altsubject_matches   (NMSetting8021x *setting);
+const char *      nm_setting_802_1x_get_phase2_altsubject_match         (NMSetting8021x *setting,
+																		 guint32 i);
+gboolean          nm_setting_802_1x_add_phase2_altsubject_match         (NMSetting8021x *setting,
+																		 const char *phase2_altsubject_match);
+void              nm_setting_802_1x_remove_phase2_altsubject_match      (NMSetting8021x *setting,
+																		 guint32 i);
+void              nm_setting_802_1x_clear_phase2_altsubject_matches     (NMSetting8021x *setting);
+
 NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme   (NMSetting8021x *setting);
 const GByteArray *     nm_setting_802_1x_get_phase2_client_cert_blob     (NMSetting8021x *setting);
 const char *           nm_setting_802_1x_get_phase2_client_cert_path     (NMSetting8021x *setting);
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index e33f67a..4e3ecab 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -451,7 +451,7 @@ add_string_val (NMSupplicantConfig *self,
 	return success;
 }
 
-#define ADD_STRING_LIST_VAL(setting, setting_name, field, field_plural, name, ucase, secret) \
+#define ADD_STRING_LIST_VAL(setting, setting_name, field, field_plural, name, separator, ucase, secret) \
 	if (nm_setting_##setting_name##_get_num_##field_plural (setting)) { \
 		guint32 k; \
 		GString *str = g_string_new (NULL); \
@@ -460,7 +460,7 @@ add_string_val (NMSupplicantConfig *self,
 			if (!str->len) { \
 				g_string_append (str, item); \
 			} else { \
-				g_string_append_c (str, ' '); \
+				g_string_append_c (str, separator); \
 				g_string_append (str, item); \
 			} \
 		} \
@@ -636,9 +636,9 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
 	if (   !strcmp (key_mgmt, "wpa-none")
 	    || !strcmp (key_mgmt, "wpa-psk")
 	    || !strcmp (key_mgmt, "wpa-eap")) {
-		ADD_STRING_LIST_VAL (setting, wireless_security, proto, protos, "proto", TRUE, FALSE);
-		ADD_STRING_LIST_VAL (setting, wireless_security, pairwise, pairwise, "pairwise", TRUE, FALSE);
-		ADD_STRING_LIST_VAL (setting, wireless_security, group, groups, "group", TRUE, FALSE);
+		ADD_STRING_LIST_VAL (setting, wireless_security, proto, protos, "proto", ' ', TRUE, FALSE);
+		ADD_STRING_LIST_VAL (setting, wireless_security, pairwise, pairwise, "pairwise", ' ', TRUE, FALSE);
+		ADD_STRING_LIST_VAL (setting, wireless_security, group, groups, "group", ' ', TRUE, FALSE);
 	}
 
 	/* WEP keys if required */
@@ -733,7 +733,7 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 			return FALSE;
 	}
 
-	ADD_STRING_LIST_VAL (setting, 802_1x, eap_method, eap_methods, "eap", TRUE, FALSE);
+	ADD_STRING_LIST_VAL (setting, 802_1x, eap_method, eap_methods, "eap", ' ', TRUE, FALSE);
 
 	/* Check for PEAP + GTC */
 	num_eap = nm_setting_802_1x_get_num_eap_methods (setting);
@@ -855,6 +855,18 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 		break;
 	}
 
+	/* Subject match */
+	value = nm_setting_802_1x_get_subject_match (setting);
+	if (!add_string_val (self, value, "subject_match", FALSE, FALSE))
+		return FALSE;
+	value = nm_setting_802_1x_get_phase2_subject_match (setting);
+	if (!add_string_val (self, value, "subject_match2", FALSE, FALSE))
+		return FALSE;
+
+	/* altSubjectName match */
+	ADD_STRING_LIST_VAL (setting, 802_1x, altsubject_match, altsubject_matches, "altsubject_match", ';', FALSE, FALSE);
+	ADD_STRING_LIST_VAL (setting, 802_1x, phase2_altsubject_match, phase2_altsubject_matches, "altsubject_match2", ';', FALSE, FALSE);
+
 	/* Private key */
 	added = FALSE;
 	switch (nm_setting_802_1x_get_private_key_scheme (setting)) {
diff --git a/src/supplicant-manager/nm-supplicant-settings-verify.c b/src/supplicant-manager/nm-supplicant-settings-verify.c
index c65af4d..2336ad7 100644
--- a/src/supplicant-manager/nm-supplicant-settings-verify.c
+++ b/src/supplicant-manager/nm-supplicant-settings-verify.c
@@ -102,6 +102,8 @@ static const struct Opt opt_table[] = {
 	{ "identity",           TYPE_BYTES,   0, 0, FALSE,  NULL },
 	{ "password",           TYPE_BYTES,   0, 0, FALSE,  NULL },
 	{ "ca_path",            TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "subject_match",      TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "altsubject_match",   TYPE_BYTES,   0, 0, FALSE,  NULL },
 	{ "ca_cert",            TYPE_BYTES,   0, 65536, FALSE,  NULL },
 	{ "client_cert",        TYPE_BYTES,   0, 65536, FALSE,  NULL },
 	{ "private_key",        TYPE_BYTES,   0, 65536, FALSE,  NULL },
@@ -110,6 +112,8 @@ static const struct Opt opt_table[] = {
 	{ "phase2",             TYPE_KEYWORD, 0, 0, TRUE, phase2_allowed },
 	{ "anonymous_identity", TYPE_BYTES,   0, 0, FALSE,  NULL },
 	{ "ca_path2",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "subject_match2",     TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "altsubject_match2",  TYPE_BYTES,   0, 0, FALSE,  NULL },
 	{ "ca_cert2",           TYPE_BYTES,   0, 65536, FALSE,  NULL },
 	{ "client_cert2",       TYPE_BYTES,   0, 65536, FALSE,  NULL },
 	{ "private_key2",       TYPE_BYTES,   0, 65536, FALSE,  NULL },