mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Honour key usage/purpose criticality flag
If a key purpose or usage field is marked as non-critical in the certificate, then a data mismatch is not (ordinarily) a cause for rejecting the connection * src/rpc/virnettlscontext.c: Honour key usage/purpose criticality
This commit is contained in:
parent
f53cc36fe8
commit
14800d49cb
@ -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;
|
||||||
|
unsigned int critical;
|
||||||
bool allowClient = false, allowServer = false;
|
bool allowClient = false, allowServer = false;
|
||||||
|
|
||||||
VIR_DEBUG("isServer %d isCA %d certFile %s",
|
VIR_DEBUG("isServer %d isCA %d certFile %s",
|
||||||
@ -190,9 +191,9 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = gnutls_x509_crt_get_key_usage(cert, &usage, NULL);
|
status = gnutls_x509_crt_get_key_usage(cert, &usage, &critical);
|
||||||
|
|
||||||
VIR_DEBUG("Cert %s key usage status %d usage %d", certFile, status, usage);
|
VIR_DEBUG("Cert %s key usage status %d usage %d critical %u", certFile, status, usage, critical);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
||||||
usage = isCA ? GNUTLS_KEY_KEY_CERT_SIGN :
|
usage = isCA ? GNUTLS_KEY_KEY_CERT_SIGN :
|
||||||
@ -207,28 +208,45 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
|
|
||||||
if (isCA) {
|
if (isCA) {
|
||||||
if (!(usage & GNUTLS_KEY_KEY_CERT_SIGN)) {
|
if (!(usage & GNUTLS_KEY_KEY_CERT_SIGN)) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
if (critical) {
|
||||||
_("Certificate %s usage does not permit certificate signing"),
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
certFile);
|
_("Certificate %s usage does not permit certificate signing"),
|
||||||
goto cleanup;
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
VIR_WARN("Certificate %s usage does not permit certificate signing",
|
||||||
|
certFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!(usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
|
if (!(usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
if (critical) {
|
||||||
_("Certificate %s usage does not permit digital signature"),
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
certFile);
|
_("Certificate %s usage does not permit digital signature"),
|
||||||
goto cleanup;
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
VIR_WARN("Certificate %s usage does not permit digital signature",
|
||||||
|
certFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!(usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
|
if (!(usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
if (critical) {
|
||||||
_("Certificate %s usage does not permit key encipherment"),
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
certFile);
|
_("Certificate %s usage does not permit key encipherment"),
|
||||||
goto cleanup;
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
VIR_WARN("Certificate %s usage does not permit key encipherment",
|
||||||
|
certFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
critical = 0;
|
||||||
for (i = 0 ; ; i++) {
|
for (i = 0 ; ; i++) {
|
||||||
size = 0;
|
size = 0;
|
||||||
|
unsigned int purposeCritical;
|
||||||
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) {
|
||||||
@ -251,15 +269,17 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, &purposeCritical);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("Unable to query certificate %s key purpose %s"),
|
_("Unable to query certificate %s key purpose %s"),
|
||||||
certFile, gnutls_strerror(status));
|
certFile, gnutls_strerror(status));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (purposeCritical)
|
||||||
|
critical = true;
|
||||||
|
|
||||||
VIR_DEBUG("Key purpose %d %s", status, buffer);
|
VIR_DEBUG("Key purpose %d %s critical %u", status, buffer, purposeCritical);
|
||||||
if (STREQ(buffer, GNUTLS_KP_TLS_WWW_SERVER)) {
|
if (STREQ(buffer, GNUTLS_KP_TLS_WWW_SERVER)) {
|
||||||
allowServer = true;
|
allowServer = true;
|
||||||
} else if (STREQ(buffer, GNUTLS_KP_TLS_WWW_CLIENT)) {
|
} else if (STREQ(buffer, GNUTLS_KP_TLS_WWW_CLIENT)) {
|
||||||
@ -273,16 +293,26 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
|
|||||||
|
|
||||||
if (!isCA) { /* No purpose checks required for CA certs */
|
if (!isCA) { /* No purpose checks required for CA certs */
|
||||||
if (isServer && !allowServer) {
|
if (isServer && !allowServer) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
if (critical) {
|
||||||
_("Certificate %s purpose does not allow use for with a TLS server"),
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
certFile);
|
_("Certificate %s purpose does not allow use for with a TLS server"),
|
||||||
goto cleanup;
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
VIR_WARN("Certificate %s purpose does not allow use for with a TLS server",
|
||||||
|
certFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!isServer && !allowClient) {
|
if (!isServer && !allowClient) {
|
||||||
virNetError(VIR_ERR_SYSTEM_ERROR,
|
if (critical) {
|
||||||
_("Certificate %s purpose does not allow use for with a TLS client"),
|
virNetError(VIR_ERR_SYSTEM_ERROR,
|
||||||
certFile);
|
_("Certificate %s purpose does not allow use for with a TLS client"),
|
||||||
goto cleanup;
|
certFile);
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
VIR_WARN("Certificate %s purpose does not allow use for with a TLS client",
|
||||||
|
certFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user