GnuTLS: Verify that server certificate EKU is valid for a server
The server certificate will be rejected if it includes any EKU and none of the listed EKUs is either TLS Web Server Authentication or ANY. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
d4d1f5cb33
commit
0e1bb94b91
1 changed files with 75 additions and 1 deletions
|
@ -741,6 +741,42 @@ static void gnutls_tls_fail_event(struct tls_connection *conn,
|
|||
}
|
||||
|
||||
|
||||
#if GNUTLS_VERSION_NUMBER < 0x030300
|
||||
static int server_eku_purpose(gnutls_x509_crt_t cert)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
char oid[128];
|
||||
size_t oid_size = sizeof(oid);
|
||||
int res;
|
||||
|
||||
res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
|
||||
&oid_size, NULL);
|
||||
if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
||||
if (i == 0) {
|
||||
/* No EKU - assume any use allowed */
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
|
||||
if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
|
||||
os_strcmp(oid, GNUTLS_KP_ANY) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* < 3.3.0 */
|
||||
|
||||
|
||||
static int tls_connection_verify_peer(gnutls_session_t session)
|
||||
{
|
||||
struct tls_connection *conn;
|
||||
|
@ -749,6 +785,7 @@ static int tls_connection_verify_peer(gnutls_session_t session)
|
|||
const gnutls_datum_t *certs;
|
||||
gnutls_x509_crt_t cert;
|
||||
gnutls_alert_description_t err;
|
||||
int res;
|
||||
|
||||
conn = gnutls_session_get_ptr(session);
|
||||
if (!conn->verify_peer) {
|
||||
|
@ -759,7 +796,24 @@ static int tls_connection_verify_peer(gnutls_session_t session)
|
|||
|
||||
wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
|
||||
|
||||
if (gnutls_certificate_verify_peers2(session, &status) < 0) {
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030300
|
||||
{
|
||||
gnutls_typed_vdata_st data[1];
|
||||
unsigned int elements = 0;
|
||||
|
||||
os_memset(data, 0, sizeof(data));
|
||||
if (!conn->global->server) {
|
||||
data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
|
||||
data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
|
||||
elements++;
|
||||
}
|
||||
res = gnutls_certificate_verify_peers(session, data, 1,
|
||||
&status);
|
||||
}
|
||||
#else /* < 3.3.0 */
|
||||
res = gnutls_certificate_verify_peers2(session, &status);
|
||||
#endif
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
|
||||
"certificate chain");
|
||||
err = GNUTLS_A_INTERNAL_ERROR;
|
||||
|
@ -904,6 +958,26 @@ static int tls_connection_verify_peer(gnutls_session_t session)
|
|||
/* TODO: validate altsubject_match.
|
||||
* For now, any such configuration is rejected in
|
||||
* tls_connection_set_params() */
|
||||
|
||||
#if GNUTLS_VERSION_NUMBER < 0x030300
|
||||
/*
|
||||
* gnutls_certificate_verify_peers() not available, so
|
||||
* need to check EKU separately.
|
||||
*/
|
||||
if (!conn->global->server &&
|
||||
!server_eku_purpose(cert)) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"GnuTLS: No server EKU");
|
||||
gnutls_tls_fail_event(
|
||||
conn, &certs[i], i, buf,
|
||||
"No server EKU",
|
||||
TLS_FAIL_BAD_CERTIFICATE);
|
||||
err = GNUTLS_A_BAD_CERTIFICATE;
|
||||
gnutls_x509_crt_deinit(cert);
|
||||
os_free(buf);
|
||||
goto out;
|
||||
}
|
||||
#endif /* < 3.3.0 */
|
||||
}
|
||||
|
||||
if (!conn->disable_time_checks &&
|
||||
|
|
Loading…
Reference in a new issue