[vlc-commits] gnutls: support SSH-style first use certificate authentication

Rémi Denis-Courmont git at videolan.org
Sun Sep 30 15:45:16 CEST 2012


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Sep 30 16:32:08 2012 +0300| [dd782427396b32a74aaa5e2d27c3cce1bbf3f1bd] | committer: Rémi Denis-Courmont

gnutls: support SSH-style first use certificate authentication

If a certificate does not validate, the user will be given the option
to accept it manually. GnuTLS will then store the certificate in its
known hosts database.

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

 modules/misc/gnutls.c |   43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
index 56124cb..7ca5063 100644
--- a/modules/misc/gnutls.c
+++ b/modules/misc/gnutls.c
@@ -247,9 +247,29 @@ static int gnutls_ContinueHandshake (vlc_tls_t *session, const char *host,
  * @return 0 on success, -1 on failure.
  */
 static int gnutls_CertSearch (vlc_tls_t *obj, const char *host,
+                              const char *service,
                               const gnutls_datum_t *restrict datum)
 {
     assert (host != NULL);
+    /* Look up mismatching certificate in store */
+    int val = gnutls_verify_stored_pubkey (NULL, NULL, host, service,
+                                           GNUTLS_CRT_X509, datum, 0);
+    switch (val)
+    {
+        case 0:
+            msg_Dbg (obj, "certificate key match for %s", host);
+            return 0;
+        case GNUTLS_E_NO_CERTIFICATE_FOUND:
+            msg_Dbg (obj, "no known certificates for %s", host);
+            break;
+        case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
+            msg_Dbg (obj, "certificate keys mismatch for %s", host);
+            break;
+        default:
+            msg_Err (obj, "certificate key match error for %s: %s", host,
+                     gnutls_strerror (val));
+            return -1;
+    }
 
     if (dialog_Question (obj, N_("Insecure site"),
          N_("You attempted to reach %s, but security certificate presented by "
@@ -273,14 +293,25 @@ static int gnutls_CertSearch (vlc_tls_t *obj, const char *host,
     }
     gnutls_x509_crt_deinit (cert);
 
-    int val = dialog_Question (obj, N_("Insecure site"),
+    val = dialog_Question (obj, N_("Insecure site"),
          N_("This is the certificate presented by %s:\n%s\n\n"
             "If in doubt, abort now.\n"),
-                           N_("Abort"), N_("Proceed anyway"), NULL,
-                           host, desc.data);
+                           N_("Abort"), N_("Accept 24 hours"),
+                           N_("Accept permanently"), host, desc.data);
     gnutls_free (desc.data);
 
-    return (val == 2) ? 0 : -1;
+    time_t expiry = 0;
+    switch (val)
+    {
+        case 2:
+            time (&expiry);
+            expiry += 24 * 60 * 60;
+        case 3:
+            gnutls_store_pubkey (NULL, NULL, host, service, GNUTLS_CRT_X509,
+                                 datum, expiry, 0);
+            return 0;
+    }
+    return -1;
 }
 
 
@@ -361,7 +392,7 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
 
     if (val || host == NULL)
         return val;
-    if (status && gnutls_CertSearch (session, host, data))
+    if (status && gnutls_CertSearch (session, host, service, data))
         return -1;
 
     gnutls_x509_crt_t cert;
@@ -384,7 +415,7 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
     if (val)
     {
         msg_Err (session, "Certificate does not match \"%s\"", host);
-        val = gnutls_CertSearch (session, host, data);
+        val = gnutls_CertSearch (session, host, service, data);
     }
 error:
     gnutls_x509_crt_init (&cert);



More information about the vlc-commits mailing list