]> git.sesse.net Git - vlc/commitdiff
Fix TLS session cleanup
authorRémi Denis-Courmont <rem@videolan.org>
Sat, 22 Sep 2007 12:37:05 +0000 (12:37 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Sat, 22 Sep 2007 12:37:05 +0000 (12:37 +0000)
include/vlc_tls.h
modules/misc/gnutls.c
src/libvlc.sym
src/network/tls.c

index 4fcb5d91d45f7c3eed30fd4fb44ab9ab05386ac8..ea78bb9cb2a764811ef204c7a190dd2a0e272519 100644 (file)
@@ -42,7 +42,8 @@ struct tls_server_t
     int (*pf_add_CA) ( tls_server_t *, const char * );
     int (*pf_add_CRL) ( tls_server_t *, const char * );
 
-    tls_session_t * (*pf_session_prepare) ( tls_server_t * );
+    tls_session_t * (*pf_open)  ( tls_server_t * );
+    void            (*pf_close) ( tls_server_t *, tls_session_t * );
 };
 
 typedef struct tls_session_sys_t tls_session_sys_t;
@@ -55,53 +56,24 @@ struct tls_session_t
     tls_session_sys_t *p_sys;
 
     struct virtual_socket_t sock;
-    int (*pf_handshake) ( tls_session_t *, int );
-    int (*pf_handshake2) ( tls_session_t * );
-    void (*pf_close) ( tls_session_t * );
+    void (*pf_set_fd) ( tls_session_t *, int );
+    int  (*pf_handshake) ( tls_session_t * );
 };
 
 
-/*****************************************************************************
- * tls_ServerCreate:
- *****************************************************************************
- * Allocates a whole server's TLS credentials.
- * Returns NULL on error.
- *****************************************************************************/
-VLC_EXPORT( tls_server_t *, tls_ServerCreate, ( vlc_object_t *, const char *, const char * ) );
-
-/*****************************************************************************
- * tls_ServerAddCA:
- *****************************************************************************
- * Adds one or more certificate authorities.
- * Returns -1 on error, 0 on success.
- *****************************************************************************/
-# define tls_ServerAddCA( a, b ) (((tls_server_t *)a)->pf_add_CA (a, b))
-
-
-/*****************************************************************************
- * tls_ServerAddCRL:
- *****************************************************************************
- * Adds a certificates revocation list to be sent to TLS clients.
- * Returns -1 on error, 0 on success.
- *****************************************************************************/
-# define tls_ServerAddCRL( a, b ) (((tls_server_t *)a)->pf_add_CRL (a, b))
-
-
-VLC_EXPORT( void, tls_ServerDelete, ( tls_server_t * ) );
+tls_server_t *tls_ServerCreate (vlc_object_t *, const char *, const char *);
+void tls_ServerDelete (tls_server_t *);
+int tls_ServerAddCA (tls_server_t *srv, const char *path);
+int tls_ServerAddCRL (tls_server_t *srv, const char *path);
 
-
-# define tls_ServerSessionPrepare( a ) (((tls_server_t *)a)->pf_session_prepare (a))
-# define tls_ServerSessionHandshake( a, b ) (((tls_session_t *)a)->pf_handshake (a, b))
-# define tls_ServerSessionClose( a ) (((tls_session_t *)a)->pf_close (a))
+tls_session_t *tls_ServerSessionPrepare (tls_server_t *);
+int tls_ServerSessionHandshake (tls_session_t *, int fd);
+int tls_SessionContinueHandshake (tls_session_t *);
+void tls_ServerSessionClose (tls_session_t *);
 
 VLC_EXPORT( tls_session_t *, tls_ClientCreate, ( vlc_object_t *, int, const char * ) );
 VLC_EXPORT( void, tls_ClientDelete, ( tls_session_t * ) );
 
-# define tls_ClientSessionHandshake( a, b ) (((tls_session_t *)a)->pf_handshake (a, b))
-
-# define tls_SessionContinueHandshake( a ) (((tls_session_t *)a)->pf_handshake2 (a))
-
-
 /* NOTE: It is assumed that a->sock.p_sys = a */
 # define tls_Send( a, b, c ) (((tls_session_t *)a)->sock.pf_send (a, b, c ))
 
index 8af649f355649e890c40e801bb7cdbd345379574..706b75a558a9267a2485a6550f09bd30d2d80fec 100644 (file)
@@ -301,9 +301,11 @@ gnutls_Recv( void *p_session, void *buf, int i_length )
 
 
 /**
- * @return -1 on error (you need not and must not call tls_SessionClose())
- * 0 on succesful handshake completion, 1 if more would-be blocking recv is
- * needed, 2 if more would-be blocking send is required.
+ * Starts or continues the TLS handshake.
+ *
+ * @return -1 on fatal error, 0 on succesful handshake completion,
+ * 1 if more would-be blocking recv is needed,
+ * 2 if more would-be blocking send is required.
  */
 static int
 gnutls_ContinueHandshake (tls_session_t *p_session)
@@ -325,7 +327,6 @@ gnutls_ContinueHandshake (tls_session_t *p_session)
 #endif
         msg_Err( p_session, "TLS handshake error: %s",
                  gnutls_strerror( val ) );
-        p_session->pf_close( p_session );
         return -1;
     }
 
@@ -373,7 +374,7 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
     {
         msg_Err( session, "Certificate verification failed: %s",
                  gnutls_strerror( val ) );
-        goto error;
+        return -1;
     }
 
     if( status )
@@ -392,7 +393,7 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
             msg_Err( session,
                      "unknown certificate error (you found a bug in VLC)" );
 
-        goto error;
+        return -1;
     }
 
     /* certificate (host)name verification */
@@ -401,7 +402,7 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
     if( data == NULL )
     {
         msg_Err( session, "Peer certificate not available" );
-        goto error;
+        return -1;
     }
 
     gnutls_x509_crt cert;
@@ -409,7 +410,7 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
     if( val )
     {
         msg_Err( session, "x509 fatal error: %s", gnutls_strerror( val ) );
-        goto error;
+        return -1;
     }
 
     val = gnutls_x509_crt_import( cert, data, GNUTLS_X509_FMT_DER );
@@ -417,7 +418,7 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
     {
         msg_Err( session, "Certificate import error: %s",
                  gnutls_strerror( val ) );
-        goto crt_error;
+        goto error;
     }
 
     if( p_sys->psz_hostname != NULL )
@@ -426,7 +427,7 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
         {
             msg_Err( session, "Certificate does not match \"%s\"",
                      p_sys->psz_hostname );
-            goto crt_error;
+            goto error;
         }
     }
     else
@@ -435,43 +436,34 @@ gnutls_HandshakeAndValidate( tls_session_t *session )
     if( gnutls_x509_crt_get_expiration_time( cert ) < time( NULL ) )
     {
         msg_Err( session, "Certificate expired" );
-        goto crt_error;
+        goto error;
     }
 
     if( gnutls_x509_crt_get_activation_time( cert ) > time ( NULL ) )
     {
         msg_Err( session, "Certificate not yet valid" );
-        goto crt_error;
+        goto 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 );
+    gnutls_x509_crt_deinit( cert );
     return -1;
 }
 
 /**
- * Starts negociation of a TLS session.
+ * Sets the operating system file descriptor backend for the TLS sesison.
  *
  * @param fd stream socket already connected with the peer.
- *
- * @return -1 on error (you need not and must not call tls_SessionClose),
- * 0 on succesful handshake completion, 1 if more would-be blocking recv is
- * needed, 2 if more would-be blocking send is required.
  */
-static int
-gnutls_BeginHandshake( tls_session_t *p_session, int fd )
+static void
+gnutls_SetFD (tls_session_t *p_session, int fd)
 {
-    tls_session_sys_t *p_sys = p_session->p_sys;
-
-    gnutls_transport_set_ptr (p_sys->session, (gnutls_transport_ptr)(intptr_t)fd);
-
-    return p_session->pf_handshake2( p_session );
+    gnutls_transport_set_ptr (p_session->p_sys->session,
+                              (gnutls_transport_ptr)(intptr_t)fd);
 }
 
 typedef int (*tls_prio_func) (gnutls_session_t, const int *);
@@ -718,8 +710,7 @@ static int OpenClient (vlc_object_t *obj)
     p_session->sock.p_sys = p_session;
     p_session->sock.pf_send = gnutls_Send;
     p_session->sock.pf_recv = gnutls_Recv;
-    p_session->pf_handshake = gnutls_BeginHandshake;
-    p_session->pf_close = NULL;
+    p_session->pf_set_fd = gnutls_SetFD;
 
     p_sys->session.b_handshaked = VLC_FALSE;
     p_sys->session.psz_hostname = NULL;
@@ -748,10 +739,10 @@ static int OpenClient (vlc_object_t *obj)
         sprintf (path, "%s/ca-certificates.crt", datadir);
         gnutls_Addx509File (VLC_OBJECT (p_session),
                             p_sys->x509_cred, path, VLC_FALSE);
-        p_session->pf_handshake2 = gnutls_HandshakeAndValidate;
+        p_session->pf_handshake = gnutls_HandshakeAndValidate;
     }
     else
-        p_session->pf_handshake2 = gnutls_ContinueHandshake;
+        p_session->pf_handshake = gnutls_ContinueHandshake;
 
     sprintf (path, "%s/ssl/private", homedir);
     gnutls_Addx509Directory (VLC_OBJECT (p_session), p_sys->x509_cred,
@@ -830,7 +821,7 @@ struct tls_server_sys_t
     int                             i_cache_size;
     vlc_mutex_t                     cache_lock;
 
-    int                             (*pf_handshake2)( tls_session_t * );
+    int                             (*pf_handshake)( tls_session_t * );
 };
 
 
@@ -949,9 +940,10 @@ static int cb_delete( void *p_server, gnutls_datum key )
  * You still have to close the socket yourself.
  */
 static void
-gnutls_SessionClose( tls_session_t *p_session )
+gnutls_SessionClose (tls_server_t *p_server, tls_session_t *p_session)
 {
     tls_session_sys_t *p_sys = p_session->p_sys;
+    (void)p_server;
 
     if( p_sys->b_handshaked == VLC_TRUE )
         gnutls_bye( p_sys->session, GNUTLS_SHUT_WR );
@@ -986,15 +978,12 @@ gnutls_ServerSessionPrepare( tls_server_t *p_server )
         return NULL;
     }
 
-    vlc_object_attach( p_session, p_server );
-
     p_server_sys = p_server->p_sys;
     p_session->sock.p_sys = p_session;
     p_session->sock.pf_send = gnutls_Send;
     p_session->sock.pf_recv = gnutls_Recv;
-    p_session->pf_handshake = gnutls_BeginHandshake;
-    p_session->pf_handshake2 = p_server_sys->pf_handshake2;
-    p_session->pf_close = gnutls_SessionClose;
+    p_session->pf_set_fd = gnutls_SetFD;
+    p_session->pf_handshake = p_server_sys->pf_handshake;
 
     p_session->p_sys->b_handshaked = VLC_FALSE;
     p_session->p_sys->psz_hostname = NULL;
@@ -1025,8 +1014,8 @@ gnutls_ServerSessionPrepare( tls_server_t *p_server )
         goto error;
     }
 
-    if( p_session->pf_handshake2 == gnutls_HandshakeAndValidate )
-        gnutls_certificate_server_set_request( session, GNUTLS_CERT_REQUIRE );
+    if (p_session->pf_handshake == gnutls_HandshakeAndValidate)
+        gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE);
 
     i_val = config_GetInt (p_server, "gnutls-dh-bits");
     gnutls_dh_set_prime_bits (session, i_val);
@@ -1079,7 +1068,7 @@ gnutls_ServerAddCA( tls_server_t *p_server, const char *psz_ca_path )
     msg_Dbg( p_server, " %d trusted CA added (%s)", val, psz_ca_path );
 
     /* enables peer's certificate verification */
-    p_sys->pf_handshake2 = gnutls_HandshakeAndValidate;
+    p_sys->pf_handshake = gnutls_HandshakeAndValidate;
 
     return VLC_SUCCESS;
 }
@@ -1143,12 +1132,13 @@ static int OpenServer (vlc_object_t *obj)
 
     p_sys->p_store = p_sys->p_cache;
     p_server->p_sys = p_sys;
-    p_server->pf_add_CA = gnutls_ServerAddCA;
+    p_server->pf_add_CA  = gnutls_ServerAddCA;
     p_server->pf_add_CRL = gnutls_ServerAddCRL;
-    p_server->pf_session_prepare = gnutls_ServerSessionPrepare;
+    p_server->pf_open    = gnutls_ServerSessionPrepare;
+    p_server->pf_close   = gnutls_SessionClose;
 
     /* No certificate validation by default */
-    p_sys->pf_handshake2 = gnutls_ContinueHandshake;
+    p_sys->pf_handshake  = gnutls_ContinueHandshake;
 
     vlc_mutex_init( p_server, &p_sys->cache_lock );
 
index 66af2385e9914294e36fd68e972b29223678d811..017365f5ac65019875a70193f2969b9de7f35e47 100644 (file)
@@ -311,8 +311,6 @@ __str_format_meta
 str_format_time
 tls_ClientCreate
 tls_ClientDelete
-tls_ServerCreate
-tls_ServerDelete
 ToLocale
 unescape_URI
 unescape_URI_duplicate
index 756e2264c3d67f0b74c3e03486d946c865e66864..3f5a3c992fead7c6fdabe44fbdd337ba277db398 100644 (file)
@@ -94,6 +94,62 @@ void tls_ServerDelete (tls_server_t *srv)
 }
 
 
+/**
+ * Adds one or more certificate authorities from a file.
+ * @return -1 on error, 0 on success.
+ */
+int tls_ServerAddCA (tls_server_t *srv, const char *path)
+{
+    return srv->pf_add_CA (srv, path);
+}
+
+
+/**
+ * Adds one or more certificate revocation list from a file.
+ * @return -1 on error, 0 on success.
+ */
+int tls_ServerAddCRL (tls_server_t *srv, const char *path)
+{
+    return srv->pf_add_CRL (srv, path);
+}
+
+
+tls_session_t *tls_ServerSessionPrepare (tls_server_t *srv)
+{
+    tls_session_t *ses;
+
+    ses = srv->pf_open (srv);
+    if (ses == NULL)
+        return NULL;
+
+    vlc_object_attach (ses, srv);
+    return ses;
+}
+
+
+void tls_ServerSessionClose (tls_session_t *ses)
+{
+    tls_server_t *srv = (tls_server_t *)(ses->p_parent);
+    srv->pf_close (srv, ses);
+}
+
+
+int tls_ServerSessionHandshake (tls_session_t *ses, int fd)
+{
+    ses->pf_set_fd (ses, fd);
+    return 2;
+}
+
+
+int tls_SessionContinueHandshake (tls_session_t *ses)
+{
+    int val = ses->pf_handshake (ses);
+    if (val < 0)
+        tls_ServerSessionClose (ses);
+    return val;
+}
+
+
 /**
  * Allocates a client's TLS credentials and shakes hands through the network.
  * This is a blocking network operation.
@@ -108,6 +164,7 @@ tls_session_t *
 tls_ClientCreate (vlc_object_t *obj, int fd, const char *psz_hostname)
 {
     tls_session_t *cl;
+    int val;
 
     cl = (tls_session_t *)vlc_custom_create (obj, sizeof (*cl),
                                              VLC_OBJECT_GENERIC,
@@ -132,9 +189,11 @@ tls_ClientCreate (vlc_object_t *obj, int fd, const char *psz_hostname)
         return NULL;
     }
 
-    int val = tls_ClientSessionHandshake (cl, fd);
-    while (val > 0)
-        val = tls_SessionContinueHandshake (cl);
+    cl->pf_set_fd (cl, fd);
+
+    do
+        val = cl->pf_handshake (cl);
+    while (val > 0);
 
     if (val == 0)
     {