aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-12-20 17:14:17 (GMT)
committerJouni Malinen <j@w1.fi>2010-01-09 19:01:29 (GMT)
commit7bd9007b3c0cfedad951a070c922826675fc1074 (patch)
tree224f72bb9f7dc63a671794043c492bd23898889b
parenta58e3e6e085b1b15ecda62902b0e8d3e860efab4 (diff)
downloadhostap-06-7bd9007b3c0cfedad951a070c922826675fc1074.zip
hostap-06-7bd9007b3c0cfedad951a070c922826675fc1074.tar.gz
hostap-06-7bd9007b3c0cfedad951a070c922826675fc1074.tar.bz2
GnuTLS: Report certificate validation failures with TLS alert
In addition, show more detailed reason for the failure in debug log. (cherry picked from commit 4a1e97790de4c3e9ddc3aed98836a2a2b26a0ad8)
-rw-r--r--src/crypto/tls_gnutls.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 05d6dd3..5015585 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -847,7 +847,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
}
-static int tls_connection_verify_peer(struct tls_connection *conn)
+static int tls_connection_verify_peer(struct tls_connection *conn,
+ gnutls_alert_description_t *err)
{
unsigned int status, num_certs, i;
struct os_time now;
@@ -857,22 +858,39 @@ static int tls_connection_verify_peer(struct tls_connection *conn)
if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
"certificate chain");
+ *err = GNUTLS_A_INTERNAL_ERROR;
return -1;
}
if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
+ if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
+ wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
+ "algorithm");
+ *err = GNUTLS_A_INSUFFICIENT_SECURITY;
+ }
+ if (status & GNUTLS_CERT_NOT_ACTIVATED) {
+ wpa_printf(MSG_INFO, "TLS: Certificate not yet "
+ "activated");
+ *err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ }
+ if (status & GNUTLS_CERT_EXPIRED) {
+ wpa_printf(MSG_INFO, "TLS: Certificate expired");
+ *err = GNUTLS_A_CERTIFICATE_EXPIRED;
+ }
return -1;
}
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
"known issuer");
+ *err = GNUTLS_A_UNKNOWN_CA;
return -1;
}
if (status & GNUTLS_CERT_REVOKED) {
wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
+ *err = GNUTLS_A_CERTIFICATE_REVOKED;
return -1;
}
@@ -882,6 +900,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn)
if (certs == NULL) {
wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
"received");
+ *err = GNUTLS_A_UNKNOWN_CA;
return -1;
}
@@ -891,6 +910,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn)
if (gnutls_x509_crt_init(&cert) < 0) {
wpa_printf(MSG_INFO, "TLS: Certificate initialization "
"failed");
+ *err = GNUTLS_A_BAD_CERTIFICATE;
return -1;
}
@@ -899,6 +919,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn)
wpa_printf(MSG_INFO, "TLS: Could not parse peer "
"certificate %d/%d", i + 1, num_certs);
gnutls_x509_crt_deinit(cert);
+ *err = GNUTLS_A_BAD_CERTIFICATE;
return -1;
}
@@ -924,6 +945,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn)
"not valid at this time",
i + 1, num_certs);
gnutls_x509_crt_deinit(cert);
+ *err = GNUTLS_A_CERTIFICATE_EXPIRED;
return -1;
}
@@ -985,12 +1007,15 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
}
} else {
size_t size;
+ gnutls_alert_description_t err;
- if (conn->verify_peer && tls_connection_verify_peer(conn)) {
+ if (conn->verify_peer &&
+ tls_connection_verify_peer(conn, &err)) {
wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
"failed validation");
conn->failed++;
- return NULL;
+ gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err);
+ goto out;
}
#ifdef CONFIG_GNUTLS_EXTRA
@@ -1027,6 +1052,7 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
}
}
+out:
out_data = conn->push_buf;
*out_len = conn->push_buf_len;
conn->push_buf = NULL;