Commit ceed481a authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Simplify x509 credential loading and allow symbolic links

parent 343ffdbf
...@@ -396,57 +396,21 @@ gnutls_SessionPrioritize (vlc_object_t *obj, gnutls_session_t session) ...@@ -396,57 +396,21 @@ gnutls_SessionPrioritize (vlc_object_t *obj, gnutls_session_t session)
return val; return val;
} }
#ifndef WIN32
static int /**
gnutls_Addx509File( vlc_object_t *p_this, * Loads x509 credentials from a file descriptor (directory or regular file)
gnutls_certificate_credentials_t cred, * and closes the descriptor.
const char *psz_path, bool b_priv ); */
static void gnutls_Addx509FD (vlc_object_t *obj,
static int
gnutls_Addx509Directory( vlc_object_t *p_this,
gnutls_certificate_credentials_t cred, gnutls_certificate_credentials_t cred,
const char *psz_dirname, int fd, bool priv, unsigned recursion)
bool b_priv )
{ {
DIR* dir; DIR *dir = fdopendir (fd);
if (dir != NULL)
if( *psz_dirname == '\0' )
psz_dirname = ".";
dir = vlc_opendir( psz_dirname );
if( dir == NULL )
{
if (errno != ENOENT)
{
msg_Err (p_this, "cannot open directory (%s): %m", psz_dirname);
return VLC_EGENERIC;
}
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 ) )
{ {
closedir( dir ); if (recursion == 0)
return VLC_EGENERIC; goto skipdir;
} recursion--;
}
#endif
for (;;) for (;;)
{ {
...@@ -456,43 +420,33 @@ gnutls_Addx509Directory( vlc_object_t *p_this, ...@@ -456,43 +420,33 @@ gnutls_Addx509Directory( vlc_object_t *p_this,
if ((strcmp (ent, ".") == 0) || (strcmp (ent, "..") == 0)) if ((strcmp (ent, ".") == 0) || (strcmp (ent, "..") == 0))
{ {
free( ent ); free (ent);
continue; continue;
} }
char path[strlen (psz_dirname) + strlen (ent) + 2]; int nfd = vlc_openat (fd, ent, O_RDONLY);
sprintf (path, "%s"DIR_SEP"%s", psz_dirname, ent); 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); free (ent);
gnutls_Addx509File( p_this, cred, path, b_priv );
} }
skipdir:
closedir( dir ); closedir (dir);
return VLC_SUCCESS; return;
} }
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); block_t *block = block_File (fd);
if (block != NULL) if (block != NULL)
{ {
close (fd);
gnutls_datum data = { gnutls_datum data = {
.data = block->p_buffer, .data = block->p_buffer,
.size = block->i_buffer, .size = block->i_buffer,
}; };
int res = b_priv int res = priv
? gnutls_certificate_set_x509_key_mem (cred, &data, &data, ? gnutls_certificate_set_x509_key_mem (cred, &data, &data,
GNUTLS_X509_FMT_PEM) GNUTLS_X509_FMT_PEM)
: gnutls_certificate_set_x509_trust_mem (cred, &data, : gnutls_certificate_set_x509_trust_mem (cred, &data,
...@@ -500,32 +454,47 @@ gnutls_Addx509File( vlc_object_t *p_this, ...@@ -500,32 +454,47 @@ gnutls_Addx509File( vlc_object_t *p_this,
block_Release (block); block_Release (block);
if (res < 0) if (res < 0)
{ msg_Warn (obj, "cannot add x509 credentials: %s",
msg_Warn (p_this, "cannot add x509 credentials (%s): %s", gnutls_strerror (res));
psz_path, gnutls_strerror (res)); else
return VLC_EGENERIC; msg_Dbg (obj, "added %d %s(s)", res, priv ? "key" : "certificate");
}
msg_Dbg (p_this, "added %d %s(s) from %s", res,
b_priv ? "key" : "certificate", psz_path);
return VLC_SUCCESS;
} }
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_Warn (obj, "cannot access x509 in %s: %m", path);
msg_Dbg (p_this, "looking recursively for x509 credentials in %s", return;
psz_path);
return gnutls_Addx509Directory (p_this, cred, psz_path, b_priv);
} }
error: gnutls_Addx509FD (obj, cred, fd, priv, 5);
msg_Warn (p_this, "cannot add x509 credentials (%s): %m", psz_path);
if (fd != -1)
close (fd);
return VLC_EGENERIC;
} }
#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 static int
gnutls_loadOSCAList (vlc_object_t *p_this, gnutls_loadOSCAList (vlc_object_t *p_this,
gnutls_certificate_credentials cred) gnutls_certificate_credentials cred)
...@@ -555,7 +524,7 @@ gnutls_loadOSCAList (vlc_object_t *p_this, ...@@ -555,7 +524,7 @@ gnutls_loadOSCAList (vlc_object_t *p_this,
} }
return VLC_SUCCESS; return VLC_SUCCESS;
} }
#endif #endif /* WIN32 */
/** /**
* Initializes a client-side TLS session. * Initializes a client-side TLS session.
...@@ -586,6 +555,7 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname) ...@@ -586,6 +555,7 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname)
goto error; goto error;
} }
#ifndef WIN32
char *userdir = config_GetUserDir (VLC_DATA_DIR); char *userdir = config_GetUserDir (VLC_DATA_DIR);
if (userdir != NULL) if (userdir != NULL)
{ {
...@@ -600,9 +570,6 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname) ...@@ -600,9 +570,6 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname)
free (userdir); free (userdir);
} }
#ifdef WIN32
gnutls_loadOSCAList (VLC_OBJECT(session), sys->x509_cred);
#else
const char *confdir = config_GetConfDir (); const char *confdir = config_GetConfDir ();
{ {
char path[strlen (confdir) char path[strlen (confdir)
...@@ -610,6 +577,8 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname) ...@@ -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); sprintf (path, "%s/ssl/certs/ca-certificates.crt", confdir);
gnutls_Addx509File (VLC_OBJECT(session), sys->x509_cred, path, false); gnutls_Addx509File (VLC_OBJECT(session), sys->x509_cred, path, false);
} }
#else /* WIN32 */
gnutls_loadOSCAList (VLC_OBJECT(session), sys->x509_cred);
#endif #endif
session->handshake = gnutls_HandshakeAndValidate; session->handshake = gnutls_HandshakeAndValidate;
/*session->_handshake = gnutls_ContinueHandshake;*/ /*session->_handshake = gnutls_ContinueHandshake;*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment