tls: add ALPN parameters
authorRémi Denis-Courmont <remi@remlab.net>
Sat, 23 Aug 2014 20:10:50 +0000 (23:10 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Sat, 23 Aug 2014 20:26:42 +0000 (23:26 +0300)
include/vlc_tls.h
modules/access/ftp.c
modules/access/http.c
src/network/httpd.c
src/network/tls.c

index 82a9c1f..5bfd418 100644 (file)
@@ -43,9 +43,12 @@ struct vlc_tls
 };
 
 VLC_API vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *, int fd,
-                                        const char *host, const char *service);
-vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *, int fd, const char *host);
-int vlc_tls_SessionHandshake (vlc_tls_t *, const char *host, const char *serv);
+                                         const char *host, const char *service,
+                                         const char *const *alpn, char **alp);
+vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *, int fd, const char *host,
+                                  const char *const *alpn);
+int vlc_tls_SessionHandshake (vlc_tls_t *, const char *host, const char *serv,
+                              char **restrict alp);
 VLC_API void vlc_tls_SessionDelete (vlc_tls_t *);
 
 /* NOTE: It is assumed that a->sock.p_sys = a */
index 90b2452..aa42a31 100644 (file)
@@ -286,7 +286,8 @@ static int createCmdTLS( vlc_object_t *p_access, access_sys_t *p_sys, int fd,
     /* TLS/SSL handshake */
     p_sys->cmd.p_tls = vlc_tls_ClientSessionCreate( p_sys->p_creds, fd,
                                                     p_sys->url.psz_host,
-                                                    psz_session_name );
+                                                    psz_session_name,
+                                                    NULL, NULL );
     if( p_sys->cmd.p_tls == NULL )
     {
         msg_Err( p_access, "cannot establish FTP/TLS session on command channel" );
@@ -1028,7 +1029,8 @@ static int ftp_StartStream( vlc_object_t *p_access, access_sys_t *p_sys,
         p_sys->data.p_tls = vlc_tls_ClientSessionCreate( p_sys->p_creds,
                             p_sys->data.fd, p_sys->url.psz_host,
                             ( p_sys->tlsmode == EXPLICIT ) ? "ftpes-data"
-                                                           : "ftps-data" );
+                                                           : "ftps-data",
+                                                         NULL, NULL );
         if( p_sys->data.p_tls == NULL )
         {
             msg_Err( p_access, "cannot establish FTP/TLS session for data" \
index 36927be..91ac069 100644 (file)
@@ -1109,7 +1109,7 @@ static int Connect( access_t *p_access, uint64_t i_tell )
 
         /* TLS/SSL handshake */
         p_sys->p_tls = vlc_tls_ClientSessionCreate( p_sys->p_creds, p_sys->fd,
-                                                p_sys->url.psz_host, "https" );
+                                    p_sys->url.psz_host, "https", NULL, NULL );
         if( p_sys->p_tls == NULL )
         {
             msg_Err( p_access, "cannot establish HTTP/TLS session" );
index 8039ea0..e243ac6 100644 (file)
@@ -1670,7 +1670,8 @@ static void httpd_ClientSend(httpd_client_t *cl)
 
 static void httpd_ClientTlsHandshake(httpd_client_t *cl)
 {
-    switch(vlc_tls_SessionHandshake(cl->p_tls, NULL, NULL)) {
+    switch (vlc_tls_SessionHandshake(cl->p_tls, NULL, NULL, NULL))
+    {
         case -1: cl->i_state = HTTPD_CLIENT_DEAD;       break;
         case 0:  cl->i_state = HTTPD_CLIENT_RECEIVING;  break;
         case 1:  cl->i_state = HTTPD_CLIENT_TLS_HS_IN;  break;
@@ -2047,7 +2048,7 @@ static void httpdLoop(httpd_host_t *host)
         vlc_tls_t *p_tls;
 
         if (host->p_tls)
-            p_tls = vlc_tls_SessionCreate(host->p_tls, fd, NULL);
+            p_tls = vlc_tls_SessionCreate(host->p_tls, fd, NULL, NULL);
         else
             p_tls = NULL;
 
index 89393bb..c9c99c7 100644 (file)
@@ -146,11 +146,11 @@ void vlc_tls_Delete (vlc_tls_creds_t *crd)
 /*** TLS  session ***/
 
 vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *crd, int fd,
-                                  const char *host)
+                                  const char *host, const char *const *alpn)
 {
     vlc_tls_t *session = vlc_custom_create (crd, sizeof (*session),
                                             "tls session");
-    int val = crd->open (crd, session, fd, host, NULL);
+    int val = crd->open (crd, session, fd, host, alpn);
     if (val == VLC_SUCCESS)
         return session;
     vlc_object_release (session);
@@ -158,11 +158,11 @@ vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *crd, int fd,
 }
 
 int vlc_tls_SessionHandshake (vlc_tls_t *session, const char *host,
-                              const char *service)
+                              const char *service, char **restrict alp)
 {
     vlc_tls_creds_t *crd = (vlc_tls_creds_t *)(session->p_parent);
 
-    return crd->handshake (session, host, service, NULL);
+    return crd->handshake (session, host, service, alp);
 }
 
 void vlc_tls_SessionDelete (vlc_tls_t *session)
@@ -180,13 +180,20 @@ void vlc_tls_SessionDelete (vlc_tls_t *session)
  * @param fd socket through which to establish the secure channel
  * @param hostname expected server name, used both as Server Name Indication
  *                 and as expected Common Name of the peer certificate
+ * @param service unique identifier for the service to connect to
+ *                (only used locally for certificates database)
+ * @param alpn NULL-terminated list of Application Layer Protocols
+ *             to negotiate, or NULL to not negotiate protocols
+ * @param alp storage space for the negotiated Application Layer
+ *            Protocol or NULL if negotiation was not performed[OUT]
  *
  * @return NULL on error.
  **/
 vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
-                                        const char *host, const char *service)
+                                        const char *host, const char *service,
+                                        const char *const *alpn, char **alp)
 {
-    vlc_tls_t *session = vlc_tls_SessionCreate (crd, fd, host);
+    vlc_tls_t *session = vlc_tls_SessionCreate (crd, fd, host, alpn);
     if (session == NULL)
         return NULL;
 
@@ -197,8 +204,14 @@ vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
     ufd[0].fd = fd;
 
     int val;
-    while ((val = vlc_tls_SessionHandshake (session, host, service)) > 0)
+    while ((val = vlc_tls_SessionHandshake (session, host, service, alp)) != 0)
     {
+        if (val < 0)
+        {
+            msg_Err (session, "TLS client session handshake error");
+            goto error;
+        }
+
         mtime_t now = mdate ();
         if (now > deadline)
            now = deadline;
@@ -209,16 +222,11 @@ vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
         if (poll (ufd, 1, (deadline - now) / 1000) == 0)
         {
             msg_Err (session, "TLS client session handshake timeout");
-            val = -1;
-            break;
+            goto error;
         }
     }
-
-    if (val != 0)
-    {
-        msg_Err (session, "TLS client session handshake error");
-        vlc_tls_SessionDelete (session);
-        session = NULL;
-    }
     return session;
+error:
+    vlc_tls_SessionDelete (session);
+    return NULL;
 }