aboutsummaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2015-01-21 13:19:05 -0800
committerDmitry Shmidt <dimitrysh@google.com>2015-01-21 13:26:50 -0800
commit2f74e36e84064ffa32f82f3decf36b653c7e4fad (patch)
tree184eb654d7eeb89fbca4b8735baf64c07c1c721d /src/crypto
parentff787d557db719adea0fdf2679667500c65cf74d (diff)
downloadandroid_external_wpa_supplicant_8-2f74e36e84064ffa32f82f3decf36b653c7e4fad.tar.gz
android_external_wpa_supplicant_8-2f74e36e84064ffa32f82f3decf36b653c7e4fad.tar.bz2
android_external_wpa_supplicant_8-2f74e36e84064ffa32f82f3decf36b653c7e4fad.zip
Cumulative patch from commit fb09ed338919db09f3990196171fa73b37e7a17f (DO NOT MERGE)
fb09ed3 Interworking: Notify the ANQP parsing status d10b01d HS20: Provide appropriate permission to the OSU related files 73f1ee0 HS20: Fix TrustRoot path for PolicyUpdate node in PPS MO 54a0ac0 HS20: Return result of cmd_sub_rem in hs20-osu-client b62b0cb WNM: Fix possible memory leak by free buf 9bd0273 EAP: Fix possible memory leak in eap_ttls_process_decrypted() b760e64 eap_server: Avoid NULL pointer dereference in eap_fast_encrypt_phase2() 948d3a8 hostapd: Remove unused variable from hostapd_get_hw_features dd09e42 Fix memory leak in wpa_supplicant global bgscan configuration 30f459c wpa_cli: Fix NULL dereference on printf string argument 414f23d Avoid NULL string in printf on EAP method names in authenticator b72b2ad P2P: Stop p2p_listen/find on wpas_p2p_invite 7b7b444 nl80211: Fix reading of the extended capabilities mask 7e608d1 P2P: Use the correct wpa_s interface to handle P2P state flush fd83335 AP: Enable HT Tx STBC for AP/GO if supported by driver d90bfa9 Move external_scan_running to wpa_radio 0c5f01f Clear reattach flag in fast associate flow 8ad8bc5 NFC: Redirect NFC commands on global control interface 57ae1f5 P2P: Fix P2P invitation with NFC 07565ab WNM: Fix the length of WNM_BSS_QUERY control interface command 2d9c99e Retry scan-for-connect if driver trigger fails 911942e Add a test framework for various wpa_supplicant failure cases 6b46bfa WPS: Re-fix an interoperability issue with mixed mode and AP Settings 1648cc6 ACS: Allow subset of channels to be configured 95ff306 nl80211: Allow HT/VHT to be disabled for IBSS 7451a21 mesh: Return negative value on join failed 5a2a6de mesh: Make inactivity timer configurable b9749ba AP: Expire STA without entry in kernel a114c72 AP: Remove redundant condition for STA expiration 0d787f0 Fix RADIUS client with out-of-memory and missing shared secret 0efcad2 Print in debug log whether attached monitor is for global interface 8266e6c HS 2.0: Try to use same BSS entry for storing GAS results 6c69991 Make wpa_supplicant FLUSH command more likely to clear all BSS entries 2dbe63a Write reason for scan only_new_results into debug log 242b83a eapol_test: Fix cert_cb() function arguments a8826b1 Interworking: Avoid busy loop in scan result mismatch corner cases edd5939 Interworking: Start ANQP fetch from eloop callback cbc210d RADIUS DAS: Allow PMKSA cache entry to be removed without association 4e871ed RADIUS DAS: Support Acct-Multi-Session-Id as a session identifier b52c0d4 Add authMultiSessionId into hostapd STA info 861beb7 RADIUS DAS: Check for single session match for Disconnect-Request 783b2a9 Interworking: Fix INTERWORKING_CONNECT with zero-length SSID BSS entry 1fef85c nl80211: Fix AP-scan-in-STA-mode error path behavior cebee30 Add domain_match network profile parameter d07d3fb Add peer certificate alt subject name information to EAP events 98a4cd4 D-Bus: Clear cached EAP data on network profile changes 483dd6a Include peer certificate always in EAP events dd5f902 Get rid of a compiler warning d29fa3a Extend VENDOR_ELEM parameters to cover non-P2P Association Request e7d0e97 hostapd: Add vendor specific VHT extension for the 2.4 GHz band Change-Id: I45436c49986cd6bddbd869db3f474871a29ce1dc Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/tls.h15
-rw-r--r--src/crypto/tls_gnutls.c36
-rw-r--r--src/crypto/tls_internal.c5
-rw-r--r--src/crypto/tls_openssl.c104
-rw-r--r--src/crypto/tls_schannel.c5
5 files changed, 149 insertions, 16 deletions
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index a4f954c7..9ae95a66 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -41,9 +41,13 @@ enum tls_fail_reason {
TLS_FAIL_ALTSUBJECT_MISMATCH = 6,
TLS_FAIL_BAD_CERTIFICATE = 7,
TLS_FAIL_SERVER_CHAIN_PROBE = 8,
- TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9
+ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9,
+ TLS_FAIL_DOMAIN_MISMATCH = 10,
};
+
+#define TLS_MAX_ALT_SUBJECT 10
+
union tls_event_data {
struct {
int depth;
@@ -59,6 +63,8 @@ union tls_event_data {
const struct wpabuf *cert;
const u8 *hash;
size_t hash_len;
+ const char *altsubject[TLS_MAX_ALT_SUBJECT];
+ int num_altsubject;
} peer_cert;
struct {
@@ -102,7 +108,11 @@ struct tls_config {
* @altsubject_match: String to match in the alternative subject of the peer
* certificate or %NULL to allow all alternative subjects
* @suffix_match: String to suffix match in the dNSName or CN of the peer
- * certificate or %NULL to allow all domain names
+ * certificate or %NULL to allow all domain names. This may allow subdomains an
+ * wildcard certificates. Each domain name label must have a full match.
+ * @domain_match: String to match in the dNSName or CN of the peer
+ * certificate or %NULL to allow all domain names. This requires a full,
+ * case-insensitive match.
* @client_cert: File or reference name for client X.509 certificate in PEM or
* DER format
* @client_cert_blob: client_cert as inlined data or %NULL if not used
@@ -146,6 +156,7 @@ struct tls_connection_params {
const char *subject_match;
const char *altsubject_match;
const char *suffix_match;
+ const char *domain_match;
const char *client_cert;
const u8 *client_cert_blob;
size_t client_cert_blob_len;
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index f2eacb5d..65db6fcc 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -58,6 +58,7 @@ struct tls_connection {
gnutls_certificate_credentials_t xcred;
char *suffix_match;
+ char *domain_match;
unsigned int flags;
};
@@ -280,6 +281,7 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
wpabuf_free(conn->push_buf);
wpabuf_free(conn->pull_buf);
os_free(conn->suffix_match);
+ os_free(conn->domain_match);
os_free(conn);
}
@@ -363,6 +365,21 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
+#if GNUTLS_VERSION_NUMBER >= 0x030300
+ os_free(conn->domain_match);
+ conn->domain_match = NULL;
+ if (params->domain_match) {
+ conn->domain_match = os_strdup(params->domain_match);
+ if (conn->domain_match == NULL)
+ return -1;
+ }
+#else /* < 3.3.0 */
+ if (params->domain_match) {
+ wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
+ return -1;
+ }
+#endif /* >= 3.3.0 */
+
conn->flags = params->flags;
if (params->openssl_ciphers) {
@@ -1111,6 +1128,25 @@ static int tls_connection_verify_peer(gnutls_session_t session)
goto out;
}
+#if GNUTLS_VERSION_NUMBER >= 0x030300
+ if (conn->domain_match &&
+ !gnutls_x509_crt_check_hostname2(
+ cert, conn->domain_match,
+ GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
+ wpa_printf(MSG_WARNING,
+ "TLS: Domain match '%s' not found",
+ conn->domain_match);
+ gnutls_tls_fail_event(
+ conn, &certs[i], i, buf,
+ "Domain mismatch",
+ TLS_FAIL_DOMAIN_MISMATCH);
+ err = GNUTLS_A_BAD_CERTIFICATE;
+ gnutls_x509_crt_deinit(cert);
+ os_free(buf);
+ goto out;
+ }
+#endif /* >= 3.3.0 */
+
/* TODO: validate altsubject_match.
* For now, any such configuration is rejected in
* tls_connection_set_params() */
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index 86375d11..0c955da2 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -205,6 +205,11 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
+ if (params->domain_match) {
+ wpa_printf(MSG_INFO, "TLS: domain_match not supported");
+ return -1;
+ }
+
if (params->openssl_ciphers) {
wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
return -1;
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 5433ebb2..e3ca0682 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -96,7 +96,7 @@ struct tls_connection {
ENGINE *engine; /* functional reference to the engine */
EVP_PKEY *private_key; /* the private key if using engine */
#endif /* OPENSSL_NO_ENGINE */
- char *subject_match, *altsubject_match, *suffix_match;
+ char *subject_match, *altsubject_match, *suffix_match, *domain_match;
int read_alerts, write_alerts, failed;
tls_session_ticket_cb session_ticket_cb;
@@ -1098,6 +1098,7 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
os_free(conn->subject_match);
os_free(conn->altsubject_match);
os_free(conn->suffix_match);
+ os_free(conn->domain_match);
os_free(conn->session_ticket);
os_free(conn);
}
@@ -1190,7 +1191,8 @@ static int tls_match_altsubject(X509 *cert, const char *match)
#ifndef CONFIG_NATIVE_WINDOWS
-static int domain_suffix_match(const u8 *val, size_t len, const char *match)
+static int domain_suffix_match(const u8 *val, size_t len, const char *match,
+ int full)
{
size_t i, match_len;
@@ -1203,7 +1205,7 @@ static int domain_suffix_match(const u8 *val, size_t len, const char *match)
}
match_len = os_strlen(match);
- if (match_len > len)
+ if (match_len > len || (full && match_len != len))
return 0;
if (os_strncasecmp((const char *) val + len - match_len, match,
@@ -1222,7 +1224,7 @@ static int domain_suffix_match(const u8 *val, size_t len, const char *match)
#endif /* CONFIG_NATIVE_WINDOWS */
-static int tls_match_suffix(X509 *cert, const char *match)
+static int tls_match_suffix(X509 *cert, const char *match, int full)
{
#ifdef CONFIG_NATIVE_WINDOWS
/* wincrypt.h has conflicting X509_NAME definition */
@@ -1235,7 +1237,8 @@ static int tls_match_suffix(X509 *cert, const char *match)
int dns_name = 0;
X509_NAME *name;
- wpa_printf(MSG_DEBUG, "TLS: Match domain against suffix %s", match);
+ wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
+ full ? "": "suffix ", match);
ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
@@ -1248,8 +1251,10 @@ static int tls_match_suffix(X509 *cert, const char *match)
gen->d.dNSName->data,
gen->d.dNSName->length);
if (domain_suffix_match(gen->d.dNSName->data,
- gen->d.dNSName->length, match) == 1) {
- wpa_printf(MSG_DEBUG, "TLS: Suffix match in dNSName found");
+ gen->d.dNSName->length, match, full) ==
+ 1) {
+ wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
+ full ? "Match" : "Suffix match");
return 1;
}
}
@@ -1276,13 +1281,16 @@ static int tls_match_suffix(X509 *cert, const char *match)
continue;
wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
cn->data, cn->length);
- if (domain_suffix_match(cn->data, cn->length, match) == 1) {
- wpa_printf(MSG_DEBUG, "TLS: Suffix match in commonName found");
+ if (domain_suffix_match(cn->data, cn->length, match, full) == 1)
+ {
+ wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
+ full ? "Match" : "Suffix match");
return 1;
}
}
- wpa_printf(MSG_DEBUG, "TLS: No CommonName suffix match found");
+ wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
+ full ? "": "suffix ");
return 0;
#endif /* CONFIG_NATIVE_WINDOWS */
}
@@ -1377,6 +1385,11 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
struct wpabuf *cert = NULL;
union tls_event_data ev;
struct tls_context *context = conn->context;
+ char *altsubject[TLS_MAX_ALT_SUBJECT];
+ int alt, num_altsubject = 0;
+ GENERAL_NAME *gen;
+ void *ext;
+ stack_index_t i;
#ifdef CONFIG_SHA256
u8 hash[32];
#endif /* CONFIG_SHA256 */
@@ -1403,8 +1416,52 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
#endif /* CONFIG_SHA256 */
ev.peer_cert.depth = depth;
ev.peer_cert.subject = subject;
+
+ ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
+ for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
+ char *pos;
+
+ if (num_altsubject == TLS_MAX_ALT_SUBJECT)
+ break;
+ gen = sk_GENERAL_NAME_value(ext, i);
+ if (gen->type != GEN_EMAIL &&
+ gen->type != GEN_DNS &&
+ gen->type != GEN_URI)
+ continue;
+
+ pos = os_malloc(10 + gen->d.ia5->length + 1);
+ if (pos == NULL)
+ break;
+ altsubject[num_altsubject++] = pos;
+
+ switch (gen->type) {
+ case GEN_EMAIL:
+ os_memcpy(pos, "EMAIL:", 6);
+ pos += 6;
+ break;
+ case GEN_DNS:
+ os_memcpy(pos, "DNS:", 4);
+ pos += 4;
+ break;
+ case GEN_URI:
+ os_memcpy(pos, "URI:", 4);
+ pos += 4;
+ break;
+ }
+
+ os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
+ pos += gen->d.ia5->length;
+ *pos = '\0';
+ }
+
+ for (alt = 0; alt < num_altsubject; alt++)
+ ev.peer_cert.altsubject[alt] = altsubject[alt];
+ ev.peer_cert.num_altsubject = num_altsubject;
+
context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
wpabuf_free(cert);
+ for (alt = 0; alt < num_altsubject; alt++)
+ os_free(altsubject[alt]);
}
@@ -1416,7 +1473,7 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
SSL *ssl;
struct tls_connection *conn;
struct tls_context *context;
- char *match, *altmatch, *suffix_match;
+ char *match, *altmatch, *suffix_match, *domain_match;
const char *err_str;
err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
@@ -1444,6 +1501,7 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
match = conn->subject_match;
altmatch = conn->altsubject_match;
suffix_match = conn->suffix_match;
+ domain_match = conn->domain_match;
if (!preverify_ok && !conn->ca_cert_verify)
preverify_ok = 1;
@@ -1513,13 +1571,21 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
"AltSubject mismatch",
TLS_FAIL_ALTSUBJECT_MISMATCH);
} else if (depth == 0 && suffix_match &&
- !tls_match_suffix(err_cert, suffix_match)) {
+ !tls_match_suffix(err_cert, suffix_match, 0)) {
wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
suffix_match);
preverify_ok = 0;
openssl_tls_fail_event(conn, err_cert, err, depth, buf,
"Domain suffix mismatch",
TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
+ } else if (depth == 0 && domain_match &&
+ !tls_match_suffix(err_cert, domain_match, 1)) {
+ wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
+ domain_match);
+ preverify_ok = 0;
+ openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+ "Domain mismatch",
+ TLS_FAIL_DOMAIN_MISMATCH);
} else
openssl_tls_cert_event(conn, err_cert, depth, buf);
@@ -1783,7 +1849,8 @@ int tls_global_set_verify(void *ssl_ctx, int check_crl)
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 *suffix_match,
+ const char *domain_match)
{
os_free(conn->subject_match);
conn->subject_match = NULL;
@@ -1809,6 +1876,14 @@ static int tls_connection_set_subject_match(struct tls_connection *conn,
return -1;
}
+ os_free(conn->domain_match);
+ conn->domain_match = NULL;
+ if (domain_match) {
+ conn->domain_match = os_strdup(domain_match);
+ if (conn->domain_match == NULL)
+ return -1;
+ }
+
return 0;
}
@@ -3273,7 +3348,8 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
if (tls_connection_set_subject_match(conn,
params->subject_match,
params->altsubject_match,
- params->suffix_match))
+ params->suffix_match,
+ params->domain_match))
return -1;
if (engine_id && ca_cert_id) {
diff --git a/src/crypto/tls_schannel.c b/src/crypto/tls_schannel.c
index a43b4874..31a2c946 100644
--- a/src/crypto/tls_schannel.c
+++ b/src/crypto/tls_schannel.c
@@ -707,6 +707,11 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
+ if (params->domain_match) {
+ wpa_printf(MSG_INFO, "TLS: domain_match not supported");
+ return -1;
+ }
+
if (params->openssl_ciphers) {
wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
return -1;