summary refs log tree commit diff
path: root/src/libnm-core-impl/nm-setting-8021x.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2021-10-01 23:05:04 +0200
committerMichael Biebl <biebl@debian.org>2021-10-01 23:05:04 +0200
commite74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch)
tree3469f17ea9af91f7ff169b890633bda68b0cf76e /src/libnm-core-impl/nm-setting-8021x.c
parentbfe522304da217296e2a61040f58e35ec5d6f3f2 (diff)
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'src/libnm-core-impl/nm-setting-8021x.c')
-rw-r--r--src/libnm-core-impl/nm-setting-8021x.c4655
1 files changed, 4655 insertions, 0 deletions
diff --git a/src/libnm-core-impl/nm-setting-8021x.c b/src/libnm-core-impl/nm-setting-8021x.c
new file mode 100644
index 00000000..6ddbd680
--- /dev/null
+++ b/src/libnm-core-impl/nm-setting-8021x.c
@@ -0,0 +1,4655 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2007 - 2013 Red Hat, Inc.
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ */
+
+#include "libnm-core-impl/nm-default-libnm-core.h"
+
+#include "nm-setting-8021x.h"
+
+#include "libnm-glib-aux/nm-secret-utils.h"
+#include "nm-utils.h"
+#include "nm-crypto.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-8021x
+ * @short_description: Describes 802.1x-authenticated connection properties
+ *
+ * The #NMSetting8021x object is a #NMSetting subclass that describes
+ * properties necessary for connection to 802.1x-authenticated networks, such as
+ * WPA and WPA2 Enterprise Wi-Fi networks and wired 802.1x networks.  802.1x
+ * connections typically use certificates and/or EAP authentication methods to
+ * securely verify, identify, and authenticate the client to the network itself,
+ * instead of simply relying on a widely shared static key.
+ *
+ * It's a good idea to read up on wpa_supplicant configuration before using this
+ * setting extensively, since most of the options here correspond closely with
+ * the relevant wpa_supplicant configuration options.
+ *
+ * Furthermore, to get a good idea of 802.1x, EAP, TLS, TTLS, etc and their
+ * applications to Wi-Fi and wired networks, you'll want to get copies of the
+ * following books.
+ *
+ *  802.11 Wireless Networks: The Definitive Guide, Second Edition
+ *       Author: Matthew Gast
+ *       ISBN: 978-0596100520
+ *
+ *  Cisco Wireless LAN Security
+ *       Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky
+ *       ISBN: 978-1587051548
+ **/
+
+/*****************************************************************************/
+
+static NMSetting8021xCKFormat
+_crypto_format_to_ck(NMCryptoFileFormat format)
+{
+    G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_UNKNOWN
+                     == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_UNKNOWN));
+    G_STATIC_ASSERT(
+        (NM_SETTING_802_1X_CK_FORMAT_X509 == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_X509));
+    G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_RAW_KEY
+                     == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_RAW_KEY));
+    G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_PKCS12
+                     == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_PKCS12));
+
+    nm_assert(NM_IN_SET(format,
+                        NM_CRYPTO_FILE_FORMAT_UNKNOWN,
+                        NM_CRYPTO_FILE_FORMAT_X509,
+                        NM_CRYPTO_FILE_FORMAT_RAW_KEY,
+                        NM_CRYPTO_FILE_FORMAT_PKCS12));
+    return (NMSetting8021xCKFormat) format;
+}
+
+/*****************************************************************************/
+
+typedef void (*EAPMethodNeedSecretsFunc)(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2);
+
+typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, gboolean phase2, GError **error);
+
+typedef struct {
+    const char *             method;
+    EAPMethodNeedSecretsFunc ns_func;
+    EAPMethodValidateFunc    v_func;
+} EAPMethodsTable;
+
+static const EAPMethodsTable eap_methods_table[];
+
+/*****************************************************************************/
+
+NM_GOBJECT_PROPERTIES_DEFINE(NMSetting8021x,
+                             PROP_EAP,
+                             PROP_IDENTITY,
+                             PROP_ANONYMOUS_IDENTITY,
+                             PROP_PAC_FILE,
+                             PROP_CA_CERT,
+                             PROP_CA_CERT_PASSWORD,
+                             PROP_CA_CERT_PASSWORD_FLAGS,
+                             PROP_CA_PATH,
+                             PROP_SUBJECT_MATCH,
+                             PROP_ALTSUBJECT_MATCHES,
+                             PROP_DOMAIN_SUFFIX_MATCH,
+                             PROP_DOMAIN_MATCH,
+                             PROP_CLIENT_CERT,
+                             PROP_CLIENT_CERT_PASSWORD,
+                             PROP_CLIENT_CERT_PASSWORD_FLAGS,
+                             PROP_PHASE1_PEAPVER,
+                             PROP_PHASE1_PEAPLABEL,
+                             PROP_PHASE1_FAST_PROVISIONING,
+                             PROP_PHASE1_AUTH_FLAGS,
+                             PROP_PHASE2_AUTH,
+                             PROP_PHASE2_AUTHEAP,
+                             PROP_PHASE2_CA_CERT,
+                             PROP_PHASE2_CA_CERT_PASSWORD,
+                             PROP_PHASE2_CA_CERT_PASSWORD_FLAGS,
+                             PROP_PHASE2_CA_PATH,
+                             PROP_PHASE2_SUBJECT_MATCH,
+                             PROP_PHASE2_ALTSUBJECT_MATCHES,
+                             PROP_PHASE2_DOMAIN_SUFFIX_MATCH,
+                             PROP_PHASE2_DOMAIN_MATCH,
+                             PROP_PHASE2_CLIENT_CERT,
+                             PROP_PHASE2_CLIENT_CERT_PASSWORD,
+                             PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS,
+                             PROP_PASSWORD,
+                             PROP_PASSWORD_FLAGS,
+                             PROP_PASSWORD_RAW,
+                             PROP_PASSWORD_RAW_FLAGS,
+                             PROP_PRIVATE_KEY,
+                             PROP_PRIVATE_KEY_PASSWORD,
+                             PROP_PRIVATE_KEY_PASSWORD_FLAGS,
+                             PROP_PHASE2_PRIVATE_KEY,
+                             PROP_PHASE2_PRIVATE_KEY_PASSWORD,
+                             PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
+                             PROP_PIN,
+                             PROP_PIN_FLAGS,
+                             PROP_SYSTEM_CA_CERTS,
+                             PROP_OPTIONAL,
+                             PROP_AUTH_TIMEOUT, );
+
+typedef struct {
+    GSList *                eap; /* GSList of strings */
+    char *                  identity;
+    char *                  anonymous_identity;
+    char *                  pac_file;
+    GBytes *                ca_cert;
+    char *                  ca_cert_password;
+    char *                  ca_path;
+    char *                  subject_match;
+    GSList *                altsubject_matches;
+    char *                  domain_suffix_match;
+    char *                  domain_match;
+    GBytes *                client_cert;
+    char *                  client_cert_password;
+    char *                  phase1_peapver;
+    char *                  phase1_peaplabel;
+    char *                  phase1_fast_provisioning;
+    char *                  phase2_auth;
+    char *                  phase2_autheap;
+    GBytes *                phase2_ca_cert;
+    char *                  phase2_ca_cert_password;
+    char *                  phase2_ca_path;
+    char *                  phase2_subject_match;
+    GSList *                phase2_altsubject_matches;
+    char *                  phase2_domain_suffix_match;
+    char *                  phase2_domain_match;
+    GBytes *                phase2_client_cert;
+    char *                  phase2_client_cert_password;
+    char *                  password;
+    GBytes *                password_raw;
+    char *                  pin;
+    GBytes *                private_key;
+    char *                  private_key_password;
+    GBytes *                phase2_private_key;
+    char *                  phase2_private_key_password;
+    int                     auth_timeout;
+    NMSetting8021xAuthFlags phase1_auth_flags;
+    NMSettingSecretFlags    ca_cert_password_flags;
+    NMSettingSecretFlags    client_cert_password_flags;
+    NMSettingSecretFlags    phase2_ca_cert_password_flags;
+    NMSettingSecretFlags    phase2_client_cert_password_flags;
+    NMSettingSecretFlags    password_flags;
+    NMSettingSecretFlags    password_raw_flags;
+    NMSettingSecretFlags    pin_flags;
+    NMSettingSecretFlags    private_key_password_flags;
+    NMSettingSecretFlags    phase2_private_key_password_flags;
+    bool                    optional : 1;
+    bool                    system_ca_certs : 1;
+} NMSetting8021xPrivate;
+
+/**
+ * NMSetting8021x:
+ *
+ * IEEE 802.1x Authentication Settings
+ */
+struct _NMSetting8021x {
+    NMSetting parent;
+    /* In the past, this struct was public API. Preserve ABI! */
+};
+
+struct _NMSetting8021xClass {
+    NMSettingClass parent;
+    /* In the past, this struct was public API. Preserve ABI! */
+    gpointer padding[4];
+};
+
+G_DEFINE_TYPE(NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING)
+
+#define NM_SETTING_802_1X_GET_PRIVATE(o) \
+    (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate))
+
+/*****************************************************************************/
+
+/**
+ * nm_setting_802_1x_check_cert_scheme:
+ * @pdata: (allow-none): the data pointer
+ * @length: the length of the data
+ * @error: (allow-none) (out): validation reason
+ *
+ * Determines and verifies the blob type.
+ * When setting certificate properties of NMSetting8021x
+ * the blob must be not UNKNOWN (or NULL).
+ *
+ * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
+ * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
+ *
+ * Since: 1.2
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_check_cert_scheme(gconstpointer pdata, gsize length, GError **error)
+{
+    const char *           data = pdata;
+    NMSetting8021xCKScheme scheme;
+    gsize                  prefix_length;
+
+    g_return_val_if_fail(!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+    if (!length || !data) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("binary data missing"));
+        return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+    }
+
+    if (length >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)
+        && !memcmp(data,
+                   NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH,
+                   NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) {
+        scheme        = NM_SETTING_802_1X_CK_SCHEME_PATH;
+        prefix_length = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
+    } else if (length >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11)
+               && !memcmp(data,
+                          NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11,
+                          NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11))) {
+        scheme        = NM_SETTING_802_1X_CK_SCHEME_PKCS11;
+        prefix_length = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11);
+    } else {
+        scheme        = NM_SETTING_802_1X_CK_SCHEME_BLOB;
+        prefix_length = 0;
+    }
+
+    if (scheme != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+        /* An actual URI must be NUL terminated, contain at least
+         * one non-NUL character, and contain only one trailing NUL
+         * character.
+         * And ensure it's UTF-8 valid too so we can pass it through
+         * D-Bus and stuff like that. */
+
+        if (data[length - 1] != '\0') {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("URI not NUL terminated"));
+            return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+        }
+        length--;
+
+        if (length <= prefix_length) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("URI is empty"));
+            return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+        }
+
+        if (!g_utf8_validate(data + prefix_length, length - prefix_length, NULL)) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("URI is not valid UTF-8"));
+            return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+        }
+    }
+
+    return scheme;
+}
+
+NMSetting8021xCKScheme
+_nm_setting_802_1x_cert_get_scheme(GBytes *bytes, GError **error)
+{
+    const char *data;
+    gsize       length;
+
+    if (!bytes) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("data missing"));
+        return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+    }
+
+    data = g_bytes_get_data(bytes, &length);
+    return nm_setting_802_1x_check_cert_scheme(data, length, error);
+}
+
+static gboolean
+_cert_verify_scheme(NMSetting8021xCKScheme scheme, GBytes *bytes, GError **error)
+{
+    GError *               local = NULL;
+    NMSetting8021xCKScheme scheme_detected;
+
+    nm_assert(bytes);
+
+    scheme_detected = _nm_setting_802_1x_cert_get_scheme(bytes, &local);
+    if (scheme_detected == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("certificate is invalid: %s"),
+                    local->message);
+        return FALSE;
+    }
+
+    if (scheme_detected != scheme) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("certificate detected as invalid scheme"));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+GBytes *
+_nm_setting_802_1x_cert_value_to_bytes(NMSetting8021xCKScheme scheme,
+                                       const guint8 *         val_bin,
+                                       gssize                 val_len,
+                                       GError **              error)
+{
+    gs_unref_bytes GBytes *bytes = NULL;
+    guint8 *               mem;
+    gsize                  total_len;
+
+    nm_assert(val_bin);
+
+    switch (scheme) {
+    case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
+        if (val_len < 0)
+            val_len = strlen((char *) val_bin) + 1;
+
+        bytes = g_bytes_new(val_bin, val_len);
+        break;
+    case NM_SETTING_802_1X_CK_SCHEME_PATH:
+        if (val_len < 0)
+            val_len = strlen((char *) val_bin) + 1;
+
+        total_len = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + ((gsize) val_len);
+
+        mem = g_new(guint8, total_len);
+        memcpy(mem,
+               NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH,
+               NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
+        memcpy(&mem[NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)], val_bin, val_len);
+        bytes = g_bytes_new_take(mem, total_len);
+        break;
+    default:
+        g_return_val_if_reached(NULL);
+    }
+
+    if (!_cert_verify_scheme(scheme, bytes, error))
+        return NULL;
+
+    return g_steal_pointer(&bytes);
+}
+
+static const char *
+_cert_get_path(GBytes *bytes)
+{
+    const guint8 *bin;
+
+    nm_assert(bytes);
+    nm_assert(g_bytes_get_size(bytes) >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
+
+    bin = g_bytes_get_data(bytes, NULL);
+
+    nm_assert(bin);
+    nm_assert(bin[g_bytes_get_size(bytes) - 1] == '\0');
+    nm_assert(g_str_has_prefix((const char *) bin, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
+
+    return (const char *) &bin[NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)];
+}
+
+#define _cert_assert_scheme(cert, check_scheme, ret_val)           \
+    G_STMT_START                                                   \
+    {                                                              \
+        NMSetting8021xCKScheme scheme;                             \
+                                                                   \
+        scheme = _nm_setting_802_1x_cert_get_scheme((cert), NULL); \
+        if (scheme != check_scheme) {                              \
+            g_return_val_if_fail(scheme == check_scheme, ret_val); \
+            return ret_val;                                        \
+        }                                                          \
+    }                                                              \
+    G_STMT_END
+
+#define _cert_impl_get_scheme(setting, cert_field)                                                 \
+    G_STMT_START                                                                                   \
+    {                                                                                              \
+        NMSetting8021x *const _setting = (setting);                                                \
+        GBytes *              _cert;                                                               \
+                                                                                                   \
+        g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); \
+                                                                                                   \
+        _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field;                               \
+                                                                                                   \
+        return _nm_setting_802_1x_cert_get_scheme(_cert, NULL);                                    \
+    }                                                                                              \
+    G_STMT_END
+
+#define _cert_impl_get_blob(setting, cert_field)                            \
+    G_STMT_START                                                            \
+    {                                                                       \
+        NMSetting8021x *const _setting = (setting);                         \
+        GBytes *              _cert;                                        \
+                                                                            \
+        g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL);         \
+                                                                            \
+        _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field;        \
+                                                                            \
+        _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); \
+                                                                            \
+        return _cert;                                                       \
+    }                                                                       \
+    G_STMT_END
+
+#define _cert_impl_get_path(setting, cert_field)                            \
+    G_STMT_START                                                            \
+    {                                                                       \
+        NMSetting8021x *const _setting = (setting);                         \
+        GBytes *              _cert;                                        \
+                                                                            \
+        g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL);         \
+                                                                            \
+        _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field;        \
+                                                                            \
+        _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); \
+                                                                            \
+        return _cert_get_path(_cert);                                       \
+    }                                                                       \
+    G_STMT_END
+
+#define _cert_impl_get_uri(setting, cert_field)                               \
+    G_STMT_START                                                              \
+    {                                                                         \
+        NMSetting8021x *const _setting = (setting);                           \
+        GBytes *              _cert;                                          \
+                                                                              \
+        g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL);           \
+                                                                              \
+        _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field;          \
+                                                                              \
+        _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); \
+                                                                              \
+        return g_bytes_get_data(_cert, NULL);                                 \
+    }                                                                         \
+    G_STMT_END
+
+static gboolean
+_cert_impl_set(NMSetting8021x *        setting,
+               _PropertyEnums          property,
+               const char *            value,
+               const char *            password,
+               NMSetting8021xCKScheme  scheme,
+               NMSetting8021xCKFormat *out_format,
+               GError **               error)
+{
+    NMSetting8021xPrivate *priv;
+    NMCryptoFileFormat     format             = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+    gs_unref_bytes GBytes *cert               = NULL;
+    GBytes **              p_cert             = NULL;
+    GBytes **              p_client_cert      = NULL;
+    char **                p_password         = NULL;
+    _PropertyEnums         notify_cert        = property;
+    _PropertyEnums         notify_password    = PROP_0;
+    _PropertyEnums         notify_client_cert = PROP_0;
+
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE);
+    g_return_val_if_fail(!error || !*error, FALSE);
+    if (value) {
+        g_return_val_if_fail(g_utf8_validate(value, -1, NULL), FALSE);
+        g_return_val_if_fail(NM_IN_SET(scheme,
+                                       NM_SETTING_802_1X_CK_SCHEME_BLOB,
+                                       NM_SETTING_802_1X_CK_SCHEME_PATH,
+                                       NM_SETTING_802_1X_CK_SCHEME_PKCS11),
+                             FALSE);
+    }
+
+    if (!value) {
+        /* coerce password to %NULL. It should be already. */
+        password = NULL;
+    }
+
+    priv = NM_SETTING_802_1X_GET_PRIVATE(setting);
+
+    if (!value) {
+        /* pass. */
+    } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+        cert = _nm_setting_802_1x_cert_value_to_bytes(scheme, (guint8 *) value, -1, error);
+        if (!cert)
+            goto err;
+    } else {
+        gs_unref_bytes GBytes *file = NULL;
+
+        if (NM_IN_SET(property, PROP_PRIVATE_KEY, PROP_PHASE2_PRIVATE_KEY)) {
+            file = nm_crypto_read_file(value, error);
+            if (!file)
+                goto err;
+            format = nm_crypto_verify_private_key_data(g_bytes_get_data(file, NULL),
+                                                       g_bytes_get_size(file),
+                                                       password,
+                                                       NULL,
+                                                       error);
+            if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN)
+                goto err;
+        } else {
+            if (!nm_crypto_load_and_verify_certificate(value, &format, &file, error))
+                goto err;
+        }
+
+        nm_assert(format != NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+        nm_assert(file);
+
+        if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+            cert = g_steal_pointer(&file);
+            if (!_cert_verify_scheme(scheme, cert, error))
+                goto err;
+        } else {
+            cert = _nm_setting_802_1x_cert_value_to_bytes(scheme, (guint8 *) value, -1, error);
+            if (!cert)
+                goto err;
+        }
+    }
+
+    switch (property) {
+    case PROP_CA_CERT:
+    case PROP_PHASE2_CA_CERT:
+        if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11
+            && format != NM_CRYPTO_FILE_FORMAT_X509) {
+            /* wpa_supplicant can only use raw x509 CA certs */
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("CA certificate must be in X.509 format"));
+            goto err;
+        }
+        p_cert = (property == PROP_CA_CERT) ? &priv->ca_cert : &priv->phase2_ca_cert;
+        break;
+    case PROP_CLIENT_CERT:
+    case PROP_PHASE2_CLIENT_CERT:
+        if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11
+            && !NM_IN_SET(format, NM_CRYPTO_FILE_FORMAT_X509, NM_CRYPTO_FILE_FORMAT_PKCS12)) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("invalid certificate format"));
+            goto err;
+        }
+        p_cert = (property == PROP_CLIENT_CERT) ? &priv->client_cert : &priv->phase2_client_cert;
+        break;
+    case PROP_PRIVATE_KEY:
+        p_cert             = &priv->private_key;
+        p_password         = &priv->private_key_password;
+        p_client_cert      = &priv->client_cert;
+        notify_password    = PROP_PRIVATE_KEY_PASSWORD;
+        notify_client_cert = PROP_CLIENT_CERT;
+        break;
+    case PROP_PHASE2_PRIVATE_KEY:
+        p_cert             = &priv->phase2_private_key;
+        p_password         = &priv->phase2_private_key_password;
+        p_client_cert      = &priv->phase2_client_cert;
+        notify_password    = PROP_PHASE2_PRIVATE_KEY_PASSWORD;
+        notify_client_cert = PROP_PHASE2_CLIENT_CERT;
+        break;
+    default:
+        nm_assert_not_reached();
+        break;
+    }
+
+    /* As required by NM and wpa_supplicant, set the client-cert
+     * property to the same PKCS#12 data.
+     */
+    if (cert && p_client_cert && format == NM_CRYPTO_FILE_FORMAT_PKCS12
+        && !nm_gbytes_equal0(cert, *p_client_cert)) {
+        g_bytes_unref(*p_client_cert);
+        *p_client_cert = g_bytes_ref(cert);
+    } else
+        notify_client_cert = PROP_0;
+
+    if (p_cert && !nm_gbytes_equal0(cert, *p_cert)) {
+        g_bytes_unref(*p_cert);
+        *p_cert = g_steal_pointer(&cert);
+    } else
+        notify_cert = PROP_0;
+
+    if (p_password && !nm_streq0(password, *p_password)) {
+        nm_free_secret(*p_password);
+        *p_password = g_strdup(password);
+    } else
+        notify_password = PROP_0;
+
+    nm_gobject_notify_together(setting, notify_cert, notify_password, notify_client_cert);
+
+    NM_SET_OUT(out_format, _crypto_format_to_ck(format));
+    return TRUE;
+
+err:
+    g_prefix_error(error,
+                   "%s.%s: ",
+                   NM_SETTING_802_1X_SETTING_NAME,
+                   obj_properties[property]->name);
+    NM_SET_OUT(out_format, NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
+    return FALSE;
+}
+
+static NMSetting8021xCKFormat
+_cert_impl_get_key_format_from_bytes(GBytes *private_key)
+{
+    const char *path;
+    GError *    error = NULL;
+
+    if (!private_key)
+        return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+
+    switch (_nm_setting_802_1x_cert_get_scheme(private_key, NULL)) {
+    case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+        if (nm_crypto_is_pkcs12_data(g_bytes_get_data(private_key, NULL),
+                                     g_bytes_get_size(private_key),
+                                     NULL))
+            return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+        return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+    case NM_SETTING_802_1X_CK_SCHEME_PATH:
+        path = _cert_get_path(private_key);
+        if (nm_crypto_is_pkcs12_file(path, &error))
+            return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+        if (error && error->domain == G_FILE_ERROR) {
+            g_error_free(error);
+            return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+        }
+        g_error_free(error);
+        return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+    default:
+        break;
+    }
+
+    return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+}
+#define _cert_impl_get_key_format(setting, private_key_field)                                      \
+    ({                                                                                             \
+        NMSetting8021x *       _setting = (setting);                                               \
+        NMSetting8021xPrivate *_priv;                                                              \
+                                                                                                   \
+        g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); \
+                                                                                                   \
+        _priv = NM_SETTING_802_1X_GET_PRIVATE(_setting);                                           \
+        _cert_impl_get_key_format_from_bytes(_priv->private_key_field);                            \
+    })
+
+static gboolean
+_cert_verify_property(GBytes *    bytes,
+                      const char *prop_name,
+                      const char *password,
+                      const char *password_prop_name,
+                      GError **   error)
+{
+    GError *               local = NULL;
+    NMSetting8021xCKScheme scheme;
+
+    if (!bytes)
+        return TRUE;
+
+    scheme = _nm_setting_802_1x_cert_get_scheme(bytes, &local);
+    if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("certificate is invalid: %s"),
+                    local->message);
+        g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name);
+        g_error_free(local);
+        return FALSE;
+    }
+
+    if (password && (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("password is not supported when certificate is not on a PKCS#11 token"));
+        g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, password_prop_name);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*****************************************************************************/
+
+/**
+ * nm_setting_802_1x_get_num_eap_methods:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the number of eap methods allowed for use when connecting to the
+ * network.  Generally only one EAP method is used.  Use the functions
+ * nm_setting_802_1x_get_eap_method(), nm_setting_802_1x_add_eap_method(),
+ * and nm_setting_802_1x_remove_eap_method() for adding, removing, and retrieving
+ * allowed EAP methods.
+ *
+ * Returns: the number of allowed EAP methods
+ **/
+guint32
+nm_setting_802_1x_get_num_eap_methods(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)->eap);
+}
+
+/**
+ * nm_setting_802_1x_get_eap_method:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the EAP method name to return
+ *
+ * Returns the name of the allowed EAP method at index @i.
+ *
+ * Returns: the name of the allowed EAP method at index @i
+ **/
+const char *
+nm_setting_802_1x_get_eap_method(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->eap), NULL);
+
+    return (const char *) g_slist_nth_data(priv->eap, i);
+}
+
+/**
+ * nm_setting_802_1x_add_eap_method:
+ * @setting: the #NMSetting8021x
+ * @eap: the name of the EAP method to allow for this connection
+ *
+ * Adds an allowed EAP method.  The setting is not valid until at least one
+ * EAP method has been added.  See #NMSetting8021x:eap property for a list of
+ * allowed EAP methods.
+ *
+ * Returns: %TRUE if the EAP method was successfully added, %FALSE if it was
+ *  not a valid method or if it was already allowed.
+ **/
+gboolean
+nm_setting_802_1x_add_eap_method(NMSetting8021x *setting, const char *eap)
+{
+    NMSetting8021xPrivate *priv;
+    GSList *               iter;
+
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE);
+    g_return_val_if_fail(eap != NULL, FALSE);
+
+    priv = NM_SETTING_802_1X_GET_PRIVATE(setting);
+    for (iter = priv->eap; iter; iter = g_slist_next(iter)) {
+        if (!strcmp(eap, (char *) iter->data))
+            return FALSE;
+    }
+
+    priv->eap = g_slist_append(priv->eap, g_ascii_strdown(eap, -1));
+    _notify(setting, PROP_EAP);
+    return TRUE;
+}
+
+/**
+ * nm_setting_802_1x_remove_eap_method:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the EAP method to remove
+ *
+ * Removes the allowed EAP method at the specified index.
+ **/
+void
+nm_setting_802_1x_remove_eap_method(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->eap, i);
+    g_return_if_fail(elt != NULL);
+
+    g_free(elt->data);
+    priv->eap = g_slist_delete_link(priv->eap, elt);
+    _notify(setting, PROP_EAP);
+}
+
+/**
+ * nm_setting_802_1x_remove_eap_method_by_value:
+ * @setting: the #NMSetting8021x
+ * @eap: the name of the EAP method to remove
+ *
+ * Removes the allowed EAP method @method.
+ *
+ * Returns: %TRUE if the EAP method was founs and removed, %FALSE if it was not.
+ **/
+gboolean
+nm_setting_802_1x_remove_eap_method_by_value(NMSetting8021x *setting, const char *eap)
+{
+    NMSetting8021xPrivate *priv;
+    GSList *               iter;
+
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE);
+    g_return_val_if_fail(eap != NULL, FALSE);
+
+    priv = NM_SETTING_802_1X_GET_PRIVATE(setting);
+    for (iter = priv->eap; iter; iter = g_slist_next(iter)) {
+        if (!strcmp(eap, (char *) iter->data)) {
+            priv->eap = g_slist_delete_link(priv->eap, iter);
+            _notify(setting, PROP_EAP);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/**
+ * nm_setting_802_1x_clear_eap_methods:
+ * @setting: the #NMSetting8021x
+ *
+ * Clears all allowed EAP methods.
+ **/
+void
+nm_setting_802_1x_clear_eap_methods(NMSetting8021x *setting)
+{
+    NMSetting8021xPrivate *priv;
+
+    g_return_if_fail(NM_IS_SETTING_802_1X(setting));
+
+    priv = NM_SETTING_802_1X_GET_PRIVATE(setting);
+    g_slist_free_full(priv->eap, g_free);
+    priv->eap = NULL;
+    _notify(setting, PROP_EAP);
+}
+
+/**
+ * nm_setting_802_1x_get_identity:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the identifier used by some EAP methods (like TLS) to
+ * authenticate the user.  Often this is a username or login name.
+ *
+ * Returns: the user identifier
+ **/
+const char *
+nm_setting_802_1x_get_identity(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->identity;
+}
+
+/**
+ * nm_setting_802_1x_get_anonymous_identity:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the anonymous identifier used by some EAP methods (like TTLS) to
+ * authenticate the user in the outer unencrypted "phase 1" authentication.  The
+ * inner "phase 2" authentication will use the #NMSetting8021x:identity in
+ * a secure form, if applicable for that EAP method.
+ *
+ * Returns: the anonymous identifier
+ **/
+const char *
+nm_setting_802_1x_get_anonymous_identity(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->anonymous_identity;
+}
+
+/**
+ * nm_setting_802_1x_get_pac_file:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the file containing PAC credentials used by EAP-FAST method.
+ *
+ * Returns: the PAC file
+ **/
+const char *
+nm_setting_802_1x_get_pac_file(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->pac_file;
+}
+
+/**
+ * nm_setting_802_1x_get_ca_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the path of the CA certificate directory if previously set.  Systems
+ * will often have a directory that contains multiple individual CA certificates
+ * which the supplicant can then add to the verification chain.  This may be
+ * used in addition to the #NMSetting8021x:ca-cert property to add more CA
+ * certificates for verifying the network to client.
+ *
+ * Returns: the CA certificate directory path
+ **/
+const char *
+nm_setting_802_1x_get_ca_path(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_path;
+}
+
+/**
+ * nm_setting_802_1x_get_system_ca_certs:
+ * @setting: the #NMSetting8021x
+ *
+ * Sets the #NMSetting8021x:system-ca-certs property. The
+ * #NMSetting8021x:ca-path and #NMSetting8021x:phase2-ca-path
+ * properties are ignored if the #NMSetting8021x:system-ca-certs property is
+ * %TRUE, in which case a system-wide CA certificate directory specified at
+ * compile time (using the --system-ca-path configure option) is used in place
+ * of these properties.
+ *
+ * Returns: %TRUE if a system CA certificate path should be used, %FALSE if not
+ **/
+gboolean
+nm_setting_802_1x_get_system_ca_certs(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->system_ca_certs;
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the CA certificate.  If the returned scheme
+ * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_ca_cert_blob();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use nm_setting_802_1x_get_ca_cert_uri().
+ *
+ * Returns: scheme used to store the CA certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_ca_cert_scheme(NMSetting8021x *setting)
+{
+    _cert_impl_get_scheme(setting, ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the CA certificate blob if the CA certificate is stored using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme.  Not all EAP methods use a
+ * CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset.  Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: (transfer none): the CA certificate data
+ **/
+GBytes *
+nm_setting_802_1x_get_ca_cert_blob(NMSetting8021x *setting)
+{
+    _cert_impl_get_blob(setting, ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the CA certificate path if the CA certificate is stored using the
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.  Not all EAP methods use a
+ * CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset.  Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: path to the CA certificate file
+ **/
+const char *
+nm_setting_802_1x_get_ca_cert_path(NMSetting8021x *setting)
+{
+    _cert_impl_get_path(setting, ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_uri:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the CA certificate URI analogously to
+ * nm_setting_802_1x_get_ca_cert_blob() and
+ * nm_setting_802_1x_get_ca_cert_path().
+ *
+ * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC
+ * 7512), but may be extended to other schemes in future (such as 'file' URIs
+ * for local files and 'data' URIs for inline certificate data).
+ *
+ * Returns: the URI string
+ *
+ * Since: 1.6
+ **/
+const char *
+nm_setting_802_1x_get_ca_cert_uri(NMSetting8021x *setting)
+{
+    _cert_impl_get_uri(setting, ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_set_ca_cert:
+ * @setting: the #NMSetting8021x
+ * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ *   or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the CA certificate
+ *   file (PEM or DER format).  The path must be UTF-8 encoded; use
+ *   g_filename_to_utf8() to convert if needed.  Passing %NULL with any @scheme
+ *   clears the CA certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:ca-cert property
+ * with the raw certificate data if using the %NM_SETTING_802_1X_CK_SCHEME_BLOB
+ * scheme, or with the path to the certificate file if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_ca_cert(NMSetting8021x *        setting,
+                              const char *            value,
+                              NMSetting8021xCKScheme  scheme,
+                              NMSetting8021xCKFormat *out_format,
+                              GError **               error)
+{
+    return _cert_impl_set(setting, PROP_CA_CERT, value, NULL, scheme, out_format, error);
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the password used to access the CA certificate stored in
+ * #NMSetting8021x:ca-cert property. Only makes sense if the certificate
+ * is stored on a PKCS#<!-- -->11 token that requires a login.
+ *
+ * Since: 1.8
+ **/
+const char *
+nm_setting_802_1x_get_ca_cert_password(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_cert_password;
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:ca-cert-password
+ *
+ * Since: 1.8
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_ca_cert_password_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_cert_password_flags;
+}
+
+/**
+ * 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));
+    _notify(setting, PROP_ALTSUBJECT_MATCHES);
+    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);
+    _notify(setting, PROP_ALTSUBJECT_MATCHES);
+}
+
+/**
+ * nm_setting_802_1x_remove_altsubject_match_by_value:
+ * @setting: the #NMSetting8021x
+ * @altsubject_match: the altSubjectName to remove
+ *
+ * Removes the allowed altSubjectName @altsubject_match.
+ *
+ * Returns: %TRUE if the alternative subject name match was found and removed,
+ *          %FALSE if it was not.
+ **/
+gboolean
+nm_setting_802_1x_remove_altsubject_match_by_value(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)) {
+            priv->altsubject_matches = g_slist_delete_link(priv->altsubject_matches, iter);
+            _notify(setting, PROP_ALTSUBJECT_MATCHES);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/**
+ * 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);
+    g_slist_free_full(priv->altsubject_matches, g_free);
+    priv->altsubject_matches = NULL;
+    _notify(setting, PROP_ALTSUBJECT_MATCHES);
+}
+
+/**
+ * nm_setting_802_1x_get_domain_suffix_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:domain-suffix-match property.
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_802_1x_get_domain_suffix_match(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->domain_suffix_match;
+}
+
+/**
+ * nm_setting_802_1x_get_domain_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:domain-match property.
+ *
+ * Since: 1.24
+ **/
+const char *
+nm_setting_802_1x_get_domain_match(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->domain_match;
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the client certificate.  If the returned scheme
+ * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_client_cert_blob();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_client_cert_path();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use nm_setting_802_1x_get_client_cert_uri().
+ *
+ * Returns: scheme used to store the client certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_client_cert_scheme(NMSetting8021x *setting)
+{
+    _cert_impl_get_scheme(setting, client_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: (transfer none): the client certificate data
+ **/
+GBytes *
+nm_setting_802_1x_get_client_cert_blob(NMSetting8021x *setting)
+{
+    _cert_impl_get_blob(setting, client_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the client certificate file
+ **/
+const char *
+nm_setting_802_1x_get_client_cert_path(NMSetting8021x *setting)
+{
+    _cert_impl_get_path(setting, client_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_uri:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the client certificate URI analogously to
+ * nm_setting_802_1x_get_client_cert_blob() and
+ * nm_setting_802_1x_get_client_cert_path().
+ *
+ * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC
+ * 7512), but may be extended to other schemes in future (such as 'file' URIs
+ * for local files and 'data' URIs for inline certificate data).
+ *
+ * Returns: the URI string
+ *
+ * Since: 1.6
+ **/
+const char *
+nm_setting_802_1x_get_client_cert_uri(NMSetting8021x *setting)
+{
+    _cert_impl_get_uri(setting, client_cert);
+}
+
+/**
+ * nm_setting_802_1x_set_client_cert:
+ * @setting: the #NMSetting8021x
+ * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ *   or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the client
+ *   certificate file (PEM, DER, or PKCS#<!-- -->12 format).  The path must be UTF-8
+ *   encoded; use g_filename_to_utf8() to convert if needed.  Passing %NULL with
+ *   any @scheme clears the client certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:client-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_client_cert(NMSetting8021x *        setting,
+                                  const char *            value,
+                                  NMSetting8021xCKScheme  scheme,
+                                  NMSetting8021xCKFormat *out_format,
+                                  GError **               error)
+{
+    return _cert_impl_set(setting, PROP_CLIENT_CERT, value, NULL, scheme, out_format, error);
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the password used to access the client certificate stored in
+ * #NMSetting8021x:client-cert property. Only makes sense if the certificate
+ * is stored on a PKCS#<!-- -->11 token that requires a login.
+ *
+ * Since: 1.8
+ **/
+const char *
+nm_setting_802_1x_get_client_cert_password(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->client_cert_password;
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:client-cert-password
+ *
+ * Since: 1.8
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_client_cert_password_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->client_cert_password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_phase1_peapver:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 1" PEAP version to be used when authenticating with
+ *  EAP-PEAP as contained in the #NMSetting8021x:phase1-peapver property.  Valid
+ *  values are %NULL (unset), "0" (PEAP version 0), and "1" (PEAP version 1).
+ **/
+const char *
+nm_setting_802_1x_get_phase1_peapver(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_peapver;
+}
+
+/**
+ * nm_setting_802_1x_get_phase1_peaplabel:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: whether the "phase 1" PEAP label is new-style or old-style, to be
+ *  used when authenticating with EAP-PEAP, as contained in the
+ *  #NMSetting8021x:phase1-peaplabel property.  Valid values are %NULL (unset),
+ *  "0" (use old-style label), and "1" (use new-style label).  See the
+ *  wpa_supplicant documentation for more details.
+ **/
+const char *
+nm_setting_802_1x_get_phase1_peaplabel(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_peaplabel;
+}
+
+/**
+ * nm_setting_802_1x_get_phase1_fast_provisioning:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: whether "phase 1" PEAP fast provisioning should be used, as specified
+ *  by the #NMSetting8021x:phase1-fast-provisioning property.  See the
+ *  wpa_supplicant documentation for more details.
+ **/
+const char *
+nm_setting_802_1x_get_phase1_fast_provisioning(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_fast_provisioning;
+}
+
+/**
+ * nm_setting_802_1x_get_phase1_auth_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the authentication flags for "phase 1".
+ *
+ * Since: 1.8
+ */
+NMSetting8021xAuthFlags
+nm_setting_802_1x_get_phase1_auth_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_auth_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_auth:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 2" non-EAP (ex MD5) allowed authentication method as
+ *   specified by the #NMSetting8021x:phase2-auth property.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_auth(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_auth;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_autheap:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 2" EAP-based (ex TLS) allowed authentication method as
+ *   specified by the #NMSetting8021x:phase2-autheap property.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_autheap(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_autheap;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the path of the "phase 2" CA certificate directory if previously set.
+ * Systems will often have a directory that contains multiple individual CA
+ * certificates which the supplicant can then add to the verification chain.
+ * This may be used in addition to the #NMSetting8021x:phase2-ca-cert property
+ * to add more CA certificates for verifying the network to client.
+ *
+ * Returns: the "phase 2" CA certificate directory path
+ **/
+const char *
+nm_setting_802_1x_get_phase2_ca_path(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_path;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" CA certificate.  If the
+ * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_ca_cert_blob(); if %NM_SETTING_802_1X_CK_SCHEME_PATH,
+ * use nm_setting_802_1x_get_ca_cert_path(); if %NM_SETTING_802_1X_CK_SCHEME_PKCS11,
+ * use nm_setting_802_1x_get_ca_cert_uri().
+ *
+ * Returns: scheme used to store the "phase 2" CA certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_phase2_ca_cert_scheme(NMSetting8021x *setting)
+{
+    _cert_impl_get_scheme(setting, phase2_ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" CA certificate blob if the CA certificate is stored
+ * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme.  Not all EAP methods use
+ * a CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset.  Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: (transfer none): the "phase 2" CA certificate data
+ **/
+GBytes *
+nm_setting_802_1x_get_phase2_ca_cert_blob(NMSetting8021x *setting)
+{
+    _cert_impl_get_blob(setting, phase2_ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" CA certificate path if the CA certificate is stored
+ * using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.  Not all EAP methods use
+ * a CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset.  Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: path to the "phase 2" CA certificate file
+ **/
+const char *
+nm_setting_802_1x_get_phase2_ca_cert_path(NMSetting8021x *setting)
+{
+    _cert_impl_get_path(setting, phase2_ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_uri:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" CA certificate URI analogously to
+ * nm_setting_802_1x_get_phase2_ca_cert_blob() and
+ * nm_setting_802_1x_get_phase2_ca_cert_path().
+ *
+ * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC
+ * 7512), but may be extended to other schemes in future (such as 'file' URIs
+ * for local files and 'data' URIs for inline certificate data).
+ *
+ * Returns: the URI string
+ *
+ * Since: 1.6
+ **/
+const char *
+nm_setting_802_1x_get_phase2_ca_cert_uri(NMSetting8021x *setting)
+{
+    _cert_impl_get_uri(setting, phase2_ca_cert);
+}
+
+/**
+ * nm_setting_802_1x_set_phase2_ca_cert:
+ * @setting: the #NMSetting8021x
+ * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ *   or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" CA
+ *   certificate file (PEM or DER format).  The path must be UTF-8 encoded; use
+ *   g_filename_to_utf8() to convert if needed.  Passing %NULL with any @scheme
+ *   clears the "phase2" CA certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:phase2-ca-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_phase2_ca_cert(NMSetting8021x *        setting,
+                                     const char *            value,
+                                     NMSetting8021xCKScheme  scheme,
+                                     NMSetting8021xCKFormat *out_format,
+                                     GError **               error)
+{
+    return _cert_impl_set(setting, PROP_PHASE2_CA_CERT, value, NULL, scheme, out_format, error);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the password used to access the "phase2" CA certificate stored in
+ * #NMSetting8021x:phase2-ca-cert property. Only makes sense if the certificate
+ * is stored on a PKCS#<!-- -->11 token that requires a login.
+ *
+ * Since: 1.8
+ **/
+const char *
+nm_setting_802_1x_get_phase2_ca_cert_password(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_cert_password;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:phase2-private-key-password
+ *
+ * Since: 1.8
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_phase2_ca_cert_password_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_cert_password_flags;
+}
+
+/**
+ * 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_domain_suffix_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:phase2-domain-suffix-match property.
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_802_1x_get_phase2_domain_suffix_match(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_domain_suffix_match;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_domain_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:phase2-domain-match property.
+ *
+ * Since: 1.24
+ **/
+const char *
+nm_setting_802_1x_get_phase2_domain_match(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_domain_match;
+}
+
+/**
+ * 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
+ * @phase2_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->phase2_altsubject_matches, g_strdup(phase2_altsubject_match));
+    _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+    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);
+    _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+}
+
+/**
+ * nm_setting_802_1x_remove_phase2_altsubject_match_by_value:
+ * @setting: the #NMSetting8021x
+ * @phase2_altsubject_match: the "phase 2" altSubjectName to remove
+ *
+ * Removes the allowed "phase 2" altSubjectName @phase2_altsubject_match.
+ *
+ * Returns: %TRUE if the alternative subject name match for "phase 2" was found and removed,
+ *          %FALSE if it was not.
+ **/
+gboolean
+nm_setting_802_1x_remove_phase2_altsubject_match_by_value(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)) {
+            priv->phase2_altsubject_matches =
+                g_slist_delete_link(priv->phase2_altsubject_matches, iter);
+            _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/**
+ * 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);
+    g_slist_free_full(priv->phase2_altsubject_matches, g_free);
+    priv->phase2_altsubject_matches = NULL;
+    _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" client certificate.  If the
+ * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use
+ * nm_setting_802_1x_get_client_cert_uri().
+ *
+ * Returns: scheme used to store the "phase 2" client certificate (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_phase2_client_cert_scheme(NMSetting8021x *setting)
+{
+    _cert_impl_get_scheme(setting, phase2_client_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: (transfer none): the "phase 2" client certificate data
+ **/
+GBytes *
+nm_setting_802_1x_get_phase2_client_cert_blob(NMSetting8021x *setting)
+{
+    _cert_impl_get_blob(setting, phase2_client_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the "phase 2" client certificate file
+ **/
+const char *
+nm_setting_802_1x_get_phase2_client_cert_path(NMSetting8021x *setting)
+{
+    _cert_impl_get_path(setting, phase2_client_cert);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_uri:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" client certificate URI analogously to
+ * nm_setting_802_1x_get_phase2_ca_cert_blob() and
+ * nm_setting_802_1x_get_phase2_ca_cert_path().
+ *
+ * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC
+ * 7512), but may be extended to other schemes in future (such as 'file' URIs
+ * for local files and 'data' URIs for inline certificate data).
+ *
+ * Returns: the URI string
+ *
+ * Since: 1.6
+ **/
+const char *
+nm_setting_802_1x_get_phase2_client_cert_uri(NMSetting8021x *setting)
+{
+    _cert_impl_get_uri(setting, phase2_client_cert);
+}
+
+/**
+ * nm_setting_802_1x_set_phase2_client_cert:
+ * @setting: the #NMSetting8021x
+ * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ *   or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" client
+ *   certificate file (PEM, DER, or PKCS#<!-- -->12 format).  The path must be UTF-8
+ *   encoded; use g_filename_to_utf8() to convert if needed.  Passing %NULL with
+ *   any @scheme clears the "phase2" client certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:phase2-client-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_phase2_client_cert(NMSetting8021x *        setting,
+                                         const char *            value,
+                                         NMSetting8021xCKScheme  scheme,
+                                         NMSetting8021xCKFormat *out_format,
+                                         GError **               error)
+{
+    return _cert_impl_set(setting, PROP_PHASE2_CLIENT_CERT, value, NULL, scheme, out_format, error);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the password used to access the "phase2" client certificate stored in
+ * #NMSetting8021x:phase2-client-cert property. Only makes sense if the certificate
+ * is stored on a PKCS#<!-- -->11 token that requires a login.
+ *
+ * Since: 1.8
+ **/
+const char *
+nm_setting_802_1x_get_phase2_client_cert_password(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_client_cert_password;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:phase2-client-cert-password
+ *
+ * Since: 1.8
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_phase2_client_cert_password_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_client_cert_password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the password used by the authentication method, if any, as specified
+ *   by the #NMSetting8021x:password property
+ **/
+const char *
+nm_setting_802_1x_get_password(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->password;
+}
+
+/**
+ * nm_setting_802_1x_get_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSetting8021x:password
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_password_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_password_raw:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: (transfer none): the password used by the authentication method as a
+ * UTF-8-encoded array of bytes, as specified by the
+ * #NMSetting8021x:password-raw property
+ **/
+GBytes *
+nm_setting_802_1x_get_password_raw(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_raw;
+}
+
+/**
+ * nm_setting_802_1x_get_password_raw_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ *   #NMSetting8021x:password-raw
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_password_raw_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_raw_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_pin:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the PIN used by the authentication method, if any, as specified
+ *   by the #NMSetting8021x:pin property
+ **/
+const char *
+nm_setting_802_1x_get_pin(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->pin;
+}
+
+/**
+ * nm_setting_802_1x_get_pin_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:pin
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_pin_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->pin_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the private key.  If the returned scheme is
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use
+ * nm_setting_802_1x_get_client_cert_uri().
+ *
+ * Returns: scheme used to store the private key (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_private_key_scheme(NMSetting8021x *setting)
+{
+    _cert_impl_get_scheme(setting, private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * WARNING: the private key property is not a "secret" property, and thus
+ * unencrypted private key data may be readable by unprivileged users.  Private
+ * keys should always be encrypted with a private key password.
+ *
+ * Returns: (transfer none): the private key data
+ **/
+GBytes *
+nm_setting_802_1x_get_private_key_blob(NMSetting8021x *setting)
+{
+    _cert_impl_get_blob(setting, private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the private key file
+ **/
+const char *
+nm_setting_802_1x_get_private_key_path(NMSetting8021x *setting)
+{
+    _cert_impl_get_path(setting, private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_uri:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the private key URI analogously to
+ * nm_setting_802_1x_get_private_key_blob() and
+ * nm_setting_802_1x_get_private_key_path().
+ *
+ * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC
+ * 7512), but may be extended to other schemes in future (such as 'file' URIs
+ * for local files and 'data' URIs for inline certificate data).
+ *
+ * Returns: the URI string
+ *
+ * Since: 1.6
+ **/
+const char *
+nm_setting_802_1x_get_private_key_uri(NMSetting8021x *setting)
+{
+    _cert_impl_get_uri(setting, private_key);
+}
+
+/**
+ * nm_setting_802_1x_set_private_key:
+ * @setting: the #NMSetting8021x
+ * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
+ *   %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the private key file
+ *   (PEM, DER, or PKCS#<!-- -->12 format).  The path must be UTF-8 encoded; use
+ *   g_filename_to_utf8() to convert if needed.  Passing %NULL with any @scheme
+ *   clears the private key.
+ * @password: password used to decrypt the private key, or %NULL if the password
+ *   is unknown.  If the password is given but fails to decrypt the private key,
+ *   an error is returned.
+ * @scheme: desired storage scheme for the private key
+ * @out_format: on successful return, the type of the private key added
+ * @error: on unsuccessful return, an error
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * This function reads a private key from disk and sets the
+ * #NMSetting8021x:private-key property with the private key file data if using
+ * the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the private
+ * key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * If @password is given, this function attempts to decrypt the private key to
+ * verify that @password is correct, and if it is, updates the
+ * #NMSetting8021x:private-key-password property with the given @password.  If
+ * the decryption is unsuccessful, %FALSE is returned, @error is set, and no
+ * internal data is changed.  If no @password is given, the private key is
+ * assumed to be valid, no decryption is performed, and the password may be set
+ * at a later time.
+ *
+ * WARNING: the private key property is not a "secret" property, and thus
+ * unencrypted private key data using the BLOB scheme may be readable by
+ * unprivileged users.  Private keys should always be encrypted with a private
+ * key password to prevent unauthorized access to unencrypted private key data.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_private_key(NMSetting8021x *        setting,
+                                  const char *            value,
+                                  const char *            password,
+                                  NMSetting8021xCKScheme  scheme,
+                                  NMSetting8021xCKFormat *out_format,
+                                  GError **               error)
+{
+    return _cert_impl_set(setting, PROP_PRIVATE_KEY, value, password, scheme, out_format, error);
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the private key password used to decrypt the private key if
+ *  previously set with nm_setting_802_1x_set_private_key(), or the
+ *  #NMSetting8021x:private-key-password property.
+ **/
+const char *
+nm_setting_802_1x_get_private_key_password(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->private_key_password;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:private-key-password
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_private_key_password_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->private_key_password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_format:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the data format of the private key data stored in the
+ *   #NMSetting8021x:private-key property
+ **/
+NMSetting8021xCKFormat
+nm_setting_802_1x_get_private_key_format(NMSetting8021x *setting)
+{
+    return _cert_impl_get_key_format(setting, private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the private key password used to decrypt the private key if
+ *  previously set with nm_setting_802_1x_set_phase2_private_key() or the
+ *  #NMSetting8021x:phase2-private-key-password property.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_private_key_password(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_private_key_password;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:phase2-private-key-password
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_phase2_private_key_password_flags(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_private_key_password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" private key.  If the returned
+ * scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use
+ * nm_setting_802_1x_get_client_cert_uri().
+ *
+ * Returns: scheme used to store the "phase 2" private key (blob or path)
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_get_phase2_private_key_scheme(NMSetting8021x *setting)
+{
+    _cert_impl_get_scheme(setting, phase2_private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * WARNING: the phase2 private key property is not a "secret" property, and thus
+ * unencrypted private key data may be readable by unprivileged users.  Private
+ * keys should always be encrypted with a private key password.
+ *
+ * Returns: (transfer none): the "phase 2" private key data
+ **/
+GBytes *
+nm_setting_802_1x_get_phase2_private_key_blob(NMSetting8021x *setting)
+{
+    _cert_impl_get_blob(setting, phase2_private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the "phase 2" private key file
+ **/
+const char *
+nm_setting_802_1x_get_phase2_private_key_path(NMSetting8021x *setting)
+{
+    _cert_impl_get_path(setting, phase2_private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_uri:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" private key URI analogously to
+ * nm_setting_802_1x_get_phase2_private_key_blob() and
+ * nm_setting_802_1x_get_phase2_private_key_path().
+ *
+ * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC
+ * 7512), but may be extended to other schemes in future (such as 'file' URIs
+ * for local files and 'data' URIs for inline certificate data).
+ *
+ * Returns: the URI string
+ *
+ * Since: 1.6
+ **/
+const char *
+nm_setting_802_1x_get_phase2_private_key_uri(NMSetting8021x *setting)
+{
+    _cert_impl_get_uri(setting, phase2_private_key);
+}
+
+/**
+ * nm_setting_802_1x_set_phase2_private_key:
+ * @setting: the #NMSetting8021x
+ * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
+ *   %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" private
+ *   key file (PEM, DER, or PKCS#<!-- -->12 format).  The path must be UTF-8 encoded;
+ *   use g_filename_to_utf8() to convert if needed.  Passing %NULL with any
+ *   @scheme clears the private key.
+ * @password: password used to decrypt the private key, or %NULL if the password
+ *   is unknown.  If the password is given but fails to decrypt the private key,
+ *   an error is returned.
+ * @scheme: desired storage scheme for the private key
+ * @out_format: on successful return, the type of the private key added
+ * @error: on unsuccessful return, an error
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * This function reads a private key from disk and sets the
+ * #NMSetting8021x:phase2-private-key property with the private key file data if
+ * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the
+ * private key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * If @password is given, this function attempts to decrypt the private key to
+ * verify that @password is correct, and if it is, updates the
+ * #NMSetting8021x:phase2-private-key-password property with the given
+ * @password.  If the decryption is unsuccessful, %FALSE is returned, @error is
+ * set, and no internal data is changed.  If no @password is given, the private
+ * key is assumed to be valid, no decryption is performed, and the password may
+ * be set at a later time.
+ *
+ * WARNING: the "phase2" private key property is not a "secret" property, and
+ * thus unencrypted private key data using the BLOB scheme may be readable by
+ * unprivileged users.  Private keys should always be encrypted with a private
+ * key password to prevent unauthorized access to unencrypted private key data.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_phase2_private_key(NMSetting8021x *        setting,
+                                         const char *            value,
+                                         const char *            password,
+                                         NMSetting8021xCKScheme  scheme,
+                                         NMSetting8021xCKFormat *out_format,
+                                         GError **               error)
+{
+    return _cert_impl_set(setting,
+                          PROP_PHASE2_PRIVATE_KEY,
+                          value,
+                          password,
+                          scheme,
+                          out_format,
+                          error);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_format:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the data format of the "phase 2" private key data stored in the
+ *   #NMSetting8021x:phase2-private-key property
+ **/
+NMSetting8021xCKFormat
+nm_setting_802_1x_get_phase2_private_key_format(NMSetting8021x *setting)
+{
+    return _cert_impl_get_key_format(setting, phase2_private_key);
+}
+
+/**
+ * nm_setting_802_1x_get_auth_timeout:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the value contained in the #NMSetting8021x:auth-timeout property.
+ *
+ * Returns: the configured authentication timeout in seconds. Zero means the
+ * global default value.
+ *
+ * Since: 1.8
+ **/
+int
+nm_setting_802_1x_get_auth_timeout(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->auth_timeout;
+}
+
+/**
+ * nm_setting_802_1x_get_optional:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the value contained in the #NMSetting8021x:optional property.
+ *
+ * Returns: %TRUE if the activation should proceed even when the 802.1X
+ *     authentication fails; %FALSE otherwise
+ *
+ * Since: 1.22
+ **/
+gboolean
+nm_setting_802_1x_get_optional(NMSetting8021x *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE);
+
+    return NM_SETTING_802_1X_GET_PRIVATE(setting)->optional;
+}
+
+/*****************************************************************************/
+
+static void
+need_secrets_password(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2)
+{
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+
+    if ((!priv->password || !strlen(priv->password))
+        && (!priv->password_raw || !g_bytes_get_size(priv->password_raw))) {
+        g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD);
+        g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD_RAW);
+    }
+}
+
+static void
+need_secrets_sim(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2)
+{
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+
+    if (!priv->pin || !strlen(priv->pin))
+        g_ptr_array_add(secrets, NM_SETTING_802_1X_PIN);
+}
+
+static gboolean
+need_private_key_password(GBytes *               blob,
+                          NMSetting8021xCKScheme scheme,
+                          const char *           path,
+                          const char *           password,
+                          NMSettingSecretFlags   flags)
+{
+    NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+
+    if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
+        return FALSE;
+
+    if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 && flags == NM_SETTING_SECRET_FLAG_NONE)
+        return FALSE;
+
+    /* Private key password is required */
+    if (password) {
+        if (path)
+            format = nm_crypto_verify_private_key(path, password, NULL, NULL);
+        else if (blob)
+            format = nm_crypto_verify_private_key_data(g_bytes_get_data(blob, NULL),
+                                                       g_bytes_get_size(blob),
+                                                       password,
+                                                       NULL,
+                                                       NULL);
+        else
+            return FALSE;
+    }
+
+    return (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+}
+
+static void
+need_secrets_tls(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2)
+{
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+    NMSetting8021xCKScheme scheme;
+    GBytes *               blob = NULL;
+    const char *           path = NULL;
+
+    if (phase2) {
+        scheme = nm_setting_802_1x_get_phase2_private_key_scheme(self);
+        if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+            path = nm_setting_802_1x_get_phase2_private_key_path(self);
+        else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+            blob = nm_setting_802_1x_get_phase2_private_key_blob(self);
+        else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)
+            g_warning("%s: unknown phase2 private key scheme %d", __func__, scheme);
+
+        if (need_private_key_password(blob,
+                                      scheme,
+                                      path,
+                                      priv->phase2_private_key_password,
+                                      priv->phase2_private_key_password_flags))
+            g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+
+        scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme(self);
+        if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11
+            && !(priv->phase2_ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE
+                 || priv->phase2_ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
+            && !priv->phase2_ca_cert_password)
+            g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD);
+
+        scheme = nm_setting_802_1x_get_phase2_client_cert_scheme(self);
+        if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11
+            && !(priv->phase2_client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED
+                 || priv->phase2_client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE)
+            && !priv->phase2_client_cert_password)
+            g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD);
+    } else {
+        scheme = nm_setting_802_1x_get_private_key_scheme(self);
+        if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+            path = nm_setting_802_1x_get_private_key_path(self);
+        else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+            blob = nm_setting_802_1x_get_private_key_blob(self);
+        else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)
+            g_warning("%s: unknown private key scheme %d", __func__, scheme);
+
+        if (need_private_key_password(blob,
+                                      scheme,
+                                      path,
+                                      priv->private_key_password,
+                                      priv->private_key_password_flags))
+            g_ptr_array_add(secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+
+        scheme = nm_setting_802_1x_get_ca_cert_scheme(self);
+        if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11
+            && !(priv->ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED
+                 || priv->ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE)
+            && !priv->ca_cert_password)
+            g_ptr_array_add(secrets, NM_SETTING_802_1X_CA_CERT_PASSWORD);
+
+        scheme = nm_setting_802_1x_get_client_cert_scheme(self);
+        if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11
+            && !(priv->client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE
+                 || priv->client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
+            && !priv->client_cert_password)
+            g_ptr_array_add(secrets, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD);
+    }
+}
+
+static gboolean
+verify_tls(NMSetting8021x *self, gboolean phase2, GError **error)
+{
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+
+    if (phase2) {
+        if (!priv->phase2_client_cert) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                                _("property is missing"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+            return FALSE;
+        } else if (!g_bytes_get_size(priv->phase2_client_cert)) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("property is empty"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+            return FALSE;
+        }
+
+        /* Private key is required for TLS */
+        if (!priv->phase2_private_key) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                                _("property is missing"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+            return FALSE;
+        } else if (!g_bytes_get_size(priv->phase2_private_key)) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("property is empty"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+            return FALSE;
+        }
+
+        /* If the private key is PKCS#12, check that it matches the client cert */
+        if (nm_crypto_is_pkcs12_data(g_bytes_get_data(priv->phase2_private_key, NULL),
+                                     g_bytes_get_size(priv->phase2_private_key),
+                                     NULL)) {
+            if (!g_bytes_equal(priv->phase2_private_key, priv->phase2_client_cert)) {
+                g_set_error(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("has to match '%s' property for PKCS#12"),
+                            NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+                g_prefix_error(error,
+                               "%s.%s: ",
+                               NM_SETTING_802_1X_SETTING_NAME,
+                               NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+                return FALSE;
+            }
+        }
+    } else {
+        if (!priv->client_cert) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                                _("property is missing"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_CLIENT_CERT);
+            return FALSE;
+        } else if (!g_bytes_get_size(priv->client_cert)) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("property is empty"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_CLIENT_CERT);
+            return FALSE;
+        }
+
+        /* Private key is required for TLS */
+        if (!priv->private_key) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                                _("property is missing"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_PRIVATE_KEY);
+            return FALSE;
+        } else if (!g_bytes_get_size(priv->private_key)) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("property is empty"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_802_1X_SETTING_NAME,
+                           NM_SETTING_802_1X_PRIVATE_KEY);
+            return FALSE;
+        }
+
+        /* If the private key is PKCS#12, check that it matches the client cert */
+        if (nm_crypto_is_pkcs12_data(g_bytes_get_data(priv->private_key, NULL),
+                                     g_bytes_get_size(priv->private_key),
+                                     NULL)) {
+            if (!g_bytes_equal(priv->private_key, priv->client_cert)) {
+                g_set_error(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("has to match '%s' property for PKCS#12"),
+                            NM_SETTING_802_1X_PRIVATE_KEY);
+                g_prefix_error(error,
+                               "%s.%s: ",
+                               NM_SETTING_802_1X_SETTING_NAME,
+                               NM_SETTING_802_1X_CLIENT_CERT);
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+static gboolean
+verify_ttls(NMSetting8021x *self, gboolean phase2, GError **error)
+{
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+
+    if (!priv->identity || !strlen(priv->identity)) {
+        if (!priv->identity) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                                _("property is missing"));
+        } else {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("property is empty"));
+        }
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_IDENTITY);
+        return FALSE;
+    }
+
+    if ((!priv->phase2_auth && !priv->phase2_autheap)
+        || (priv->phase2_auth && priv->phase2_autheap)) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                            _("exactly one property must be set"));
+        g_prefix_error(error,
+                       "%s.%s, %s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE2_AUTH,
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE2_AUTHEAP);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static gboolean
+verify_identity(NMSetting8021x *self, gboolean phase2, GError **error)
+{
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+
+    if (!priv->identity) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                            _("property is missing"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_IDENTITY);
+        return FALSE;
+    } else if (!strlen(priv->identity)) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property is empty"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_IDENTITY);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+need_secrets_phase2(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2)
+{
+    NMSetting8021xPrivate *priv   = NM_SETTING_802_1X_GET_PRIVATE(self);
+    char *                 method = NULL;
+    int                    i;
+
+    g_return_if_fail(phase2 == FALSE);
+
+    /* Check phase2_auth and phase2_autheap */
+    method = priv->phase2_auth;
+    if (!method && priv->phase2_autheap)
+        method = priv->phase2_autheap;
+
+    if (!method) {
+        g_warning("Couldn't find EAP method.");
+        g_assert_not_reached();
+        return;
+    }
+
+    /* Ask the configured phase2 method if it needs secrets */
+    for (i = 0; eap_methods_table[i].method; i++) {
+        if (eap_methods_table[i].ns_func == NULL)
+            continue;
+        if (!strcmp(eap_methods_table[i].method, method)) {
+            (*eap_methods_table[i].ns_func)(self, secrets, TRUE);
+            break;
+        }
+    }
+}
+
+static const EAPMethodsTable eap_methods_table[] = {
+    {"leap", need_secrets_password, verify_identity},
+    {"pwd", need_secrets_password, verify_identity},
+    {"md5", need_secrets_password, verify_identity},
+    {"pap", need_secrets_password, verify_identity},
+    {"chap", need_secrets_password, verify_identity},
+    {"mschap", need_secrets_password, verify_identity},
+    {"mschapv2", need_secrets_password, verify_identity},
+    {"fast", need_secrets_password, verify_identity},
+    {"tls", need_secrets_tls, verify_tls},
+    {"peap", need_secrets_phase2, verify_ttls},
+    {"ttls", need_secrets_phase2, verify_ttls},
+    {"sim", need_secrets_sim, NULL},
+    {"gtc", need_secrets_password, verify_identity},
+    {"otp", NULL, NULL},  // FIXME: implement
+    {"external", NULL, NULL},
+    {NULL, NULL, NULL}};
+
+static gboolean
+verify(NMSetting *setting, NMConnection *connection, GError **error)
+{
+    NMSetting8021x *       self = NM_SETTING_802_1X(setting);
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+    const char *           valid_eap[] =
+        {"leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", "external", NULL};
+    GSList *iter;
+
+    if (error)
+        g_return_val_if_fail(*error == NULL, FALSE);
+
+    if (connection && priv->optional
+        && !nm_streq0(nm_connection_get_connection_type(connection),
+                      NM_SETTING_WIRED_SETTING_NAME)) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("can be enabled only on Ethernet connections"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_OPTIONAL);
+        return FALSE;
+    }
+
+    if (!priv->eap) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                            _("property is missing"));
+        g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP);
+        return FALSE;
+    }
+
+    if (!_nm_utils_string_slist_validate(priv->eap, valid_eap)) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property is invalid"));
+        g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP);
+        return FALSE;
+    }
+
+    /* Ask each configured EAP method if its valid */
+    for (iter = priv->eap; iter; iter = g_slist_next(iter)) {
+        const char *method = (const char *) iter->data;
+        int         i;
+
+        for (i = 0; eap_methods_table[i].method; i++) {
+            if (eap_methods_table[i].v_func == NULL)
+                continue;
+            if (!strcmp(eap_methods_table[i].method, method)) {
+                if (!(*eap_methods_table[i].v_func) (self, FALSE, error))
+                    return FALSE;
+                break;
+            }
+        }
+    }
+
+    if (!NM_IN_STRSET(priv->phase1_peapver, NULL, "0", "1")) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("'%s' is not a valid value for the property"),
+                    priv->phase1_peapver);
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE1_PEAPVER);
+        return FALSE;
+    }
+
+    if (!NM_IN_STRSET(priv->phase1_peaplabel, NULL, "0", "1")) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("'%s' is not a valid value for the property"),
+                    priv->phase1_peaplabel);
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE1_PEAPLABEL);
+        return FALSE;
+    }
+
+    if (!NM_IN_STRSET(priv->phase1_fast_provisioning, NULL, "0", "1", "2", "3")) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("'%s' is not a valid value for the property"),
+                    priv->phase1_fast_provisioning);
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING);
+        return FALSE;
+    }
+
+    if (NM_FLAGS_ANY(priv->phase1_auth_flags, ~NM_SETTING_802_1X_AUTH_FLAGS_ALL)) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("invalid auth flags"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE1_AUTH_FLAGS);
+        return FALSE;
+    }
+
+    if (!NM_IN_STRSET(priv->phase2_auth,
+                      NULL,
+                      "pap",
+                      "chap",
+                      "mschap",
+                      "mschapv2",
+                      "gtc",
+                      "otp",
+                      "md5",
+                      "tls")) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("'%s' is not a valid value for the property"),
+                    priv->phase2_auth);
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE2_AUTH);
+        return FALSE;
+    }
+
+    if (!NM_IN_STRSET(priv->phase2_autheap, NULL, "md5", "mschapv2", "otp", "gtc", "tls")) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("'%s' is not a valid value for the property"),
+                    priv->phase2_autheap);
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_802_1X_SETTING_NAME,
+                       NM_SETTING_802_1X_PHASE2_AUTHEAP);
+        return FALSE;
+    }
+
+    if (!_cert_verify_property(priv->ca_cert,
+                               NM_SETTING_802_1X_CA_CERT,
+                               priv->ca_cert_password,
+                               NM_SETTING_802_1X_CA_CERT_PASSWORD,
+                               error))
+        return FALSE;
+    if (!_cert_verify_property(priv->phase2_ca_cert,
+                               NM_SETTING_802_1X_PHASE2_CA_CERT,
+                               priv->phase2_ca_cert_password,
+                               NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD,
+                               error))
+        return FALSE;
+
+    if (!_cert_verify_property(priv->client_cert,
+                               NM_SETTING_802_1X_CLIENT_CERT,
+                               priv->client_cert_password,
+                               NM_SETTING_802_1X_CLIENT_CERT_PASSWORD,
+                               error))
+        return FALSE;
+    if (!_cert_verify_property(priv->phase2_client_cert,
+                               NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
+                               priv->phase2_client_cert_password,
+                               NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD,
+                               error))
+        return FALSE;
+
+    if (!_cert_verify_property(priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, NULL, NULL, error))
+        return FALSE;
+    if (!_cert_verify_property(priv->phase2_private_key,
+                               NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+                               NULL,
+                               NULL,
+                               error))
+        return FALSE;
+
+    return TRUE;
+}
+
+/*****************************************************************************/
+
+static GPtrArray *
+need_secrets(NMSetting *setting)
+{
+    NMSetting8021x *       self = NM_SETTING_802_1X(setting);
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+    GSList *               iter;
+    GPtrArray *            secrets;
+    gboolean               eap_method_found = FALSE;
+
+    secrets = g_ptr_array_sized_new(4);
+
+    /* Ask each configured EAP method if it needs secrets */
+    for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next(iter)) {
+        const char *method = (const char *) iter->data;
+        int         i;
+
+        for (i = 0; eap_methods_table[i].method; i++) {
+            if (eap_methods_table[i].ns_func == NULL)
+                continue;
+            if (!strcmp(eap_methods_table[i].method, method)) {
+                (*eap_methods_table[i].ns_func)(self, secrets, FALSE);
+
+                /* Only break out of the outer loop if this EAP method
+                 * needed secrets.
+                 */
+                if (secrets->len > 0)
+                    eap_method_found = TRUE;
+                break;
+            }
+        }
+    }
+
+    if (secrets->len == 0) {
+        g_ptr_array_free(secrets, TRUE);
+        return NULL;
+    }
+
+    return secrets;
+}
+
+/*****************************************************************************/
+
+static void
+get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+    NMSetting8021x *       setting = NM_SETTING_802_1X(object);
+    NMSetting8021xPrivate *priv    = NM_SETTING_802_1X_GET_PRIVATE(setting);
+
+    switch (prop_id) {
+    case PROP_EAP:
+        g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->eap, TRUE));
+        break;
+    case PROP_IDENTITY:
+        g_value_set_string(value, priv->identity);
+        break;
+    case PROP_ANONYMOUS_IDENTITY:
+        g_value_set_string(value, priv->anonymous_identity);
+        break;
+    case PROP_PAC_FILE:
+        g_value_set_string(value, priv->pac_file);
+        break;
+    case PROP_CA_CERT:
+        g_value_set_boxed(value, priv->ca_cert);
+        break;
+    case PROP_CA_CERT_PASSWORD:
+        g_value_set_string(value, priv->ca_cert_password);
+        break;
+    case PROP_CA_CERT_PASSWORD_FLAGS:
+        g_value_set_flags(value, priv->ca_cert_password_flags);
+        break;
+    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_take_boxed(value, _nm_utils_slist_to_strv(priv->altsubject_matches, TRUE));
+        break;
+    case PROP_DOMAIN_SUFFIX_MATCH:
+        g_value_set_string(value, priv->domain_suffix_match);
+        break;
+    case PROP_DOMAIN_MATCH:
+        g_value_set_string(value, priv->domain_match);
+        break;
+    case PROP_CLIENT_CERT:
+        g_value_set_boxed(value, priv->client_cert);
+        break;
+    case PROP_CLIENT_CERT_PASSWORD:
+        g_value_set_string(value, priv->client_cert_password);
+        break;
+    case PROP_CLIENT_CERT_PASSWORD_FLAGS:
+        g_value_set_flags(value, priv->client_cert_password_flags);
+        break;
+    case PROP_PHASE1_PEAPVER:
+        g_value_set_string(value, priv->phase1_peapver);
+        break;
+    case PROP_PHASE1_PEAPLABEL:
+        g_value_set_string(value, priv->phase1_peaplabel);
+        break;
+    case PROP_PHASE1_FAST_PROVISIONING:
+        g_value_set_string(value, priv->phase1_fast_provisioning);
+        break;
+    case PROP_PHASE1_AUTH_FLAGS:
+        g_value_set_uint(value, priv->phase1_auth_flags);
+        break;
+    case PROP_PHASE2_AUTH:
+        g_value_set_string(value, priv->phase2_auth);
+        break;
+    case PROP_PHASE2_AUTHEAP:
+        g_value_set_string(value, priv->phase2_autheap);
+        break;
+    case PROP_PHASE2_CA_CERT:
+        g_value_set_boxed(value, priv->phase2_ca_cert);
+        break;
+    case PROP_PHASE2_CA_CERT_PASSWORD:
+        g_value_set_string(value, priv->phase2_ca_cert_password);
+        break;
+    case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS:
+        g_value_set_flags(value, priv->phase2_ca_cert_password_flags);
+        break;
+    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_take_boxed(value, _nm_utils_slist_to_strv(priv->phase2_altsubject_matches, TRUE));
+        break;
+    case PROP_PHASE2_DOMAIN_SUFFIX_MATCH:
+        g_value_set_string(value, priv->phase2_domain_suffix_match);
+        break;
+    case PROP_PHASE2_DOMAIN_MATCH:
+        g_value_set_string(value, priv->phase2_domain_match);
+        break;
+    case PROP_PHASE2_CLIENT_CERT:
+        g_value_set_boxed(value, priv->phase2_client_cert);
+        break;
+    case PROP_PHASE2_CLIENT_CERT_PASSWORD:
+        g_value_set_string(value, priv->phase2_client_cert_password);
+        break;
+    case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS:
+        g_value_set_flags(value, priv->phase2_client_cert_password_flags);
+        break;
+    case PROP_PASSWORD:
+        g_value_set_string(value, priv->password);
+        break;
+    case PROP_PASSWORD_FLAGS:
+        g_value_set_flags(value, priv->password_flags);
+        break;
+    case PROP_PASSWORD_RAW:
+        g_value_set_boxed(value, priv->password_raw);
+        break;
+    case PROP_PASSWORD_RAW_FLAGS:
+        g_value_set_flags(value, priv->password_raw_flags);
+        break;
+    case PROP_PRIVATE_KEY:
+        g_value_set_boxed(value, priv->private_key);
+        break;
+    case PROP_PRIVATE_KEY_PASSWORD:
+        g_value_set_string(value, priv->private_key_password);
+        break;
+    case PROP_PRIVATE_KEY_PASSWORD_FLAGS:
+        g_value_set_flags(value, priv->private_key_password_flags);
+        break;
+    case PROP_PHASE2_PRIVATE_KEY:
+        g_value_set_boxed(value, priv->phase2_private_key);
+        break;
+    case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
+        g_value_set_string(value, priv->phase2_private_key_password);
+        break;
+    case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS:
+        g_value_set_flags(value, priv->phase2_private_key_password_flags);
+        break;
+    case PROP_PIN:
+        g_value_set_string(value, priv->pin);
+        break;
+    case PROP_PIN_FLAGS:
+        g_value_set_flags(value, priv->pin_flags);
+        break;
+    case PROP_SYSTEM_CA_CERTS:
+        g_value_set_boolean(value, priv->system_ca_certs);
+        break;
+    case PROP_AUTH_TIMEOUT:
+        g_value_set_int(value, priv->auth_timeout);
+        break;
+    case PROP_OPTIONAL:
+        g_value_set_boolean(value, priv->optional);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+    NMSetting8021x *       setting = NM_SETTING_802_1X(object);
+    NMSetting8021xPrivate *priv    = NM_SETTING_802_1X_GET_PRIVATE(setting);
+
+    switch (prop_id) {
+    case PROP_EAP:
+        g_slist_free_full(priv->eap, g_free);
+        priv->eap = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE);
+        break;
+    case PROP_IDENTITY:
+        g_free(priv->identity);
+        priv->identity = g_value_dup_string(value);
+        break;
+    case PROP_ANONYMOUS_IDENTITY:
+        g_free(priv->anonymous_identity);
+        priv->anonymous_identity = g_value_dup_string(value);
+        break;
+    case PROP_PAC_FILE:
+        g_free(priv->pac_file);
+        priv->pac_file = g_value_dup_string(value);
+        break;
+    case PROP_CA_CERT:
+        g_bytes_unref(priv->ca_cert);
+        priv->ca_cert = g_value_dup_boxed(value);
+        break;
+    case PROP_CA_CERT_PASSWORD:
+        g_free(priv->ca_cert_password);
+        priv->ca_cert_password = g_value_dup_string(value);
+        break;
+    case PROP_CA_CERT_PASSWORD_FLAGS:
+        priv->ca_cert_password_flags = g_value_get_flags(value);
+        break;
+    case PROP_CA_PATH:
+        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 = nm_strdup_not_empty(g_value_get_string(value));
+        break;
+    case PROP_ALTSUBJECT_MATCHES:
+        g_slist_free_full(priv->altsubject_matches, g_free);
+        priv->altsubject_matches = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE);
+        break;
+    case PROP_DOMAIN_SUFFIX_MATCH:
+        g_free(priv->domain_suffix_match);
+        priv->domain_suffix_match = nm_strdup_not_empty(g_value_get_string(value));
+        break;
+    case PROP_DOMAIN_MATCH:
+        g_free(priv->domain_match);
+        priv->domain_match = nm_strdup_not_empty(g_value_get_string(value));
+        break;
+    case PROP_CLIENT_CERT:
+        g_bytes_unref(priv->client_cert);
+        priv->client_cert = g_value_dup_boxed(value);
+        break;
+    case PROP_CLIENT_CERT_PASSWORD:
+        g_free(priv->client_cert_password);
+        priv->client_cert_password = g_value_dup_string(value);
+        break;
+    case PROP_CLIENT_CERT_PASSWORD_FLAGS:
+        priv->client_cert_password_flags = g_value_get_flags(value);
+        break;
+    case PROP_PHASE1_PEAPVER:
+        g_free(priv->phase1_peapver);
+        priv->phase1_peapver = g_value_dup_string(value);
+        break;
+    case PROP_PHASE1_PEAPLABEL:
+        g_free(priv->phase1_peaplabel);
+        priv->phase1_peaplabel = g_value_dup_string(value);
+        break;
+    case PROP_PHASE1_FAST_PROVISIONING:
+        g_free(priv->phase1_fast_provisioning);
+        priv->phase1_fast_provisioning = g_value_dup_string(value);
+        break;
+    case PROP_PHASE1_AUTH_FLAGS:
+        priv->phase1_auth_flags = g_value_get_uint(value);
+        break;
+    case PROP_PHASE2_AUTH:
+        g_free(priv->phase2_auth);
+        priv->phase2_auth = g_value_dup_string(value);
+        break;
+    case PROP_PHASE2_AUTHEAP:
+        g_free(priv->phase2_autheap);
+        priv->phase2_autheap = g_value_dup_string(value);
+        break;
+    case PROP_PHASE2_CA_CERT:
+        g_bytes_unref(priv->phase2_ca_cert);
+        priv->phase2_ca_cert = g_value_dup_boxed(value);
+        break;
+    case PROP_PHASE2_CA_CERT_PASSWORD:
+        g_free(priv->phase2_ca_cert_password);
+        priv->phase2_ca_cert_password = g_value_dup_string(value);
+        break;
+    case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS:
+        priv->phase2_ca_cert_password_flags = g_value_get_flags(value);
+        break;
+    case PROP_PHASE2_CA_PATH:
+        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 = nm_strdup_not_empty(g_value_get_string(value));
+        break;
+    case PROP_PHASE2_ALTSUBJECT_MATCHES:
+        g_slist_free_full(priv->phase2_altsubject_matches, g_free);
+        priv->phase2_altsubject_matches = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE);
+        break;
+    case PROP_PHASE2_DOMAIN_SUFFIX_MATCH:
+        g_free(priv->phase2_domain_suffix_match);
+        priv->phase2_domain_suffix_match = nm_strdup_not_empty(g_value_get_string(value));
+        break;
+    case PROP_PHASE2_DOMAIN_MATCH:
+        g_free(priv->phase2_domain_match);
+        priv->phase2_domain_match = nm_strdup_not_empty(g_value_get_string(value));
+        break;
+    case PROP_PHASE2_CLIENT_CERT:
+        g_bytes_unref(priv->phase2_client_cert);
+        priv->phase2_client_cert = g_value_dup_boxed(value);
+        break;
+    case PROP_PHASE2_CLIENT_CERT_PASSWORD:
+        g_free(priv->phase2_client_cert_password);
+        priv->phase2_client_cert_password = g_value_dup_string(value);
+        break;
+    case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS:
+        priv->phase2_client_cert_password_flags = g_value_get_flags(value);
+        break;
+    case PROP_PASSWORD:
+        g_free(priv->password);
+        priv->password = g_value_dup_string(value);
+        break;
+    case PROP_PASSWORD_FLAGS:
+        priv->password_flags = g_value_get_flags(value);
+        break;
+    case PROP_PASSWORD_RAW:
+        g_bytes_unref(priv->password_raw);
+        priv->password_raw = g_value_dup_boxed(value);
+        break;
+    case PROP_PASSWORD_RAW_FLAGS:
+        priv->password_raw_flags = g_value_get_flags(value);
+        break;
+    case PROP_PRIVATE_KEY:
+        g_bytes_unref(priv->private_key);
+        priv->private_key = g_value_dup_boxed(value);
+        break;
+    case PROP_PRIVATE_KEY_PASSWORD:
+        nm_free_secret(priv->private_key_password);
+        priv->private_key_password = g_value_dup_string(value);
+        break;
+    case PROP_PRIVATE_KEY_PASSWORD_FLAGS:
+        priv->private_key_password_flags = g_value_get_flags(value);
+        break;
+    case PROP_PHASE2_PRIVATE_KEY:
+        g_bytes_unref(priv->phase2_private_key);
+        priv->phase2_private_key = g_value_dup_boxed(value);
+        break;
+    case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
+        nm_free_secret(priv->phase2_private_key_password);
+        priv->phase2_private_key_password = g_value_dup_string(value);
+        break;
+    case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS:
+        priv->phase2_private_key_password_flags = g_value_get_flags(value);
+        break;
+    case PROP_PIN:
+        g_free(priv->pin);
+        priv->pin = g_value_dup_string(value);
+        break;
+    case PROP_PIN_FLAGS:
+        priv->pin_flags = g_value_get_flags(value);
+        break;
+    case PROP_SYSTEM_CA_CERTS:
+        priv->system_ca_certs = g_value_get_boolean(value);
+        break;
+    case PROP_AUTH_TIMEOUT:
+        priv->auth_timeout = g_value_get_int(value);
+        break;
+    case PROP_OPTIONAL:
+        priv->optional = g_value_get_boolean(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+/*****************************************************************************/
+
+static void
+nm_setting_802_1x_init(NMSetting8021x *setting)
+{}
+
+/**
+ * nm_setting_802_1x_new:
+ *
+ * Creates a new #NMSetting8021x object with default values.
+ *
+ * Returns: the new empty #NMSetting8021x object
+ **/
+NMSetting *
+nm_setting_802_1x_new(void)
+{
+    return g_object_new(NM_TYPE_SETTING_802_1X, NULL);
+}
+
+static void
+finalize(GObject *object)
+{
+    NMSetting8021x *       self = NM_SETTING_802_1X(object);
+    NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self);
+
+    g_free(priv->identity);
+    g_free(priv->anonymous_identity);
+    g_free(priv->ca_path);
+    g_free(priv->subject_match);
+    g_free(priv->domain_suffix_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->phase2_domain_suffix_match);
+    g_free(priv->password);
+    g_bytes_unref(priv->password_raw);
+    g_free(priv->pin);
+
+    g_slist_free_full(priv->eap, g_free);
+    g_slist_free_full(priv->altsubject_matches, g_free);
+    g_slist_free_full(priv->phase2_altsubject_matches, g_free);
+
+    g_bytes_unref(priv->ca_cert);
+    g_free(priv->ca_cert_password);
+    g_bytes_unref(priv->client_cert);
+    g_free(priv->client_cert_password);
+    g_bytes_unref(priv->private_key);
+    nm_free_secret(priv->private_key_password);
+    g_bytes_unref(priv->phase2_ca_cert);
+    g_free(priv->phase2_ca_cert_password);
+    g_bytes_unref(priv->phase2_client_cert);
+    g_free(priv->phase2_client_cert_password);
+    g_bytes_unref(priv->phase2_private_key);
+    nm_free_secret(priv->phase2_private_key_password);
+
+    G_OBJECT_CLASS(nm_setting_802_1x_parent_class)->finalize(object);
+}
+
+static void
+nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
+{
+    GObjectClass *  object_class        = G_OBJECT_CLASS(klass);
+    NMSettingClass *setting_class       = NM_SETTING_CLASS(klass);
+    GArray *        properties_override = _nm_sett_info_property_override_create_array();
+
+    g_type_class_add_private(klass, sizeof(NMSetting8021xPrivate));
+
+    object_class->get_property = get_property;
+    object_class->set_property = set_property;
+    object_class->finalize     = finalize;
+
+    setting_class->verify       = verify;
+    setting_class->need_secrets = need_secrets;
+
+    /**
+     * NMSetting8021x:eap:
+     *
+     * The allowed EAP method to be used when authenticating to the network with
+     * 802.1x.  Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd",
+     * and "fast".  Each method requires different configuration using the
+     * properties of this setting; refer to wpa_supplicant documentation for the
+     * allowed combinations.
+     **/
+    /* ---ifcfg-rh---
+     * property: eap
+     * variable: IEEE_8021X_EAP_METHODS(+)
+     * values: "LEAP", "PWD", "TLS", "PEAP", "TTLS", "FAST"
+     * description: EAP method for 802.1X authentication.
+     * example: IEEE_8021X_EAP_METHODS=PEAP
+     * ---end---
+     */
+    obj_properties[PROP_EAP] = g_param_spec_boxed(NM_SETTING_802_1X_EAP,
+                                                  "",
+                                                  "",
+                                                  G_TYPE_STRV,
+                                                  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:identity:
+     *
+     * Identity string for EAP authentication methods.  Often the user's user or
+     * login name.
+     **/
+    /* ---ifcfg-rh---
+     * property: identity
+     * variable: IEEE_8021X_IDENTITY(+)
+     * description: Identity for EAP authentication methods.
+     * example: IEEE_8021X_IDENTITY=itsme
+     * ---end---
+     */
+    obj_properties[PROP_IDENTITY] = g_param_spec_string(NM_SETTING_802_1X_IDENTITY,
+                                                        "",
+                                                        "",
+                                                        NULL,
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:anonymous-identity:
+     *
+     * Anonymous identity string for EAP authentication methods.  Used as the
+     * unencrypted identity with EAP types that support different tunneled
+     * identity like EAP-TTLS.
+     **/
+    /* ---ifcfg-rh---
+     * property: anonymous-identity
+     * variable: IEEE_8021X_ANON_IDENTITY(+)
+     * description: Anonymous identity for EAP authentication methods.
+     * ---end---
+     */
+    obj_properties[PROP_ANONYMOUS_IDENTITY] =
+        g_param_spec_string(NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:pac-file:
+     *
+     * UTF-8 encoded file path containing PAC for EAP-FAST.
+     **/
+    /* ---ifcfg-rh---
+     * property: pac-file
+     * variable: IEEE_8021X_PAC_FILE(+)
+     * description: File with PAC (Protected Access Credential) for EAP-FAST.
+     * example: IEEE_8021X_PAC_FILE=/home/joe/my-fast.pac
+     * ---end---
+     */
+    obj_properties[PROP_PAC_FILE] = g_param_spec_string(NM_SETTING_802_1X_PAC_FILE,
+                                                        "",
+                                                        "",
+                                                        NULL,
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:ca-cert:
+     *
+     * Contains the CA certificate if used by the EAP method specified in the
+     * #NMSetting8021x:eap property.
+     *
+     * Certificate data is specified using a "scheme"; three are currently
+     * supported: blob, path and pkcs#11 URL. When using the blob scheme this property
+     * should be set to the certificate's DER encoded data. When using the path
+     * scheme, this property should be set to the full UTF-8 encoded path of the
+     * certificate, prefixed with the string "file://" and ending with a terminating
+     * NUL byte.
+     * This property can be unset even if the EAP method supports CA certificates,
+     * but this allows man-in-the-middle attacks and is NOT recommended.
+     *
+     * Note that enabling NMSetting8021x:system-ca-certs will override this
+     * setting to use the built-in path, if the built-in path is not a directory.
+     *
+     * Setting this property directly is discouraged; use the
+     * nm_setting_802_1x_set_ca_cert() function instead.
+     **/
+    /* ---ifcfg-rh---
+     * property: ca-cert
+     * variable: IEEE_8021X_CA_CERT(+)
+     * description: CA certificate for EAP.
+     * example: IEEE_8021X_CA_CERT=/home/joe/cacert.crt
+     * ---end---
+     */
+    obj_properties[PROP_CA_CERT] = g_param_spec_boxed(NM_SETTING_802_1X_CA_CERT,
+                                                      "",
+                                                      "",
+                                                      G_TYPE_BYTES,
+                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:ca-cert-password:
+     *
+     * The password used to access the CA certificate stored in
+     * #NMSetting8021x:ca-cert property. Only makes sense if the certificate
+     * is stored on a PKCS#<!-- -->11 token that requires a login.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_CA_CERT_PASSWORD] =
+        g_param_spec_string(NM_SETTING_802_1X_CA_CERT_PASSWORD,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:ca-cert-password-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:ca-cert-password property.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_CA_CERT_PASSWORD_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:ca-path:
+     *
+     * UTF-8 encoded path to a directory containing PEM or DER formatted
+     * certificates to be added to the verification chain in addition to the
+     * certificate specified in the #NMSetting8021x:ca-cert property.
+     *
+     * If NMSetting8021x:system-ca-certs is enabled and the built-in CA
+     * path is an existing directory, then this setting is ignored.
+     **/
+    /* ---ifcfg-rh---
+     * property: ca-path
+     * variable: IEEE_8021X_CA_PATH(+)
+     * description: The search path for the certificate.
+     * ---end---
+     */
+    obj_properties[PROP_CA_PATH] = g_param_spec_string(NM_SETTING_802_1X_CA_PATH,
+                                                       "",
+                                                       "",
+                                                       NULL,
+                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * 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.  This property
+     * provides little security, if any, and its use is deprecated in favor of
+     * NMSetting8021x:domain-suffix-match.
+     **/
+    /* ---ifcfg-rh---
+     * property: subject-match
+     * variable: IEEE_8021X_SUBJECT_MATCH(+)
+     * description: Substring to match subject of server certificate against.
+     * example: IEEE_8021X_SUBJECT_MATCH="Red Hat"
+     * ---end---
+     */
+    obj_properties[PROP_SUBJECT_MATCH] =
+        g_param_spec_string(NM_SETTING_802_1X_SUBJECT_MATCH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * 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.
+     **/
+    /* ---ifcfg-rh---
+     * property: altsubject-matches
+     * variable: IEEE_8021X_ALTSUBJECT_MATCHES(+)
+     * description: List of strings to be matched against the altSubjectName.
+     * example: IEEE_8021X_ALTSUBJECT_MATCHES="s1.domain.cc"
+     * ---end---
+     */
+    obj_properties[PROP_ALTSUBJECT_MATCHES] =
+        g_param_spec_boxed(NM_SETTING_802_1X_ALTSUBJECT_MATCHES,
+                           "",
+                           "",
+                           G_TYPE_STRV,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:domain-suffix-match:
+     *
+     * Constraint for server domain name. If set, this FQDN is used as a suffix
+     * match requirement for dNSName element(s) of the certificate presented by
+     * the authentication server.  If a matching dNSName is found, this
+     * constraint is met.  If no dNSName values are present, this constraint is
+     * matched against SubjectName CN using same suffix match comparison.
+     * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited
+     * list.
+     *
+     * Since: 1.2
+     **/
+    /* ---ifcfg-rh---
+     * property: domain-suffix-match
+     * description: Suffix to match domain of server certificate against.
+     * variable: IEEE_8021X_DOMAIN_SUFFIX_MATCH(+)
+     * ---end---
+     */
+    obj_properties[PROP_DOMAIN_SUFFIX_MATCH] =
+        g_param_spec_string(NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:domain-match:
+     *
+     * Constraint for server domain name. If set, this list of FQDNs is used as
+     * a match requirement for dNSName element(s) of the certificate presented
+     * by the authentication server.  If a matching dNSName is found, this
+     * constraint is met.  If no dNSName values are present, this constraint is
+     * matched against SubjectName CN using the same comparison.
+     * Multiple valid FQDNs can be passed as a ";" delimited list.
+     *
+     * Since: 1.24
+     **/
+    /* ---ifcfg-rh---
+     * property: domain-match
+     * description: Value to match domain of server certificate against.
+     * variable: IEEE_8021X_DOMAIN_MATCH(+)
+     * ---end---
+     */
+    obj_properties[PROP_DOMAIN_MATCH] =
+        g_param_spec_string(NM_SETTING_802_1X_DOMAIN_MATCH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:client-cert:
+     *
+     * Contains the client certificate if used by the EAP method specified in
+     * the #NMSetting8021x:eap property.
+     *
+     * Certificate data is specified using a "scheme"; two are currently
+     * supported: blob and path. When using the blob scheme (which is backwards
+     * compatible with NM 0.7.x) this property should be set to the
+     * certificate's DER encoded data. When using the path scheme, this property
+     * should be set to the full UTF-8 encoded path of the certificate, prefixed
+     * with the string "file://" and ending with a terminating NUL byte.
+     *
+     * Setting this property directly is discouraged; use the
+     * nm_setting_802_1x_set_client_cert() function instead.
+     **/
+    /* ---ifcfg-rh---
+     * property: client-cert
+     * variable: IEEE_8021X_CLIENT_CERT(+)
+     * description: Client certificate for EAP.
+     * example: IEEE_8021X_CLIENT_CERT=/home/joe/mycert.crt
+     * ---end---
+     */
+    obj_properties[PROP_CLIENT_CERT] =
+        g_param_spec_boxed(NM_SETTING_802_1X_CLIENT_CERT,
+                           "",
+                           "",
+                           G_TYPE_BYTES,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:client-cert-password:
+     *
+     * The password used to access the client certificate stored in
+     * #NMSetting8021x:client-cert property. Only makes sense if the certificate
+     * is stored on a PKCS#<!-- -->11 token that requires a login.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_CLIENT_CERT_PASSWORD] =
+        g_param_spec_string(NM_SETTING_802_1X_CLIENT_CERT_PASSWORD,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:client-cert-password-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:client-cert-password property.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_CLIENT_CERT_PASSWORD_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase1-peapver:
+     *
+     * Forces which PEAP version is used when PEAP is set as the EAP method in
+     * the #NMSetting8021x:eap property.  When unset, the version reported by
+     * the server will be used.  Sometimes when using older RADIUS servers, it
+     * is necessary to force the client to use a particular PEAP version.  To do
+     * so, this property may be set to "0" or "1" to force that specific PEAP
+     * version.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase1-peapver
+     * variable: IEEE_8021X_PEAP_VERSION(+)
+     * values: 0, 1
+     * description: Use to force a specific PEAP version.
+     * ---end---
+     */
+    obj_properties[PROP_PHASE1_PEAPVER] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE1_PEAPVER,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase1-peaplabel:
+     *
+     * Forces use of the new PEAP label during key derivation.  Some RADIUS
+     * servers may require forcing the new PEAP label to interoperate with
+     * PEAPv1.  Set to "1" to force use of the new PEAP label.  See the
+     * wpa_supplicant documentation for more details.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase1-peaplabel
+     * variable: IEEE_8021X_PEAP_FORCE_NEW_LABEL(+)
+     * values: yes, no
+     * default: no
+     * description: Use to force the new PEAP label during key derivation.
+     * ---end---
+     */
+    obj_properties[PROP_PHASE1_PEAPLABEL] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE1_PEAPLABEL,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase1-fast-provisioning:
+     *
+     * Enables or disables in-line provisioning of EAP-FAST credentials when
+     * FAST is specified as the EAP method in the #NMSetting8021x:eap property.
+     * Recognized values are "0" (disabled), "1" (allow unauthenticated
+     * provisioning), "2" (allow authenticated provisioning), and "3" (allow
+     * both authenticated and unauthenticated provisioning).  See the
+     * wpa_supplicant documentation for more details.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase1-fast-provisioning
+     * variable: IEEE_8021X_FAST_PROVISIONING(+)
+     * values: space-separated list of these values [allow-auth, allow-unauth]
+     * description: Enable in-line provisioning of EAP-FAST credentials.
+     * example: IEEE_8021X_FAST_PROVISIONING="allow-auth allow-unauth"
+     * ---end---
+     */
+    obj_properties[PROP_PHASE1_FAST_PROVISIONING] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase1-auth-flags:
+     *
+     * Specifies authentication flags to use in "phase 1" outer
+     * authentication using #NMSetting8021xAuthFlags options.
+     * The individual TLS versions can be explicitly disabled. If a certain
+     * TLS disable flag is not set, it is up to the supplicant to allow
+     * or forbid it. The TLS options map to tls_disable_tlsv1_x settings.
+     * See the wpa_supplicant documentation for more details.
+     *
+     * Since: 1.8
+     */
+    /* ---ifcfg-rh---
+     * property: phase1-auth-flags
+     * variable: IEEE_8021X_PHASE1_AUTH_FLAGS(+)
+     * values: space-separated list of authentication flags names
+     * description: Authentication flags for the supplicant
+     * example: IEEE_8021X_PHASE1_AUTH_FLAGS="tls-1-0-disable tls-1-1-disable"
+     * ---end---
+     */
+    obj_properties[PROP_PHASE1_AUTH_FLAGS] =
+        g_param_spec_uint(NM_SETTING_802_1X_PHASE1_AUTH_FLAGS,
+                          "",
+                          "",
+                          0,
+                          G_MAXUINT32,
+                          NM_SETTING_802_1X_AUTH_FLAGS_NONE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-auth:
+     *
+     * Specifies the allowed "phase 2" inner authentication method when an EAP
+     * method that uses an inner TLS tunnel is specified in the #NMSetting8021x:eap
+     * property.  For TTLS this property selects one of the supported non-EAP
+     * inner methods: "pap", "chap", "mschap", "mschapv2" while
+     * #NMSetting8021x:phase2-autheap selects an EAP inner method.  For PEAP
+     * this selects an inner EAP method, one of: "gtc", "otp", "md5" and "tls".
+     * Each "phase 2" inner method requires specific parameters for successful
+     * authentication; see the wpa_supplicant documentation for more details.
+     * Both #NMSetting8021x:phase2-auth and #NMSetting8021x:phase2-autheap cannot
+     * be specified.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-auth
+     * variable: IEEE_8021X_INNER_AUTH_METHODS(+)
+     * values: "PAP", "CHAP", "MSCHAP", "MSCHAPV2", "GTC", "OTP", "MD5" and "TLS"
+     * description: Inner non-EAP authentication methods for TTLS or the inner EAP
+     *   authentication method for PEAP. IEEE_8021X_INNER_AUTH_METHODS can contain
+     *   values both for 'phase2-auth' and 'phase2-autheap' properties.
+     * example: IEEE_8021X_INNER_AUTH_METHODS=PAP
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_AUTH] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_AUTH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-autheap:
+     *
+     * Specifies the allowed "phase 2" inner EAP-based authentication method
+     * when TTLS is specified in the #NMSetting8021x:eap property.  Recognized
+     * EAP-based "phase 2" methods are "md5", "mschapv2", "otp", "gtc", and
+     * "tls". Each "phase 2" inner method requires specific parameters for
+     * successful authentication; see the wpa_supplicant documentation for
+     * more details.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-autheap
+     * variable: IEEE_8021X_INNER_AUTH_METHODS(+)
+     * values: "EAP-MD5", "EAP-MSCHAPV2", "EAP-GTC", "EAP-OTP" and "EAP-TLS"
+     * description: Inner EAP-based authentication methods. Note that
+     *   IEEE_8021X_INNER_AUTH_METHODS is also used for 'phase2-auth' values.
+     * example: IEEE_8021X_INNER_AUTH_METHODS="MSCHAPV2 EAP-TLS"
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_AUTHEAP] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_AUTHEAP,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-ca-cert:
+     *
+     * Contains the "phase 2" CA certificate if used by the EAP method specified
+     * in the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap
+     * properties.
+     *
+     * Certificate data is specified using a "scheme"; three are currently
+     * supported: blob, path and pkcs#11 URL. When using the blob scheme this property
+     * should be set to the certificate's DER encoded data. When using the path
+     * scheme, this property should be set to the full UTF-8 encoded path of the
+     * certificate, prefixed with the string "file://" and ending with a terminating
+     * NUL byte.
+     * This property can be unset even if the EAP method supports CA certificates,
+     * but this allows man-in-the-middle attacks and is NOT recommended.
+     *
+     * Note that enabling NMSetting8021x:system-ca-certs will override this
+     * setting to use the built-in path, if the built-in path is not a directory.
+     *
+     * Setting this property directly is discouraged; use the
+     * nm_setting_802_1x_set_phase2_ca_cert() function instead.
+     **/
+    obj_properties[PROP_PHASE2_CA_CERT] =
+        g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_CA_CERT,
+                           "",
+                           "",
+                           G_TYPE_BYTES,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-ca-cert-password:
+     *
+     * The password used to access the "phase2" CA certificate stored in
+     * #NMSetting8021x:phase2-ca-cert property. Only makes sense if the certificate
+     * is stored on a PKCS#<!-- -->11 token that requires a login.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_CA_CERT_PASSWORD] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-ca-cert-password-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:phase2-ca-cert-password property.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_CA_CERT_PASSWORD_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-ca-path:
+     *
+     * UTF-8 encoded path to a directory containing PEM or DER formatted
+     * certificates to be added to the verification chain in addition to the
+     * certificate specified in the #NMSetting8021x:phase2-ca-cert property.
+     *
+     * If NMSetting8021x:system-ca-certs is enabled and the built-in CA
+     * path is an existing directory, then this setting is ignored.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-ca-path
+     * variable: IEEE_8021X_PHASE2_CA_PATH(+)
+     * description: The search path for the certificate.
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_CA_PATH] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_CA_PATH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * 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.  This property provides little security,
+     * if any, and its use is deprecated in favor of
+     * NMSetting8021x:phase2-domain-suffix-match.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-subject-match
+     * variable: IEEE_8021X_PHASE2_SUBJECT_MATCH(+)
+     * description: Substring to match subject of server certificate against.
+     * example: IEEE_8021X_PHASE2_SUBJECT_MATCH="Red Hat"
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_SUBJECT_MATCH] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * 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.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-altsubject-matches
+     * variable: IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES(+)
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_ALTSUBJECT_MATCHES] =
+        g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES,
+                           "",
+                           "",
+                           G_TYPE_STRV,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-domain-suffix-match:
+     *
+     * Constraint for server domain name. If set, this FQDN is used as a suffix
+     * match requirement for dNSName element(s) of the certificate presented by
+     * the authentication server during the inner "phase 2" authentication.  If
+     * a matching dNSName is found, this constraint is met.  If no dNSName
+     * values are present, this constraint is matched against SubjectName CN
+     * using same suffix match comparison.
+     * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited
+     * list.
+     *
+     * Since: 1.2
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-domain-suffix-match
+     * description: Suffix to match domain of server certificate for phase 2 against.
+     * variable: IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH(+)
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_DOMAIN_SUFFIX_MATCH] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-domain-match:
+     *
+     * Constraint for server domain name. If set, this list of FQDNs is used as
+     * a match requirement for dNSName element(s) of the certificate presented
+     * by the authentication server during the inner "phase 2" authentication.
+     * If a matching dNSName is found, this constraint is met.  If no dNSName
+     * values are present, this constraint is matched against SubjectName CN
+     * using the same comparison.
+     * Multiple valid FQDNs can be passed as a ";" delimited list.
+     *
+     * Since: 1.24
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-domain-match
+     * description: Value to match domain of server certificate for phase 2 against.
+     * variable: IEEE_8021X_PHASE2_DOMAIN_MATCH(+)
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_DOMAIN_MATCH] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-client-cert:
+     *
+     * Contains the "phase 2" client certificate if used by the EAP method
+     * specified in the #NMSetting8021x:phase2-auth or
+     * #NMSetting8021x:phase2-autheap properties.
+     *
+     * Certificate data is specified using a "scheme"; two are currently
+     * supported: blob and path. When using the blob scheme (which is backwards
+     * compatible with NM 0.7.x) this property should be set to the
+     * certificate's DER encoded data. When using the path scheme, this property
+     * should be set to the full UTF-8 encoded path of the certificate, prefixed
+     * with the string "file://" and ending with a terminating NUL byte. This
+     * property can be unset even if the EAP method supports CA certificates,
+     * but this allows man-in-the-middle attacks and is NOT recommended.
+     *
+     * Setting this property directly is discouraged; use the
+     * nm_setting_802_1x_set_phase2_client_cert() function instead.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-client-cert
+     * variable: IEEE_8021X_INNER_CLIENT_CERT(+)
+     * description: Client certificate for inner EAP method.
+     * example: IEEE_8021X_INNER_CLIENT_CERT=/home/joe/mycert.crt
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_CLIENT_CERT] =
+        g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
+                           "",
+                           "",
+                           G_TYPE_BYTES,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-client-cert-password:
+     *
+     * The password used to access the "phase2" client certificate stored in
+     * #NMSetting8021x:phase2-client-cert property. Only makes sense if the certificate
+     * is stored on a PKCS#<!-- -->11 token that requires a login.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-client-cert-password-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:phase2-client-cert-password property.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:password:
+     *
+     * UTF-8 encoded password used for EAP authentication methods. If both the
+     * #NMSetting8021x:password property and the #NMSetting8021x:password-raw
+     * property are specified, #NMSetting8021x:password is preferred.
+     **/
+    /* ---ifcfg-rh---
+     * property: password
+     * variable: IEEE_8021X_PASSWORD(+)
+     * description: UTF-8 encoded password used for EAP. It can also go to "key-"
+     *   lookaside file, or it can be owned by a secret agent.
+     * ---end---
+     */
+    obj_properties[PROP_PASSWORD] =
+        g_param_spec_string(NM_SETTING_802_1X_PASSWORD,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:password-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:password property.
+     **/
+    /* ---ifcfg-rh---
+     * property: password-flags
+     * variable: IEEE_8021X_PASSWORD_FLAGS(+)
+     * format: NMSettingSecretFlags
+     * description: Password flags for IEEE_8021X_PASSWORD password.
+     * ---end---
+     */
+    obj_properties[PROP_PASSWORD_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_PASSWORD_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:password-raw:
+     *
+     * Password used for EAP authentication methods, given as a byte array to
+     * allow passwords in other encodings than UTF-8 to be used. If both the
+     * #NMSetting8021x:password property and the #NMSetting8021x:password-raw
+     * property are specified, #NMSetting8021x:password is preferred.
+     **/
+    /* ---ifcfg-rh---
+     * property: password-raw
+     * variable: IEEE_8021X_PASSWORD_RAW(+)
+     * description: password used for EAP, encoded as a hexadecimal string. It
+     *   can also go to "key-" lookaside file.
+     * example: IEEE_8021X_PASSWORD_RAW=041c8320083aa4bf
+     * ---end---
+     */
+    obj_properties[PROP_PASSWORD_RAW] =
+        g_param_spec_boxed(NM_SETTING_802_1X_PASSWORD_RAW,
+                           "",
+                           "",
+                           G_TYPE_BYTES,
+                           G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:password-raw-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:password-raw property.
+     **/
+    /* ---ifcfg-rh---
+     * property: password-raw-flags
+     * variable: IEEE_8021X_PASSWORD_RAW_FLAGS(+)
+     * description: The secret flags for password-raw.
+     * ---end---
+     */
+    obj_properties[PROP_PASSWORD_RAW_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_PASSWORD_RAW_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:private-key:
+     *
+     * Contains the private key when the #NMSetting8021x:eap property is set to
+     * "tls".
+     *
+     * Key data is specified using a "scheme"; two are currently supported: blob
+     * and path. When using the blob scheme and private keys, this property
+     * should be set to the key's encrypted PEM encoded data. When using private
+     * keys with the path scheme, this property should be set to the full UTF-8
+     * encoded path of the key, prefixed with the string "file://" and ending
+     * with a terminating NUL byte. When using PKCS#<!-- -->12 format private
+     * keys and the blob scheme, this property should be set to the
+     * PKCS#<!-- -->12 data and the #NMSetting8021x:private-key-password
+     * property must be set to password used to decrypt the PKCS#<!-- -->12
+     * certificate and key. When using PKCS#<!-- -->12 files and the path
+     * scheme, this property should be set to the full UTF-8 encoded path of the
+     * key, prefixed with the string "file://" and ending with a terminating
+     * NUL byte, and as with the blob scheme the "private-key-password" property
+     * must be set to the password used to decode the PKCS#<!-- -->12 private
+     * key and certificate.
+     *
+     * Setting this property directly is discouraged; use the
+     * nm_setting_802_1x_set_private_key() function instead.
+     *
+     * WARNING: #NMSetting8021x:private-key is not a "secret" property, and thus
+     * unencrypted private key data using the BLOB scheme may be readable by
+     * unprivileged users.  Private keys should always be encrypted with a
+     * private key password to prevent unauthorized access to unencrypted
+     * private key data.
+     **/
+    /* ---ifcfg-rh---
+     * property: private-key
+     * variable: IEEE_8021X_PRIVATE_KEY(+)
+     * description: Private key for EAP-TLS.
+     * example: IEEE_8021X_PRIVATE_KEY=/home/joe/mykey.p12
+     * ---end---
+     */
+    obj_properties[PROP_PRIVATE_KEY] =
+        g_param_spec_boxed(NM_SETTING_802_1X_PRIVATE_KEY,
+                           "",
+                           "",
+                           G_TYPE_BYTES,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:private-key-password:
+     *
+     * The password used to decrypt the private key specified in the
+     * #NMSetting8021x:private-key property when the private key either uses the
+     * path scheme, or if the private key is a PKCS#<!-- -->12 format key.  Setting this
+     * property directly is not generally necessary except when returning
+     * secrets to NetworkManager; it is generally set automatically when setting
+     * the private key by the nm_setting_802_1x_set_private_key() function.
+     **/
+    /* ---ifcfg-rh---
+     * property: private-key-password
+     * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD(+)
+     * description: Password for IEEE_8021X_PRIVATE_KEY. It can also go to "key-"
+     *   lookaside file, or it can be owned by a secret agent.
+     * ---end---
+     */
+    obj_properties[PROP_PRIVATE_KEY_PASSWORD] =
+        g_param_spec_string(NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:private-key-password-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:private-key-password
+     * property.
+     **/
+    /* ---ifcfg-rh---
+     * property: private-key-password-flags
+     * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS(+)
+     * format: NMSettingSecretFlags
+     * description: Password flags for IEEE_8021X_PRIVATE_KEY_PASSWORD password.
+     * ---end---
+     */
+    obj_properties[PROP_PRIVATE_KEY_PASSWORD_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-private-key:
+     *
+     * Contains the "phase 2" inner private key when the
+     * #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap property is
+     * set to "tls".
+     *
+     * Key data is specified using a "scheme"; two are currently supported: blob
+     * and path. When using the blob scheme and private keys, this property
+     * should be set to the key's encrypted PEM encoded data. When using private
+     * keys with the path scheme, this property should be set to the full UTF-8
+     * encoded path of the key, prefixed with the string "file://" and ending
+     * with a terminating NUL byte. When using PKCS#<!-- -->12 format private
+     * keys and the blob scheme, this property should be set to the
+     * PKCS#<!-- -->12 data and the #NMSetting8021x:phase2-private-key-password
+     * property must be set to password used to decrypt the PKCS#<!-- -->12
+     * certificate and key. When using PKCS#<!-- -->12 files and the path
+     * scheme, this property should be set to the full UTF-8 encoded path of the
+     * key, prefixed with the string "file://" and ending with a terminating
+     * NUL byte, and as with the blob scheme the
+     * #NMSetting8021x:phase2-private-key-password property must be set to the
+     * password used to decode the PKCS#<!-- -->12 private key and certificate.
+     *
+     * Setting this property directly is discouraged; use the
+     * nm_setting_802_1x_set_phase2_private_key() function instead.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-private-key
+     * variable: IEEE_8021X_INNER_PRIVATE_KEY(+)
+     * description: Private key for inner authentication method for EAP-TLS.
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_PRIVATE_KEY] =
+        g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+                           "",
+                           "",
+                           G_TYPE_BYTES,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-private-key-password:
+     *
+     * The password used to decrypt the "phase 2" private key specified in the
+     * #NMSetting8021x:phase2-private-key property when the private key either
+     * uses the path scheme, or is a PKCS#<!-- -->12 format key.  Setting this
+     * property directly is not generally necessary except when returning
+     * secrets to NetworkManager; it is generally set automatically when setting
+     * the private key by the nm_setting_802_1x_set_phase2_private_key()
+     * function.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-private-key-password
+     * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD(+)
+     * description: Password for IEEE_8021X_INNER_PRIVATE_KEY. It can also go to "key-"
+     *   lookaside file, or it can be owned by a secret agent.
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD] =
+        g_param_spec_string(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:phase2-private-key-password-flags:
+     *
+     * Flags indicating how to handle the
+     * #NMSetting8021x:phase2-private-key-password property.
+     **/
+    /* ---ifcfg-rh---
+     * property: phase2-private-key-password-flags
+     * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS(+)
+     * format: NMSettingSecretFlags
+     * description: Password flags for IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD password.
+     * ---end---
+     */
+    obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS] =
+        g_param_spec_flags(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
+                           "",
+                           "",
+                           NM_TYPE_SETTING_SECRET_FLAGS,
+                           NM_SETTING_SECRET_FLAG_NONE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:pin:
+     *
+     * PIN used for EAP authentication methods.
+     **/
+    /* ---ifcfg-rh---
+     * property: pin
+     * variable: IEEE_8021X_PIN(+)
+     * description: The pin secret used for EAP authentication methods.
+     * ---end---
+     */
+    obj_properties[PROP_PIN] =
+        g_param_spec_string(NM_SETTING_802_1X_PIN,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:pin-flags:
+     *
+     * Flags indicating how to handle the #NMSetting8021x:pin property.
+     **/
+    /* ---ifcfg-rh---
+     * property: pin-flags
+     * variable: IEEE_8021X_PIN_FLAGS(+)
+     * description: The secret flags for the pin property.
+     * ---end---
+     */
+    obj_properties[PROP_PIN_FLAGS] = g_param_spec_flags(NM_SETTING_802_1X_PIN_FLAGS,
+                                                        "",
+                                                        "",
+                                                        NM_TYPE_SETTING_SECRET_FLAGS,
+                                                        NM_SETTING_SECRET_FLAG_NONE,
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:system-ca-certs:
+     *
+     * When %TRUE, overrides the #NMSetting8021x:ca-path and
+     * #NMSetting8021x:phase2-ca-path properties using the system CA directory
+     * specified at configure time with the --system-ca-path switch.  The
+     * certificates in this directory are added to the verification chain in
+     * addition to any certificates specified by the #NMSetting8021x:ca-cert and
+     * #NMSetting8021x:phase2-ca-cert properties. If the path provided with
+     * --system-ca-path is rather a file name (bundle of trusted CA certificates),
+     * it overrides #NMSetting8021x:ca-cert and #NMSetting8021x:phase2-ca-cert
+     * properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant).
+     **/
+    /* ---ifcfg-rh---
+     * property: system-ca-certs
+     * variable: IEEE_8021X_SYSTEM_CA_CERTS(+)
+     * description: a boolean value.
+     * ---end---
+     */
+    _nm_setting_property_define_boolean(properties_override,
+                                        obj_properties,
+                                        NM_SETTING_802_1X_SYSTEM_CA_CERTS,
+                                        PROP_SYSTEM_CA_CERTS,
+                                        FALSE,
+                                        NM_SETTING_PARAM_NONE,
+                                        nm_setting_802_1x_get_system_ca_certs);
+
+    /**
+     * NMSetting8021x:auth-timeout:
+     *
+     * A timeout for the authentication. Zero means the global default; if the
+     * global default is not set, the authentication timeout is 25 seconds.
+     *
+     * Since: 1.8
+     **/
+    /* ---ifcfg-rh---
+     * property: auth-timeout
+     * variable: IEEE_8021X_AUTH_TIMEOUT(+)
+     * default: 0
+     * description: Timeout in seconds for the 802.1X authentication. Zero means the global default or 25.
+     * ---end---
+     */
+    obj_properties[PROP_AUTH_TIMEOUT] = g_param_spec_int(
+        NM_SETTING_802_1X_AUTH_TIMEOUT,
+        "",
+        "",
+        0,
+        G_MAXINT32,
+        0,
+        G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSetting8021x:optional:
+     *
+     * Whether the 802.1X authentication is optional. If %TRUE, the activation
+     * will continue even after a timeout or an authentication failure. Setting
+     * the property to %TRUE is currently allowed only for Ethernet connections.
+     * If set to %FALSE, the activation can continue only after a successful
+     * authentication.
+     *
+     * Since: 1.22
+     **/
+    /* ---ifcfg-rh---
+     * property: optional
+     * variable: IEEE_8021X_OPTIONAL(+)
+     * default=no
+     * description: whether the 802.1X authentication is optional
+     * ---end---
+     */
+    _nm_setting_property_define_boolean(properties_override,
+                                        obj_properties,
+                                        NM_SETTING_802_1X_OPTIONAL,
+                                        PROP_OPTIONAL,
+                                        FALSE,
+                                        NM_SETTING_PARAM_NONE,
+                                        nm_setting_802_1x_get_optional);
+
+    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+
+    _nm_setting_class_commit_full(setting_class,
+                                  NM_META_SETTING_TYPE_802_1X,
+                                  NULL,
+                                  properties_override);
+}