]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
OpenSSL: Add 'check_cert_subject' support for TLS server
authorJared Bents <jared.bents@rockwellcollins.com>
Thu, 28 Feb 2019 19:39:50 +0000 (13:39 -0600)
committerJouni Malinen <j@w1.fi>
Mon, 11 Mar 2019 12:09:45 +0000 (14:09 +0200)
This patch added 'check_cert_subject' support to match the value of
every field against the DN of the subject in the client certificate. If
the values do not match, the certificate verification will fail and will
reject the user.

This option allows hostapd to match every individual field in the right
order, also allow '*' character as a wildcard (e.g OU=Development*).

Note: hostapd will match string up to 'wildcard' against the DN of the
subject in the client certificate for every individual field.

Signed-off-by: Paresh Chaudhary <paresh.chaudhary@rockwellcollins.com>
Signed-off-by: Jared Bents <jared.bents@rockwellcollins.com>
Signed-off-by: Jouni Malinen <j@w1.fi>
16 files changed:
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/authsrv.c
src/crypto/tls.h
src/crypto/tls_gnutls.c
src/crypto/tls_internal.c
src/crypto/tls_openssl.c
src/crypto/tls_wolfssl.c
src/eap_peer/eap_config.h
src/eap_peer/eap_tls_common.c
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/config_winreg.c
wpa_supplicant/wpa_cli.c

index 5ddfbfb196b5d9f34b469a5dfb63ab9b114a7a0c..ee3ae65f364be9da8be34e586578d3b9db3e46da 100644 (file)
@@ -2525,6 +2525,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "private_key_passwd") == 0) {
                os_free(bss->private_key_passwd);
                bss->private_key_passwd = os_strdup(pos);
+       } else if (os_strcmp(buf, "check_cert_subject") == 0) {
+               if (!pos[0]) {
+                       wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'",
+                                  line, pos);
+                       return 1;
+               }
+               os_free(bss->check_cert_subject);
+               bss->check_cert_subject = os_strdup(pos);
+               if (!bss->check_cert_subject)
+                       return 1;
        } else if (os_strcmp(buf, "check_crl") == 0) {
                bss->check_crl = atoi(pos);
        } else if (os_strcmp(buf, "check_crl_strict") == 0) {
index deb2af3b05fd1845ce785572db3e5890b671379f..f8caa56239d3a5743458a988137c33dd79d7d326 100644 (file)
@@ -946,6 +946,32 @@ eap_server=0
 # 0 = do not reload CRLs (default)
 # crl_reload_interval = 300
 
+# If check_cert_subject is set, the value of every field will be checked
+# against the DN of the subject in the client certificate. If the values do
+# not match, the certificate verification will fail, rejecting the user.
+# This option allows hostapd to match every individual field in the right order
+# against the DN of the subject in the client certificate.
+#
+# For example, check_cert_subject=C=US/O=XX/OU=ABC/OU=XYZ/CN=1234 will check
+# every individual DN field of the subject in the client certificate. If OU=XYZ
+# comes first in terms of the order in the client certificate (DN field of
+# client certificate C=US/O=XX/OU=XYZ/OU=ABC/CN=1234), hostapd will reject the
+# client because the order of 'OU' is not matching the specified string in
+# check_cert_subject.
+#
+# This option also allows '*' as a wildcard. This option has some limitation.
+# It can only be used as per the following example.
+#
+# For example, check_cert_subject=C=US/O=XX/OU=Production* and we have two
+# clients and DN of the subject in the first client certificate is
+# (C=US/O=XX/OU=Production Unit) and DN of the subject in the second client is
+# (C=US/O=XX/OU=Production Factory). In this case, hostapd will allow both
+# clients because the value of 'OU' field in both client certificates matches
+# 'OU' value in 'check_cert_subject' up to 'wildcard'.
+#
+# * (Allow all clients, e.g., check_cert_subject=*)
+#check_cert_subject=string
+
 # TLS Session Lifetime in seconds
 # This can be used to allow TLS sessions to be cached and resumed with an
 # abbreviated handshake when using EAP-TLS/TTLS/PEAP.
index cd55b574e02d1e763b6f8f49f1ad8482096db7d8..a30859e0c5cceeeff8d10f0a1000e9f240a9360e 100644 (file)
@@ -595,6 +595,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        os_free(conf->server_cert);
        os_free(conf->private_key);
        os_free(conf->private_key_passwd);
+       os_free(conf->check_cert_subject);
        os_free(conf->ocsp_stapling_response);
        os_free(conf->ocsp_stapling_response_multi);
        os_free(conf->dh_file);
index 2671e74c68cb332a6e4bf215834b372649fc86f5..509677a45f0564cebf952fa27da48b93d12d3501 100644 (file)
@@ -392,6 +392,7 @@ struct hostapd_bss_config {
        char *server_cert;
        char *private_key;
        char *private_key_passwd;
+       char *check_cert_subject;
        int check_crl;
        int check_crl_strict;
        unsigned int crl_reload_interval;
index 1bb3d9f6ff7cd38e5bc81d8decee79c283f1310d..eced6c7c6d9411d24338f71d61d8dc6d66ea9dd4 100644 (file)
@@ -233,6 +233,7 @@ int authsrv_init(struct hostapd_data *hapd)
                        hapd->conf->ocsp_stapling_response;
                params.ocsp_stapling_response_multi =
                        hapd->conf->ocsp_stapling_response_multi;
+               params.check_cert_subject = hapd->conf->check_cert_subject;
 
                if (tls_global_set_params(hapd->ssl_ctx, &params)) {
                        wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
index 413cccddc84dc012247e5c6d91271ccdd1666ebc..6cc924150d7d8dc34f5581ba8bf6b27585d96d72 100644 (file)
@@ -42,6 +42,7 @@ enum tls_fail_reason {
        TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9,
        TLS_FAIL_DOMAIN_MISMATCH = 10,
        TLS_FAIL_INSUFFICIENT_KEY_LEN = 11,
+       TLS_FAIL_DN_MISMATCH = 12,
 };
 
 
@@ -156,6 +157,7 @@ struct tls_config {
  * @ocsp_stapling_response_multi: DER encoded file with cached OCSP stapling
  *     response list (OCSPResponseList for ocsp_multi in RFC 6961) or %NULL if
  *     ocsp_multi is not enabled
+ * @check_cert_subject: Client certificate subject name matching string
  *
  * TLS connection parameters to be configured with tls_connection_set_params()
  * and tls_global_set_params().
@@ -198,6 +200,7 @@ struct tls_connection_params {
        unsigned int flags;
        const char *ocsp_stapling_response;
        const char *ocsp_stapling_response_multi;
+       const char *check_cert_subject;
 };
 
 
index 527d01ecfd16e127431cfde704458cd53f524c28..73e80f3b782b3507713ff6dbd230b05176281916 100644 (file)
@@ -739,6 +739,9 @@ int tls_global_set_params(void *tls_ctx,
        struct tls_global *global = tls_ctx;
        int ret;
 
+       if (params->check_cert_subject)
+               return -1; /* not yet supported */
+
        /* Currently, global parameters are only set when running in server
         * mode. */
        global->server = 1;
index 57b3e632df545e7c394f2a4579ef819064facea8..2876630aa8ad4be08fe5ceaf39ae9815cf5d9415 100644 (file)
@@ -309,6 +309,9 @@ int tls_global_set_params(void *tls_ctx,
        struct tls_global *global = tls_ctx;
        struct tlsv1_credentials *cred;
 
+       if (params->check_cert_subject)
+               return -1; /* not yet supported */
+
        /* Currently, global parameters are only set when running in server
         * mode. */
        global->server = 1;
index 18d76737e78a1c96319215eaf1bdcfc217510e65..699e074436339dc21c652e974773e4cf8e07c837 100644 (file)
@@ -219,6 +219,7 @@ struct tls_data {
        char *ca_cert;
        unsigned int crl_reload_interval;
        struct os_reltime crl_last_reload;
+       char *check_cert_subject;
 };
 
 struct tls_connection {
@@ -232,6 +233,7 @@ struct tls_connection {
        EVP_PKEY *private_key; /* the private key if using engine */
 #endif /* OPENSSL_NO_ENGINE */
        char *subject_match, *altsubject_match, *suffix_match, *domain_match;
+       char *check_cert_subject;
        int read_alerts, write_alerts, failed;
 
        tls_session_ticket_cb session_ticket_cb;
@@ -1134,6 +1136,7 @@ void tls_deinit(void *ssl_ctx)
                tls_global = NULL;
        }
 
+       os_free(data->check_cert_subject);
        os_free(data);
 }
 
@@ -1611,6 +1614,7 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
        os_free(conn->altsubject_match);
        os_free(conn->suffix_match);
        os_free(conn->domain_match);
+       os_free(conn->check_cert_subject);
        os_free(conn->session_ticket);
        os_free(conn);
 }
@@ -1763,6 +1767,219 @@ static int domain_suffix_match(const u8 *val, size_t len, const char *match,
 #endif /* CONFIG_NATIVE_WINDOWS */
 
 
+struct tls_dn_field_order_cnt {
+       u8 cn;
+       u8 c;
+       u8 l;
+       u8 st;
+       u8 o;
+       u8 ou;
+       u8 email;
+};
+
+
+static int get_dn_field_index(const struct tls_dn_field_order_cnt *dn_cnt,
+                             int nid)
+{
+       switch (nid) {
+       case NID_commonName:
+               return dn_cnt->cn;
+       case NID_countryName:
+               return dn_cnt->c;
+       case NID_localityName:
+               return dn_cnt->l;
+       case NID_stateOrProvinceName:
+               return dn_cnt->st;
+       case NID_organizationName:
+               return dn_cnt->o;
+       case NID_organizationalUnitName:
+               return dn_cnt->ou;
+       case NID_pkcs9_emailAddress:
+               return dn_cnt->email;
+       default:
+               wpa_printf(MSG_ERROR,
+                          "TLS: Unknown NID '%d' in check_cert_subject",
+                          nid);
+               return -1;
+       }
+}
+
+
+/**
+ * match_dn_field - Match configuration DN field against Certificate DN field
+ * @cert: Certificate
+ * @nid: NID of DN field
+ * @field: Field name
+ * @value DN field value which is passed from configuration
+ *     e.g., if configuration have C=US and this argument will point to US.
+ * @dn_cnt: DN matching context
+ * Returns: 1 on success and 0 on failure
+ */
+static int match_dn_field(const X509 *cert, int nid, const char *field,
+                         const char *value,
+                         const struct tls_dn_field_order_cnt *dn_cnt)
+{
+       int i, ret = 0, len, config_dn_field_index, match_index = 0;
+       X509_NAME *name;
+
+       len = os_strlen(value);
+       name = X509_get_subject_name(cert);
+
+       /* Assign incremented cnt for every field of DN to check DN field in
+        * right order */
+       config_dn_field_index = get_dn_field_index(dn_cnt, nid);
+       if (config_dn_field_index < 0)
+               return 0;
+
+       /* Fetch value based on NID */
+       for (i = -1; (i = X509_NAME_get_index_by_NID(name, nid, i)) > -1;) {
+               X509_NAME_ENTRY *e;
+               ASN1_STRING *cn;
+
+               e = X509_NAME_get_entry(name, i);
+               if (!e)
+                       continue;
+
+               cn = X509_NAME_ENTRY_get_data(e);
+               if (!cn)
+                       continue;
+
+               match_index++;
+
+               /* check for more than one DN field with same name */
+               if (match_index != config_dn_field_index)
+                       continue;
+
+               /* Check wildcard at the right end side */
+               /* E.g., if OU=develop* mentioned in configuration, allow 'OU'
+                * of the subject in the client certificate to start with
+                * 'develop' */
+               if (len > 0 && value[len - 1] == '*') {
+                       /* Compare actual certificate DN field value with
+                        * configuration DN field value up to the specified
+                        * length. */
+                       ret = ASN1_STRING_length(cn) >= len - 1 &&
+                               os_memcmp(ASN1_STRING_get0_data(cn), value,
+                                         len - 1) == 0;
+               } else {
+                       /* Compare actual certificate DN field value with
+                        * configuration DN field value */
+                       ret = ASN1_STRING_length(cn) == len &&
+                               os_memcmp(ASN1_STRING_get0_data(cn), value,
+                                         len) == 0;
+               }
+               if (!ret) {
+                       wpa_printf(MSG_ERROR,
+                                  "OpenSSL: Failed to match %s '%s' with certificate DN field value '%s'",
+                                  field, value, ASN1_STRING_get0_data(cn));
+               }
+               break;
+       }
+
+       return ret;
+}
+
+
+/**
+ * get_value_from_field - Get value from DN field
+ * @cert: Certificate
+ * @field_str: DN field string which is passed from configuration file (e.g.,
+ *      C=US)
+ * @dn_cnt: DN matching context
+ * Returns: 1 on success and 0 on failure
+ */
+static int get_value_from_field(const X509 *cert, char *field_str,
+                               struct tls_dn_field_order_cnt *dn_cnt)
+{
+       int nid;
+       char *context = NULL, *name, *value;
+
+       if (os_strcmp(field_str, "*") == 0)
+               return 1; /* wildcard matches everything */
+
+       name = str_token(field_str, "=", &context);
+       if (!name)
+               return 0;
+
+       /* Compare all configured DN fields and assign nid based on that to
+        * fetch correct value from certificate subject */
+       if (os_strcmp(name, "CN") == 0) {
+               nid = NID_commonName;
+               dn_cnt->cn++;
+       } else if(os_strcmp(name, "C") == 0) {
+               nid = NID_countryName;
+               dn_cnt->c++;
+       } else if (os_strcmp(name, "L") == 0) {
+               nid = NID_localityName;
+               dn_cnt->l++;
+       } else if (os_strcmp(name, "ST") == 0) {
+               nid = NID_stateOrProvinceName;
+               dn_cnt->st++;
+       } else if (os_strcmp(name, "O") == 0) {
+               nid = NID_organizationName;
+               dn_cnt->o++;
+       } else if (os_strcmp(name, "OU") == 0) {
+               nid = NID_organizationalUnitName;
+               dn_cnt->ou++;
+       } else if (os_strcmp(name, "emailAddress") == 0) {
+               nid = NID_pkcs9_emailAddress;
+               dn_cnt->email++;
+       } else {
+               wpa_printf(MSG_ERROR,
+                       "TLS: Unknown field '%s' in check_cert_subject", name);
+               return 0;
+       }
+
+       value = str_token(field_str, "=", &context);
+       if (!value) {
+               wpa_printf(MSG_ERROR,
+                          "TLS: Distinguished Name field '%s' value is not defined in check_cert_subject",
+                          name);
+               return 0;
+       }
+
+       return match_dn_field(cert, nid, name, value, dn_cnt);
+}
+
+
+/**
+ * tls_match_dn_field - Match subject DN field with check_cert_subject
+ * @cert: Certificate
+ * @match: check_cert_subject string
+ * Returns: Return 1 on success and 0 on failure
+*/
+static int tls_match_dn_field(X509 *cert, const char *match)
+{
+       const char *token, *last = NULL;
+       char field[256];
+       struct tls_dn_field_order_cnt dn_cnt;
+
+       os_memset(&dn_cnt, 0, sizeof(dn_cnt));
+
+       /* Maximum length of each DN field is 255 characters */
+
+       /* Process each '/' delimited field */
+       while ((token = cstr_token(match, "/", &last))) {
+               if (last - token >= (int) sizeof(field)) {
+                       wpa_printf(MSG_ERROR,
+                                  "OpenSSL: Too long DN matching field value in '%s'",
+                                  match);
+                       return 0;
+               }
+               os_memcpy(field, token, last - token);
+               field[last - token] = '\0';
+
+               if (!get_value_from_field(cert, field, &dn_cnt)) {
+                       wpa_printf(MSG_DEBUG, "OpenSSL: No match for DN '%s'",
+                                  field);
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+
 static int tls_match_suffix(X509 *cert, const char *match, int full)
 {
 #ifdef CONFIG_NATIVE_WINDOWS
@@ -2027,6 +2244,7 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
        struct tls_connection *conn;
        struct tls_context *context;
        char *match, *altmatch, *suffix_match, *domain_match;
+       const char *check_cert_subject;
        const char *err_str;
 
        err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
@@ -2127,6 +2345,18 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
                   "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
                   preverify_ok, err, err_str,
                   conn->ca_cert_verify, depth, buf);
+       check_cert_subject = conn->check_cert_subject;
+       if (!check_cert_subject)
+               check_cert_subject = conn->data->check_cert_subject;
+       if (check_cert_subject) {
+               if (depth == 0 &&
+                   !tls_match_dn_field(err_cert, check_cert_subject)) {
+                       preverify_ok = 0;
+                       openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+                                              "Distinguished Name",
+                                              TLS_FAIL_DN_MISMATCH);
+               }
+       }
        if (depth == 0 && match && os_strstr(buf, match) == NULL) {
                wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
                           "match with '%s'", buf, match);
@@ -2503,7 +2733,8 @@ static int tls_connection_set_subject_match(struct tls_connection *conn,
                                            const char *subject_match,
                                            const char *altsubject_match,
                                            const char *suffix_match,
-                                           const char *domain_match)
+                                           const char *domain_match,
+                                           const char *check_cert_subject)
 {
        os_free(conn->subject_match);
        conn->subject_match = NULL;
@@ -2537,6 +2768,14 @@ static int tls_connection_set_subject_match(struct tls_connection *conn,
                        return -1;
        }
 
+       os_free(conn->check_cert_subject);
+       conn->check_cert_subject = NULL;
+       if (check_cert_subject) {
+               conn->check_cert_subject = os_strdup(check_cert_subject);
+               if (!conn->check_cert_subject)
+                       return -1;
+       }
+
        return 0;
 }
 
@@ -4591,7 +4830,8 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
                                             params->subject_match,
                                             params->altsubject_match,
                                             params->suffix_match,
-                                            params->domain_match))
+                                            params->domain_match,
+                                            params->check_cert_subject))
                return -1;
 
        if (engine_id && ca_cert_id) {
@@ -4732,6 +4972,15 @@ int tls_global_set_params(void *tls_ctx,
                           __func__, ERR_error_string(err, NULL));
        }
 
+       os_free(data->check_cert_subject);
+       data->check_cert_subject = NULL;
+       if (params->check_cert_subject) {
+               data->check_cert_subject =
+                       os_strdup(params->check_cert_subject);
+               if (!data->check_cert_subject)
+                       return -1;
+       }
+
        if (tls_global_ca_cert(data, params->ca_cert) ||
            tls_global_client_cert(data, params->client_cert) ||
            tls_global_private_key(data, params->private_key,
index b59622e5e7ec7a7f2fd7403479386e7758d235f1..39a24b3309a0c620e2980a5c0b421748d3db482b 100644 (file)
@@ -1487,6 +1487,9 @@ int tls_global_set_params(void *tls_ctx,
 {
        wpa_printf(MSG_DEBUG, "SSL: global set params");
 
+       if (params->check_cert_subject)
+               return -1; /* not yet supported */
+
        if (tls_global_ca_cert(tls_ctx, params->ca_cert) < 0) {
                wpa_printf(MSG_INFO, "SSL: Failed to load ca cert file '%s'",
                           params->ca_cert);
index dbe0fb6f2f19cba88802fa813744dd30ec006e1e..56278930d643b1e63def9cf77dcf9d7bd5837866 100644 (file)
@@ -196,6 +196,48 @@ struct eap_peer_config {
         */
        char *subject_match;
 
+       /**
+        * check_cert_subject - Constraint for server certificate subject fields
+        *
+        * If check_cert_subject is set, the value of every field will be
+        * checked against the DN of the subject in the authentication server
+        * certificate. If the values do not match, the certificate verification
+        * will fail, rejecting the server. This option allows wpa_supplicant to
+        * match every individual field in the right order against the DN of the
+        * subject in the server certificate.
+        *
+        * For example, check_cert_subject=C=US/O=XX/OU=ABC/OU=XYZ/CN=1234 will
+        * check every individual DN field of the subject in the server
+        * certificate. If OU=XYZ comes first in terms of the order in the
+        * server certificate (DN field of server certificate
+        * C=US/O=XX/OU=XYZ/OU=ABC/CN=1234), wpa_supplicant will reject the
+        * server because the order of 'OU' is not matching the specified string
+        * in check_cert_subject.
+        *
+        * This option also allows '*' as a wildcard. This option has some
+        * limitation.
+        * It can only be used as per the following example.
+        *
+        * For example, check_cert_subject=C=US/O=XX/OU=Production* and we have
+        * two servers and DN of the subject in the first server certificate is
+        * (C=US/O=XX/OU=Production Unit) and DN of the subject in the second
+        * server is (C=US/O=XX/OU=Production Factory). In this case,
+        * wpa_supplicant will allow both servers because the value of 'OU'
+        * field in both server certificates matches 'OU' value in
+        * 'check_cert_subject' up to 'wildcard'.
+        *
+        * (Allow all servers, e.g., check_cert_subject=*)
+        */
+       char *check_cert_subject;
+
+       /**
+        * check_cert_subject2 - Constraint for server certificate subject fields
+        *
+        * This field is like check_cert_subject, but used for phase 2 (inside
+        * EAP-TTLS/PEAP/FAST tunnel) authentication.
+        */
+       char *check_cert_subject2;
+
        /**
         * altsubject_match - Constraint for server certificate alt. subject
         *
index a7d31cf6b81a87f945ef9b96af4b4c505b2bb650..1ee01a2da98ebca7f96d36eaffcea641b304694b 100644 (file)
@@ -116,6 +116,7 @@ static void eap_tls_params_from_conf1(struct tls_connection_params *params,
        params->dh_file = config->dh_file;
        params->subject_match = config->subject_match;
        params->altsubject_match = config->altsubject_match;
+       params->check_cert_subject = config->check_cert_subject;
        params->suffix_match = config->domain_suffix_match;
        params->domain_match = config->domain_match;
        params->engine = config->engine;
@@ -139,6 +140,7 @@ static void eap_tls_params_from_conf2(struct tls_connection_params *params,
        params->dh_file = config->dh_file2;
        params->subject_match = config->subject_match2;
        params->altsubject_match = config->altsubject_match2;
+       params->check_cert_subject = config->check_cert_subject2;
        params->suffix_match = config->domain_suffix_match2;
        params->domain_match = config->domain_match2;
        params->engine = config->engine2;
index d4122b524b105a971ddc42c9e30dcbd8bb37dd82..2058175f885e5f39575afb09a6be7c9506b6adfc 100644 (file)
@@ -2257,6 +2257,7 @@ static const struct parse_data ssid_fields[] = {
        { STR_KEYe(private_key_passwd) },
        { STRe(dh_file) },
        { STRe(subject_match) },
+       { STRe(check_cert_subject) },
        { STRe(altsubject_match) },
        { STRe(domain_suffix_match) },
        { STRe(domain_match) },
@@ -2267,6 +2268,7 @@ static const struct parse_data ssid_fields[] = {
        { STR_KEYe(private_key2_passwd) },
        { STRe(dh_file2) },
        { STRe(subject_match2) },
+       { STRe(check_cert_subject2) },
        { STRe(altsubject_match2) },
        { STRe(domain_suffix_match2) },
        { STRe(domain_match2) },
@@ -2525,6 +2527,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        str_clear_free(eap->private_key_passwd);
        os_free(eap->dh_file);
        os_free(eap->subject_match);
+       os_free(eap->check_cert_subject);
        os_free(eap->altsubject_match);
        os_free(eap->domain_suffix_match);
        os_free(eap->domain_match);
@@ -2535,6 +2538,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        str_clear_free(eap->private_key2_passwd);
        os_free(eap->dh_file2);
        os_free(eap->subject_match2);
+       os_free(eap->check_cert_subject2);
        os_free(eap->altsubject_match2);
        os_free(eap->domain_suffix_match2);
        os_free(eap->domain_match2);
index dd97d43a91ca6dde2efa791b572070214d412840..26f6ee1478445ac09fb5b6fae2fcf6f658df60bf 100644 (file)
@@ -782,6 +782,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        STR(private_key_passwd);
        STR(dh_file);
        STR(subject_match);
+       STR(check_cert_subject);
        STR(altsubject_match);
        STR(domain_suffix_match);
        STR(domain_match);
@@ -792,6 +793,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        STR(private_key2_passwd);
        STR(dh_file2);
        STR(subject_match2);
+       STR(check_cert_subject2);
        STR(altsubject_match2);
        STR(domain_suffix_match2);
        STR(domain_match2);
index c3ab817c5c06163f11e814dde6892a13d6c243a8..6328e91b989e24b7609c041cc952e19d2f8c6783 100644 (file)
@@ -896,6 +896,7 @@ static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id)
        STR(private_key_passwd);
        STR(dh_file);
        STR(subject_match);
+       STR(check_cert_subject);
        STR(altsubject_match);
        STR(ca_cert2);
        STR(ca_path2);
@@ -904,6 +905,7 @@ static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id)
        STR(private_key2_passwd);
        STR(dh_file2);
        STR(subject_match2);
+       STR(check_cert_subject2);
        STR(altsubject_match2);
        STR(phase1);
        STR(phase2);
index 9881021c2f0bf74170605ca114329f589c86b5bf..695fcbe04995644ca349082b87bb6f564142f3a8 100644 (file)
@@ -1411,9 +1411,11 @@ static const char *network_fields[] = {
        "eap", "identity", "anonymous_identity", "password", "ca_cert",
        "ca_path", "client_cert", "private_key", "private_key_passwd",
        "dh_file", "subject_match", "altsubject_match",
+       "check_cert_subject",
        "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
        "client_cert2", "private_key2", "private_key2_passwd",
        "dh_file2", "subject_match2", "altsubject_match2",
+       "check_cert_subject2",
        "domain_suffix_match2", "domain_match2", "phase1", "phase2",
        "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
        "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",