[vlc-commits] gnutls: simplify certificate verification

Rémi Denis-Courmont git at videolan.org
Fri Aug 22 22:44:40 CEST 2014


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Fri Aug 22 23:32:48 2014 +0300| [f283e2537366f47ba8ccea582763ea086290164f] | committer: Rémi Denis-Courmont

gnutls: simplify certificate verification

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f283e2537366f47ba8ccea582763ea086290164f
---

 modules/misc/gnutls.c |   75 +++++++++++++------------------------------------
 1 file changed, 20 insertions(+), 55 deletions(-)

diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
index c67c5f5..5a1bf3b 100644
--- a/modules/misc/gnutls.c
+++ b/modules/misc/gnutls.c
@@ -333,22 +333,6 @@ static int gnutls_CertSearch (vlc_tls_t *obj, const char *host,
 }
 
 
-static struct
-{
-    unsigned flag;
-    const char msg[29];
-} cert_errs[] =
-{
-    { GNUTLS_CERT_INVALID,            "Certificate not verified"     },
-    { GNUTLS_CERT_REVOKED,            "Certificate revoked"          },
-    { GNUTLS_CERT_SIGNER_NOT_FOUND,   "Signer not found"             },
-    { GNUTLS_CERT_SIGNER_NOT_CA,      "Signer not a CA"              },
-    { GNUTLS_CERT_INSECURE_ALGORITHM, "Signature algorithm insecure" },
-    { GNUTLS_CERT_NOT_ACTIVATED,      "Certificate not activated"    },
-    { GNUTLS_CERT_EXPIRED,            "Certificate expired"          },
-};
-
-
 static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
                                         const char *service)
 {
@@ -361,29 +345,37 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
     /* certificates chain verification */
     unsigned status;
 
-    val = gnutls_certificate_verify_peers2 (sys->session, &status);
+    val = gnutls_certificate_verify_peers3 (sys->session, host, &status);
     if (val)
     {
         msg_Err (session, "Certificate verification error: %s",
                  gnutls_strerror (val));
         return -1;
     }
-    if (status)
+
+    if (status == 0)
+        return 0; /* good certificate */
+
+    gnutls_datum_t datum;
+
+    if (gnutls_certificate_verification_status_print(status,
+                   gnutls_certificate_type_get (sys->session), &datum, 0) == 0)
     {
-        msg_Err (session, "Certificate verification failure (0x%04X)", status);
-        for (size_t i = 0; i < sizeof (cert_errs) / sizeof (cert_errs[0]); i++)
-            if (status & cert_errs[i].flag)
-                msg_Err (session, " * %s", cert_errs[i].msg);
-        if (status & ~(GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND))
-            return -1;
+        msg_Err (session, "Certificate verification failure: %s", datum.data);
+        gnutls_free (datum.data);
     }
 
-    if (host == NULL)
-        return status ? -1 : 0;
+    status &= ~GNUTLS_CERT_INVALID; /* always set / catch-all error */
+    status &= ~GNUTLS_CERT_SIGNER_NOT_FOUND; /* unknown CA */
+    status &= ~GNUTLS_CERT_UNEXPECTED_OWNER; /* mismatched hostname */
+
+    if (status != 0 || host == NULL)
+        return -1; /* really bad certificate */
 
-    /* certificate (host)name verification */
+    /* manual verification */
     const gnutls_datum_t *data;
     unsigned count;
+
     data = gnutls_certificate_get_peers (sys->session, &count);
     if (data == NULL || count == 0)
     {
@@ -392,34 +384,7 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
     }
     msg_Dbg (session, "%u certificate(s) in the list", count);
 
-    if (status && gnutls_CertSearch (session, host, service, data))
-        return -1;
-
-    gnutls_x509_crt_t cert;
-    val = gnutls_x509_crt_init (&cert);
-    if (val)
-    {
-        msg_Err (session, "X.509 fatal error: %s", gnutls_strerror (val));
-        return -1;
-    }
-
-    val = gnutls_x509_crt_import (cert, data, GNUTLS_X509_FMT_DER);
-    if (val)
-    {
-        msg_Err (session, "Certificate import error: %s",
-                 gnutls_strerror (val));
-        goto error;
-    }
-
-    val = !gnutls_x509_crt_check_hostname (cert, host);
-    if (val)
-    {
-        msg_Err (session, "Certificate does not match \"%s\"", host);
-        val = gnutls_CertSearch (session, host, service, data);
-    }
-error:
-    gnutls_x509_crt_deinit (cert);
-    return val;
+    return gnutls_CertSearch (session, host, service, data);
 }
 
 static int



More information about the vlc-commits mailing list