From 93c5ad7cbc57e0d677bb26a3989530eba40fa6ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Wed, 25 Jan 2017 17:06:11 -0500
Subject: [PATCH] crypto: make Certificate::isCA() more restrictive

---
 include/opendht/crypto.h |  3 ++-
 src/crypto.cpp           | 15 ++++++++++++++-
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index 4f66b764..7d9c8f2f 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -373,7 +373,8 @@ struct OPENDHT_PUBLIC Certificate {
     std::chrono::system_clock::time_point getExpiration() const;
 
     /**
-     * Returns true if the certificate is marked as a Certificate Authority.
+     * Returns true if the certificate is marked as a Certificate Authority
+     * and has necessary key usage flags to sign certificates.
      */
     bool isCA() const;
 
diff --git a/src/crypto.cpp b/src/crypto.cpp
index d7a30c63..80c1dc80 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -722,7 +722,20 @@ bool
 Certificate::isCA() const
 {
     unsigned critical;
-    return gnutls_x509_crt_get_ca_status(cert, &critical) > 0;
+    bool ca_flag = gnutls_x509_crt_get_ca_status(cert, &critical) > 0;
+    if (ca_flag) {
+        unsigned usage;
+        auto ret = gnutls_x509_crt_get_key_usage(cert, &usage, &critical);
+        /* Conforming CAs MUST include this extension in certificates that
+           contain public keys that are used to validate digital signatures on
+           other public key certificates or CRLs. */
+        if (ret < 0)
+            return false;
+        if (not critical)
+            return true;
+        return usage & GNUTLS_KEY_KEY_CERT_SIGN;
+    }
+    return false;
 }
 
 std::string
-- 
GitLab