[vlc-commits] Simplify x509 credential loading and allow symbolic links

Rémi Denis-Courmont git at videolan.org
Wed Aug 31 23:02:52 CEST 2011


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Aug 31 17:45:15 2011 +0300| [ceed481a747610be5a881d8746cf188c7419329e] | committer: Rémi Denis-Courmont

Simplify x509 credential loading and allow symbolic links

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

 modules/misc/gnutls.c |  177 ++++++++++++++++++++-----------------------------
 1 files changed, 73 insertions(+), 104 deletions(-)

diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
index a978a18..cc8a56d 100644
--- a/modules/misc/gnutls.c
+++ b/modules/misc/gnutls.c
@@ -396,103 +396,57 @@ gnutls_SessionPrioritize (vlc_object_t *obj, gnutls_session_t session)
     return val;
 }
 
-
-static int
-gnutls_Addx509File( vlc_object_t *p_this,
-                    gnutls_certificate_credentials_t cred,
-                    const char *psz_path, bool b_priv );
-
-static int
-gnutls_Addx509Directory( vlc_object_t *p_this,
-                         gnutls_certificate_credentials_t cred,
-                         const char *psz_dirname,
-                         bool b_priv )
+#ifndef WIN32
+/**
+ * Loads x509 credentials from a file descriptor (directory or regular file)
+ * and closes the descriptor.
+ */
+static void gnutls_Addx509FD (vlc_object_t *obj,
+                              gnutls_certificate_credentials_t cred,
+                              int fd, bool priv, unsigned recursion)
 {
-    DIR* dir;
-
-    if( *psz_dirname == '\0' )
-        psz_dirname = ".";
-
-    dir = vlc_opendir( psz_dirname );
-    if( dir == NULL )
+    DIR *dir = fdopendir (fd);
+    if (dir != NULL)
     {
-        if (errno != ENOENT)
-        {
-            msg_Err (p_this, "cannot open directory (%s): %m", psz_dirname);
-            return VLC_EGENERIC;
-        }
+        if (recursion == 0)
+            goto skipdir;
+        recursion--;
 
-        msg_Dbg (p_this, "creating empty certificate directory: %s",
-                 psz_dirname);
-        vlc_mkdir (psz_dirname, b_priv ? 0700 : 0755);
-        return VLC_SUCCESS;
-    }
-#ifdef S_ISLNK
-    else
-    {
-        struct stat st1, st2;
-        int fd = dirfd( dir );
-
-        /*
-         * Gets stats for the directory path, checks that it is not a
-         * symbolic link (to avoid possibly infinite recursion), and verifies
-         * that the inode is still the same, to avoid TOCTOU race condition.
-         */
-        if( ( fd == -1)
-         || fstat( fd, &st1 ) || vlc_lstat( psz_dirname, &st2 )
-         || S_ISLNK( st2.st_mode ) || ( st1.st_ino != st2.st_ino ) )
+        for (;;)
         {
-            closedir( dir );
-            return VLC_EGENERIC;
-        }
-    }
-#endif
+            char *ent = vlc_readdir (dir);
+            if (ent == NULL)
+                break;
 
-    for (;;)
-    {
-        char *ent = vlc_readdir (dir);
-        if (ent == NULL)
-            break;
+            if ((strcmp (ent, ".") == 0) || (strcmp (ent, "..") == 0))
+            {
+                free (ent);
+                continue;
+            }
 
-        if ((strcmp (ent, ".") == 0) || (strcmp (ent, "..") == 0))
-        {
-            free( ent );
-            continue;
+            int nfd = vlc_openat (fd, ent, O_RDONLY);
+            if (nfd != -1)
+            {
+                msg_Dbg (obj, "loading x509 credentials from %s...", ent);
+                gnutls_Addx509FD (obj, cred, nfd, priv, recursion);
+            }
+            else
+                msg_Dbg (obj, "cannot access x509 credentials in %s", ent);
+            free (ent);
         }
-
-        char path[strlen (psz_dirname) + strlen (ent) + 2];
-        sprintf (path, "%s"DIR_SEP"%s", psz_dirname, ent);
-        free (ent);
-
-        gnutls_Addx509File( p_this, cred, path, b_priv );
+    skipdir:
+        closedir (dir);
+        return;
     }
 
-    closedir( dir );
-    return VLC_SUCCESS;
-}
-
-
-static int
-gnutls_Addx509File( vlc_object_t *p_this,
-                    gnutls_certificate_credentials cred,
-                    const char *psz_path, bool b_priv )
-{
-    struct stat st;
-
-    int fd = vlc_open (psz_path, O_RDONLY);
-    if (fd == -1)
-        goto error;
-
     block_t *block = block_File (fd);
     if (block != NULL)
     {
-        close (fd);
-
         gnutls_datum data = {
             .data = block->p_buffer,
             .size = block->i_buffer,
         };
-        int res = b_priv
+        int res = priv
             ? gnutls_certificate_set_x509_key_mem (cred, &data, &data,
                                                    GNUTLS_X509_FMT_PEM)
             : gnutls_certificate_set_x509_trust_mem (cred, &data,
@@ -500,32 +454,47 @@ gnutls_Addx509File( vlc_object_t *p_this,
         block_Release (block);
 
         if (res < 0)
-        {
-            msg_Warn (p_this, "cannot add x509 credentials (%s): %s",
-                      psz_path, gnutls_strerror (res));
-            return VLC_EGENERIC;
-        }
-        msg_Dbg (p_this, "added %d %s(s) from %s", res,
-                 b_priv ? "key" : "certificate", psz_path);
-        return VLC_SUCCESS;
+            msg_Warn (obj, "cannot add x509 credentials: %s",
+                      gnutls_strerror (res));
+        else
+            msg_Dbg (obj, "added %d %s(s)", res, priv ? "key" : "certificate");
     }
+    else
+        msg_Warn (obj, "cannot read x509 credentials: %m");
+    close (fd);
+}
 
-    if (!fstat (fd, &st) && S_ISDIR (st.st_mode))
+static void gnutls_Addx509Directory (vlc_object_t *obj,
+                                     gnutls_certificate_credentials cred,
+                                     const char *path, bool priv)
+{
+    msg_Dbg (obj, "browsing x509 credentials in %s...", path);
+    int fd = vlc_open (path, O_RDONLY|O_DIRECTORY);
+    if (fd == -1)
     {
-        close (fd);
-        msg_Dbg (p_this, "looking recursively for x509 credentials in %s",
-                 psz_path);
-        return gnutls_Addx509Directory (p_this, cred, psz_path, b_priv);
+        msg_Warn (obj, "cannot access x509 in %s: %m", path);
+        return;
     }
 
-error:
-    msg_Warn (p_this, "cannot add x509 credentials (%s): %m", psz_path);
-    if (fd != -1)
-        close (fd);
-    return VLC_EGENERIC;
+    gnutls_Addx509FD (obj, cred, fd, priv, 5);
 }
 
-#ifdef WIN32
+static void gnutls_Addx509File (vlc_object_t *obj,
+                                gnutls_certificate_credentials cred,
+                                const char *path, bool priv)
+{
+    msg_Dbg (obj, "loading x509 credentials from %s...", path);
+
+    int fd = vlc_open (path, O_RDONLY);
+    if (fd == -1)
+    {
+        msg_Warn (obj, "cannot access x509 in %s: %m", path);
+        return;
+    }
+
+    gnutls_Addx509FD (obj, cred, fd, priv, 0);
+}
+#else /* WIN32 */
 static int
 gnutls_loadOSCAList (vlc_object_t *p_this,
                      gnutls_certificate_credentials cred)
@@ -555,7 +524,7 @@ gnutls_loadOSCAList (vlc_object_t *p_this,
     }
     return VLC_SUCCESS;
 }
-#endif
+#endif /* WIN32 */
 
 /**
  * Initializes a client-side TLS session.
@@ -586,6 +555,7 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname)
         goto error;
     }
 
+#ifndef WIN32
     char *userdir = config_GetUserDir (VLC_DATA_DIR);
     if (userdir != NULL)
     {
@@ -600,9 +570,6 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname)
         free (userdir);
     }
 
-#ifdef WIN32
-    gnutls_loadOSCAList (VLC_OBJECT(session), sys->x509_cred);
-#else
     const char *confdir = config_GetConfDir ();
     {
         char path[strlen (confdir)
@@ -610,6 +577,8 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname)
         sprintf (path, "%s/ssl/certs/ca-certificates.crt", confdir);
         gnutls_Addx509File (VLC_OBJECT(session), sys->x509_cred, path, false);
     }
+#else /* WIN32 */
+    gnutls_loadOSCAList (VLC_OBJECT(session), sys->x509_cred);
 #endif
     session->handshake = gnutls_HandshakeAndValidate;
     /*session->_handshake = gnutls_ContinueHandshake;*/



More information about the vlc-commits mailing list