]> git.sesse.net Git - vlc/commitdiff
- Check x509 certificates start and end date (*ahem*)
authorRémi Denis-Courmont <rem@videolan.org>
Thu, 7 Sep 2006 19:09:27 +0000 (19:09 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Thu, 7 Sep 2006 19:09:27 +0000 (19:09 +0000)
- Some cleanup

configure.ac
modules/misc/gnutls.c

index 9896ea0186d955b87cdc08aefc7b1ff10d58fd90..1a75b65ca86b6db10784c5f0a28a81ccaa5811cb 100644 (file)
@@ -9,7 +9,7 @@ VERSION_EXTRA="svn"
 CONFIGURE_LINE="$0 $*"
 CODENAME="Janus"
 
-AC_PREREQ(2.50)
+AC_PREREQ(2.59c)
 AC_CONFIG_SRCDIR(src/libvlc.c)
 AC_CONFIG_AUX_DIR(autotools)
 AC_CANONICAL_SYSTEM
@@ -37,7 +37,7 @@ VLC_SAVE_FLAGS
 dnl
 dnl Check for tools
 dnl
-AC_PROG_CC
+AC_PROG_CC_C99
 AM_PROG_CC_C_O
 AC_PROG_CPP
 AC_PROG_CXX
index 257c7876afe3de41836581ffec445f4358ce2870..b4234e676b4b2cc7c249053668635eeda183f58a 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
-/*
- * TODO:
- * - fix FIXMEs
- */
-
-
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 #include <stdlib.h>
 #include <errno.h>
+#include <time.h>
 #include <vlc/vlc.h>
 
 #include <sys/types.h>
@@ -305,58 +300,127 @@ gnutls_VerifyHostname( vlc_object_t *p_this, gnutls_session session,
     return 0;
 }
 
+
+typedef struct
+{
+    int flag;
+    const char *msg;
+} error_msg_t;
+
+static const error_msg_t cert_errors[] =
+{
+    { GNUTLS_CERT_INVALID,
+        "Certificate could not be verified" },
+    { GNUTLS_CERT_REVOKED,
+        "Certificate was revoked" },
+    { GNUTLS_CERT_SIGNER_NOT_FOUND,
+        "Certificate's signer was not found" },
+    { GNUTLS_CERT_SIGNER_NOT_CA,
+        "Certificate's signer is not a CA" },
+    { GNUTLS_CERT_INSECURE_ALGORITHM,
+        "Insecure certificate signature algorithm" },
+    { 0, NULL }
+};
+
+
 static int
-gnutls_HandshakeAndValidate( tls_session_t *p_session )
+gnutls_HandshakeAndValidate( tls_session_t *session )
 {
-    int val;
+    int val = gnutls_ContinueHandshake( session );
+    if( val )
+        return val;
 
-    val = gnutls_ContinueHandshake( p_session );
-    if( val == 0 )
-    {
-        unsigned status;
-        tls_session_sys_t *p_sys;
+    tls_session_sys_t *p_sys = (tls_session_sys_t *)(session->p_sys);
 
-        p_sys = (tls_session_sys_t *)(p_session->p_sys);
-        /* certificates chain verification */
-        val = gnutls_certificate_verify_peers2( p_sys->session, &status );
+    /* certificates chain verification */
+    unsigned status;
+    val = gnutls_certificate_verify_peers2( p_sys->session, &status );
 
-        if( val )
+    if( val )
+    {
+        msg_Err( session, "Certificate verification failed: %s",
+                 gnutls_strerror( val ) );
+        goto error;
+    }
+
+    if( status )
+    {
+        msg_Err( session, "TLS session: access denied" );
+        for( const error_msg_t *e = cert_errors; e->flag; e++ )
         {
-            msg_Err( p_session, "TLS certificate verification failed: %s",
-                     gnutls_strerror( val ) );
-            p_session->pf_close( p_session );
-            return -1;
+            if( status & e->flag )
+            {
+                msg_Err( session, e->msg );
+                status &= ~e->flag;
+            }
         }
 
         if( status )
-        {
-            msg_Err( p_session, "TLS session: access denied" );
-            if( status & GNUTLS_CERT_INVALID )
-                msg_Warn( p_session, "certificate could not be verified" );
-            if( status & GNUTLS_CERT_REVOKED )
-                msg_Warn( p_session, "certificate was revoked" );
-            if( status & GNUTLS_CERT_SIGNER_NOT_FOUND )
-                msg_Warn( p_session, "certificate's signer was not found" );
-            if( status & GNUTLS_CERT_SIGNER_NOT_CA )
-                msg_Warn( p_session, "certificate's signer is not a CA" );
-            if( status & GNUTLS_CERT_INSECURE_ALGORITHM )
-                msg_Warn( p_session, "insecure certificate signature algorithm" );
-            p_session->pf_close( p_session );
-            return -1;
-        }
+            msg_Err( session,
+                     "unknown certificate error (you found a bug in VLC)" );
+
+        goto error;
+    }
 
-        msg_Dbg( p_session, "TLS certificate verified" );
-        if( ( p_sys->psz_hostname != NULL )
-         && gnutls_VerifyHostname( (vlc_object_t *)p_session, p_sys->session,
-                                   p_sys->psz_hostname ) )
+    /* certificate (host)name verification */
+    const gnutls_datum *data = gnutls_certificate_get_peers( p_sys->session,
+                                                             &(size_t){ 0 } );
+    if( data == NULL )
+    {
+        msg_Err( session, "Peer certificate not available" );
+        goto error;
+    }
+
+    gnutls_x509_crt cert;
+    val = gnutls_x509_crt_init( &cert );
+    if( val )
+    {
+        msg_Err( session, "x509 fatal error: %s", gnutls_strerror( val ) );
+        goto error;
+    }
+
+    val = gnutls_x509_crt_import( cert, data, GNUTLS_X509_FMT_DER );
+    if( val )
+    {
+        msg_Err( session, "Certificate import error: %s",
+                 gnutls_strerror( val ) );
+        gnutls_x509_crt_deinit( cert );
+        goto crt_error;
+    }
+
+    if( p_sys->psz_hostname != NULL )
+    {
+        if ( !gnutls_x509_crt_check_hostname( cert, p_sys->psz_hostname ) )
         {
-            p_session->pf_close( p_session );
-            return -1;
+            msg_Err( session, "Certificate does not match \"%s\"",
+                     p_sys->psz_hostname );
+            goto crt_error;
         }
-        return 0;
+    }
+    else
+        msg_Warn( session, "Certificate and hostname were not verified" );
+
+    if( gnutls_x509_crt_get_expiration_time( cert ) < time( NULL ) )
+    {
+        msg_Err( session, "Certificate expired" );
+        goto crt_error;
     }
 
-    return val;
+    if( gnutls_x509_crt_get_activation_time( cert ) > time ( NULL ) )
+    {
+        msg_Err( session, "Certificate not yet valid" );
+        goto crt_error;
+    }
+
+    gnutls_x509_crt_deinit( cert );
+    msg_Dbg( session, "TLS/x509 certificate verified" );
+    return 0;
+
+crt_error:
+    gnutls_x509_crt_deinit( cert );
+error:
+    session->pf_close( session );
+    return -1;
 }
 
 /**
@@ -1011,7 +1075,6 @@ gnutls_ServerCreate( tls_t *p_tls, const char *psz_cert_path,
     /* No certificate validation by default */
     p_sys->pf_handshake2 = gnutls_ContinueHandshake;
 
-    /* FIXME: check for errors */
     vlc_mutex_init( p_server, &p_sys->cache_lock );
 
     /* Sets server's credentials */