[vlc-commits] tls: keep credentials when HTTP reconnects

Rémi Denis-Courmont git at videolan.org
Sat Sep 29 18:14:27 CEST 2012


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Sep 29 16:52:13 2012 +0300| [4f0fadb7794b092f6363482cc7b41346b265b9c4] | committer: Rémi Denis-Courmont

tls: keep credentials when HTTP reconnects

Keeping the credentials container saves some times, as we do not need
to load and parse all of the 100+ Certificate Authorities again.
In the future, it will also avoid reloading the stored public keys
(i.e. security exceptions), or asking for user confirmation again.

Given how the HTTP access is written, the credentials are now preserved
upon seeking. Unfortunately, they are not recycled across redirections
as access_t.p_sys gets destroyed internally. This also does not work
across multiple inputs - support from the instance or input manager
would be required.

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

 include/vlc_tls.h     |   17 ++++++------
 modules/access/http.c |   24 ++++++++++-------
 src/libvlccore.sym    |    4 ++-
 src/network/tls.c     |   72 ++++++++++++++++++++++---------------------------
 4 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/include/vlc_tls.h b/include/vlc_tls.h
index 59ef7c2..d732d16 100644
--- a/include/vlc_tls.h
+++ b/include/vlc_tls.h
@@ -45,9 +45,12 @@ struct vlc_tls
     int  (*handshake) (struct vlc_tls *);
 };
 
-VLC_API vlc_tls_t *vlc_tls_ClientCreate (vlc_object_t *, int fd,
-                                         const char *hostname);
-VLC_API void vlc_tls_ClientDelete (vlc_tls_t *);
+VLC_API vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *, int fd,
+                                                const char *host);
+vlc_tls_t *vlc_tls_ServerSessionCreate (vlc_tls_creds_t *, int fd);
+int vlc_tls_ServerSessionHandshake (vlc_tls_t *);
+VLC_API void vlc_tls_SessionDelete (vlc_tls_t *);
+#define vlc_tls_ServerSessionDelete vlc_tls_SessionDelete
 
 /* NOTE: It is assumed that a->sock.p_sys = a */
 # define tls_Send( a, b, c ) (((vlc_tls_t *)a)->sock.pf_send (a, b, c))
@@ -70,16 +73,12 @@ struct vlc_tls_creds
     void (*close) (vlc_tls_creds_t *, vlc_tls_t *);
 };
 
+VLC_API vlc_tls_creds_t *vlc_tls_ClientCreate (vlc_object_t *);
 vlc_tls_creds_t *vlc_tls_ServerCreate (vlc_object_t *,
                                        const char *cert, const char *key);
-void vlc_tls_Delete (vlc_tls_creds_t *);
+VLC_API void vlc_tls_Delete (vlc_tls_creds_t *);
 #define vlc_tls_ServerDelete vlc_tls_Delete
 int vlc_tls_ServerAddCA (vlc_tls_creds_t *srv, const char *path);
 int vlc_tls_ServerAddCRL (vlc_tls_creds_t *srv, const char *path);
 
-vlc_tls_t *vlc_tls_ServerSessionCreate (vlc_tls_creds_t *, int fd);
-int vlc_tls_ServerSessionHandshake (vlc_tls_t *);
-void vlc_tls_SessionDelete (vlc_tls_t *);
-#define vlc_tls_ServerSessionDelete vlc_tls_SessionDelete
-
 #endif
diff --git a/modules/access/http.c b/modules/access/http.c
index baa1a59..226333b 100644
--- a/modules/access/http.c
+++ b/modules/access/http.c
@@ -139,7 +139,8 @@ struct access_sys_t
 {
     int fd;
     bool b_error;
-    vlc_tls_t  *p_tls;
+    vlc_tls_creds_t *p_creds;
+    vlc_tls_t *p_tls;
     v_socket_t *p_vs;
 
     /* From uri */
@@ -164,7 +165,6 @@ struct access_sys_t
     char       *psz_location;
     bool b_mms;
     bool b_icecast;
-    bool b_ssl;
 #ifdef HAVE_ZLIB_H
     bool b_compressed;
     struct
@@ -269,7 +269,6 @@ static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
     p_sys->psz_user_agent = NULL;
     p_sys->psz_referrer = NULL;
     p_sys->b_pace_control = true;
-    p_sys->b_ssl = false;
 #ifdef HAVE_ZLIB_H
     p_sys->b_compressed = false;
     /* 15 is the max windowBits, +32 to enable optional gzip decoding */
@@ -314,7 +313,9 @@ static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
     if( !strncmp( psz_access, "https", 5 ) )
     {
         /* HTTP over SSL */
-        p_sys->b_ssl = true;
+        p_sys->p_creds = vlc_tls_ClientCreate( p_this );
+        if( p_sys->p_creds == NULL )
+            goto error;
         if( p_sys->url.i_port <= 0 )
             p_sys->url.i_port = 443;
     }
@@ -600,6 +601,7 @@ connect:
         free( p_sys->psz_referrer );
 
         Disconnect( p_access );
+        vlc_tls_Delete( p_sys->p_creds );
         cookies = p_sys->cookies;
 #ifdef HAVE_ZLIB_H
         inflateEnd( &p_sys->inflate.stream );
@@ -692,6 +694,7 @@ error:
     free( p_sys->psz_referrer );
 
     Disconnect( p_access );
+    vlc_tls_Delete( p_sys->p_creds );
 
     if( p_sys->cookies )
     {
@@ -733,6 +736,7 @@ static void Close( vlc_object_t *p_this )
     free( p_sys->psz_referrer );
 
     Disconnect( p_access );
+    vlc_tls_Delete( p_sys->p_creds );
 
     if( p_sys->cookies )
     {
@@ -1156,7 +1160,7 @@ static int Connect( access_t *p_access, uint64_t i_tell )
     setsockopt (p_sys->fd, SOL_SOCKET, SO_KEEPALIVE, &(int){ 1 }, sizeof (int));
 
     /* Initialize TLS/SSL session */
-    if( p_sys->b_ssl )
+    if( p_sys->p_creds != NULL )
     {
         /* CONNECT to establish TLS tunnel through HTTP proxy */
         if( p_sys->b_proxy )
@@ -1220,8 +1224,8 @@ static int Connect( access_t *p_access, uint64_t i_tell )
         }
 
         /* TLS/SSL handshake */
-        p_sys->p_tls = vlc_tls_ClientCreate( VLC_OBJECT(p_access), p_sys->fd,
-                                             p_sys->url.psz_host );
+        p_sys->p_tls = vlc_tls_ClientSessionCreate( p_sys->p_creds, p_sys->fd,
+                                                    p_sys->url.psz_host );
         if( p_sys->p_tls == NULL )
         {
             msg_Err( p_access, "cannot establish HTTP/TLS session" );
@@ -1450,9 +1454,9 @@ static int Request( access_t *p_access, uint64_t i_tell )
              * handle it as everyone does. */
             if( p[0] == '/' )
             {
-                const char *psz_http_ext = p_sys->b_ssl ? "s" : "" ;
+                const char *psz_http_ext = p_sys->p_tls ? "s" : "" ;
 
-                if( p_sys->url.i_port == ( p_sys->b_ssl ? 443 : 80 ) )
+                if( p_sys->url.i_port == ( p_sys->p_tls ? 443 : 80 ) )
                 {
                     if( asprintf(&psz_new_loc, "http%s://%s%s", psz_http_ext,
                                  p_sys->url.psz_host, p) < 0 )
@@ -1632,7 +1636,7 @@ static void Disconnect( access_t *p_access )
 
     if( p_sys->p_tls != NULL)
     {
-        vlc_tls_ClientDelete( p_sys->p_tls );
+        vlc_tls_SessionDelete( p_sys->p_tls );
         p_sys->p_tls = NULL;
         p_sys->p_vs = NULL;
     }
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index c7ec811..0c36f01 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -414,7 +414,9 @@ subpicture_region_ChainDelete
 subpicture_region_Delete
 subpicture_region_New
 vlc_tls_ClientCreate
-vlc_tls_ClientDelete
+vlc_tls_Delete
+vlc_tls_ClientSessionCreate
+vlc_tls_SessionDelete
 ToCharset
 update_Check
 update_Delete
diff --git a/src/network/tls.c b/src/network/tls.c
index 0740263..707c1b4 100644
--- a/src/network/tls.c
+++ b/src/network/tls.c
@@ -95,13 +95,37 @@ vlc_tls_ServerCreate (vlc_object_t *obj, const char *cert_path,
         return NULL;
     }
 
-    msg_Dbg (srv, "TLS server plugin initialized");
     return srv;
 }
 
+/**
+ * Allocates TLS credentials for a client.
+ * Credentials can be cached and reused across multiple TLS sessions.
+ *
+ * @return TLS credentials object, or NULL on error.
+ **/
+vlc_tls_creds_t *vlc_tls_ClientCreate (vlc_object_t *obj)
+{
+    vlc_tls_creds_t *crd = vlc_custom_create (obj, sizeof (*crd),
+                                              "tls client");
+    if (unlikely(crd == NULL))
+        return NULL;
+
+    crd->module = vlc_module_load (crd, "tls client", NULL, false,
+                                   tls_client_load, crd);
+    if (crd->module == NULL)
+    {
+        msg_Err (crd, "TLS client plugin not available");
+        vlc_object_release (crd);
+        return NULL;
+    }
+
+    return crd;
+}
 
 /**
- * Releases data allocated with vlc_tls_ServerCreate().
+ * Releases data allocated with vlc_tls_ClientCreate() or
+ * vlc_tls_ServerCreate().
  * @param srv TLS server object to be destroyed, or NULL
  */
 void vlc_tls_Delete (vlc_tls_creds_t *crd)
@@ -170,34 +194,19 @@ int vlc_tls_ServerSessionHandshake (vlc_tls_t *ses)
 }
 
 /**
- * Allocates a client's TLS credentials and shakes hands through the network.
- * This is a blocking network operation.
+ * Performs client side of TLS handshake through a connected socket, and
+ * establishes a secure channel. This is a blocking network operation.
  *
  * @param fd stream socket through which to establish the secure communication
  * layer.
- * @param psz_hostname Server Name Indication to pass to the server, or NULL.
+ * @param hostname expected server name, used both as Server Name Indication
+ *                 and as expected Common Name of the peer's certificate.
  *
  * @return NULL on error.
  **/
-vlc_tls_t *
-vlc_tls_ClientCreate (vlc_object_t *obj, int fd, const char *hostname)
+vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
+                                        const char *hostname)
 {
-    vlc_tls_creds_t *crd = vlc_custom_create (obj, sizeof (*crd),
-                                              "tls client");
-    if (unlikely(crd == NULL))
-        return NULL;
-
-    crd->module = vlc_module_load (crd, "tls client", NULL, false,
-                                   tls_client_load, crd);
-    if (crd->module == NULL)
-    {
-        msg_Err (crd, "TLS client plugin not available");
-        vlc_object_release (crd);
-        return NULL;
-    }
-
-    /* TODO: separate credentials and sessions, so we do not reload the
-     * credentials every time the HTTP access seeks... */
     vlc_tls_t *session = vlc_tls_SessionCreate (crd, fd, hostname);
     if (session == NULL)
         goto error;
@@ -214,25 +223,8 @@ vlc_tls_ClientCreate (vlc_object_t *obj, int fd, const char *hostname)
         vlc_tls_SessionDelete (session);
         goto error;
     }
-    msg_Dbg (session, "TLS client session initialized");
     return session;
 error:
     vlc_tls_Delete (crd);
     return NULL;
 }
-
-
-/**
- * Releases data allocated with vlc_tls_ClientCreate().
- * It is your job to close the underlying socket.
- */
-void vlc_tls_ClientDelete (vlc_tls_t *session)
-{
-    if (session == NULL)
-        return;
-
-    vlc_tls_creds_t *cl = (vlc_tls_creds_t *)(session->p_parent);
-
-    vlc_tls_SessionDelete (session);
-    vlc_tls_Delete (cl);
-}



More information about the vlc-commits mailing list