mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
Fix checking of key usage/purpose data
If key usage or purpose data is not present in the cert, the RFC recommends that access be allowed. Also fix checking of key usage to include requirements for client/server certs, and fix key purpose checking to treat data as a list of bits
This commit is contained in:
parent
3ea043254c
commit
f53cc36fe8
@ -111,6 +111,7 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
size_t size;
|
size_t size;
|
||||||
unsigned int usage;
|
unsigned int usage;
|
||||||
|
bool allowClient = false, allowServer = false;
|
||||||
|
|
||||||
VIR_DEBUG("isServer %d isCA %d certFile %s",
|
VIR_DEBUG("isServer %d isCA %d certFile %s",
|
||||||
isServer, isCA, certFile);
|
isServer, isCA, certFile);
|
||||||
@ -193,24 +194,34 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
|
|
||||||
VIR_DEBUG("Cert %s key usage status %d usage %d", certFile, status, usage);
|
VIR_DEBUG("Cert %s key usage status %d usage %d", certFile, status, usage);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
||||||
|
usage = isCA ? GNUTLS_KEY_KEY_CERT_SIGN :
|
||||||
|
GNUTLS_KEY_DIGITAL_SIGNATURE|GNUTLS_KEY_KEY_ENCIPHERMENT;
|
||||||
|
} else {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("Unable to query certificate %s key usage %s"),
|
_("Unable to query certificate %s key usage %s"),
|
||||||
certFile, gnutls_strerror(status));
|
certFile, gnutls_strerror(status));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (usage & GNUTLS_KEY_KEY_CERT_SIGN) {
|
if (isCA) {
|
||||||
if (!isCA) {
|
if (!(usage & GNUTLS_KEY_KEY_CERT_SIGN)) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR, isServer ?
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("Certificate %s usage is for certificate signing, but wanted a server certificate") :
|
_("Certificate %s usage does not permit certificate signing"),
|
||||||
_("Certificate %s usage is for certificate signing, but wanted a client certificate"),
|
|
||||||
certFile);
|
certFile);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isCA) {
|
if (!(usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("Certificate %s usage is for not certificate signing"),
|
_("Certificate %s usage does not permit digital signature"),
|
||||||
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!(usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
|
||||||
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("Certificate %s usage does not permit key encipherment"),
|
||||||
certFile);
|
certFile);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -221,7 +232,11 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
status = gnutls_x509_crt_get_key_purpose_oid(cert, i, buffer, &size, NULL);
|
status = gnutls_x509_crt_get_key_purpose_oid(cert, i, buffer, &size, NULL);
|
||||||
|
|
||||||
if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
||||||
VIR_DEBUG("No key purpose data available, skipping checks");
|
VIR_DEBUG("No key purpose data available at slot %d", i);
|
||||||
|
|
||||||
|
/* If there is no data at all, then we must allow client/server to pass */
|
||||||
|
if (i == 0)
|
||||||
|
allowServer = allowClient = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (status != GNUTLS_E_SHORT_MEMORY_BUFFER) {
|
if (status != GNUTLS_E_SHORT_MEMORY_BUFFER) {
|
||||||
@ -246,34 +261,31 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
|
|
||||||
VIR_DEBUG("Key purpose %d %s", status, buffer);
|
VIR_DEBUG("Key purpose %d %s", status, buffer);
|
||||||
if (STREQ(buffer, GNUTLS_KP_TLS_WWW_SERVER)) {
|
if (STREQ(buffer, GNUTLS_KP_TLS_WWW_SERVER)) {
|
||||||
if (isCA || !isServer) {
|
allowServer = true;
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR, isCA ?
|
|
||||||
_("Certificate %s purpose is TLS server, but wanted a CA certificate") :
|
|
||||||
_("Certificate %s client purpose is TLS server, but wanted a TLS client certificate"),
|
|
||||||
certFile);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
} else if (STREQ(buffer, GNUTLS_KP_TLS_WWW_CLIENT)) {
|
} else if (STREQ(buffer, GNUTLS_KP_TLS_WWW_CLIENT)) {
|
||||||
if (isCA || isServer) {
|
allowClient = true;
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR, isCA ?
|
|
||||||
_("Certificate %s purpose is TLS client, but wanted a CA certificate") :
|
|
||||||
_("Certificate %s server purpose is TLS client, but wanted a TLS server certificate"),
|
|
||||||
certFile);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
} else if (STRNEQ(buffer, GNUTLS_KP_ANY)) {
|
} else if (STRNEQ(buffer, GNUTLS_KP_ANY)) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR, (isCA ?
|
allowServer = allowClient = true;
|
||||||
_("Certificate %s purpose is wrong, wanted a CA certificate") :
|
|
||||||
(isServer ?
|
|
||||||
_("Certificate %s purpose is wrong, wanted a TLS server certificate") :
|
|
||||||
_("Certificate %s purpose is wrong, wanted a TLS client certificate"))),
|
|
||||||
certFile);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FREE(buffer);
|
VIR_FREE(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isCA) { /* No purpose checks required for CA certs */
|
||||||
|
if (isServer && !allowServer) {
|
||||||
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("Certificate %s purpose does not allow use for with a TLS server"),
|
||||||
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!isServer && !allowClient) {
|
||||||
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("Certificate %s purpose does not allow use for with a TLS client"),
|
||||||
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user