[libvirt] [PATCH 2/3] Fix checking of key usage/purpose data
Daniel Veillard
veillard at redhat.com
Wed Jul 20 13:39:53 UTC 2011
On Wed, Jul 20, 2011 at 02:12:46PM +0100, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
>
> 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
> ---
> src/rpc/virnettlscontext.c | 78 +++++++++++++++++++++++++------------------
> 1 files changed, 45 insertions(+), 33 deletions(-)
>
> diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
> index 402029f..1ee5ab2 100644
> --- a/src/rpc/virnettlscontext.c
> +++ b/src/rpc/virnettlscontext.c
> @@ -111,6 +111,7 @@ static gnutls_x509_crt_t virNetTLSContextSanityCheckCert(bool isServer,
> char *buffer = NULL;
> size_t size;
> unsigned int usage;
> + bool allowClient = false, allowServer = false;
>
> VIR_DEBUG("isServer %d isCA %d certFile %s",
> 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);
> if (status < 0) {
> - virNetError(VIR_ERR_SYSTEM_ERROR,
> - _("Unable to query certificate %s key usage %s"),
> - certFile, gnutls_strerror(status));
> - goto cleanup;
> + 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,
> + _("Unable to query certificate %s key usage %s"),
> + certFile, gnutls_strerror(status));
> + goto cleanup;
> + }
> }
>
> - if (usage & GNUTLS_KEY_KEY_CERT_SIGN) {
> - if (!isCA) {
> - virNetError(VIR_ERR_SYSTEM_ERROR, isServer ?
> - _("Certificate %s usage is for certificate signing, but wanted a server certificate") :
> - _("Certificate %s usage is for certificate signing, but wanted a client certificate"),
> + if (isCA) {
> + if (!(usage & GNUTLS_KEY_KEY_CERT_SIGN)) {
> + virNetError(VIR_ERR_SYSTEM_ERROR,
> + _("Certificate %s usage does not permit certificate signing"),
> certFile);
> goto cleanup;
> }
> } else {
> - if (isCA) {
> + if (!(usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
> + virNetError(VIR_ERR_SYSTEM_ERROR,
> + _("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 is for not certificate signing"),
> + _("Certificate %s usage does not permit key encipherment"),
> certFile);
> 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);
>
> 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;
> }
> 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);
> if (STREQ(buffer, GNUTLS_KP_TLS_WWW_SERVER)) {
> - if (isCA || !isServer) {
> - 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;
> - }
> + allowServer = true;
> } else if (STREQ(buffer, GNUTLS_KP_TLS_WWW_CLIENT)) {
> - if (isCA || isServer) {
> - 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;
> - }
> + allowClient = true;
> } else if (STRNEQ(buffer, GNUTLS_KP_ANY)) {
> - virNetError(VIR_ERR_SYSTEM_ERROR, (isCA ?
> - _("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;
> + allowServer = allowClient = true;
> }
>
> 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;
Okay, not a trivial change but relax the contraints,
ACK,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list