- return VLC_EGENERIC;
- }
-
- if (gnutls_SetPriority (obj, "protocols",
- gnutls_protocol_set_priority, session, protos)
- || gnutls_SetPriority (obj, "compression algorithms",
- gnutls_compression_set_priority, session, comps)
- || gnutls_SetPriority (obj, "MAC algorithms",
- gnutls_mac_set_priority, session, macs)
- || gnutls_SetPriority (obj, "ciphers",
- gnutls_cipher_set_priority, session, ciphers)
- || gnutls_SetPriority (obj, "key exchange algorithms",
- gnutls_kx_set_priority, session, kx)
- || gnutls_SetPriority (obj, "certificate types",
- gnutls_certificate_type_set_priority, session,
- cert_types))
- return VLC_EGENERIC;
-
- return VLC_SUCCESS;
-}
-
-
-static int
-gnutls_Addx509File( vlc_object_t *p_this,
- gnutls_certificate_credentials cred,
- const char *psz_path, vlc_bool_t b_priv );
-
-static int
-gnutls_Addx509Directory( vlc_object_t *p_this,
- gnutls_certificate_credentials cred,
- const char *psz_dirname,
- vlc_bool_t b_priv )
-{
- DIR* dir;
-
- if( *psz_dirname == '\0' )
- psz_dirname = ".";
-
- dir = utf8_opendir( psz_dirname );
- if( dir == NULL )
- {
- msg_Warn( p_this, "cannot open directory (%s): %m", psz_dirname );
- return VLC_EGENERIC;
- }
-#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 ) || utf8_lstat( psz_dirname, &st2 )
- || S_ISLNK( st2.st_mode ) || ( st1.st_ino != st2.st_ino ) )
- {
- closedir( dir );
- return VLC_EGENERIC;
- }
- }
-#endif
-
- for (;;)
- {
- char *ent = utf8_readdir (dir);
- if (ent == NULL)
- break;
-
- if ((strcmp (ent, ".") == 0) || (strcmp (ent, "..") == 0))
- continue;
-
- 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 );
- }
-
- closedir( dir );
- return VLC_SUCCESS;
-}
-
-
-static int
-gnutls_Addx509File( vlc_object_t *p_this,
- gnutls_certificate_credentials cred,
- const char *psz_path, vlc_bool_t b_priv )
-{
- struct stat st;
-
- if( utf8_stat( psz_path, &st ) == 0 )
- {
- if( S_ISREG( st.st_mode ) )
- {
- char *psz_localname = ToLocale( psz_path );
- int i = b_priv
- ? gnutls_certificate_set_x509_key_file( cred,
- psz_localname, psz_localname, GNUTLS_X509_FMT_PEM )
- : gnutls_certificate_set_x509_trust_file( cred,
- psz_localname, GNUTLS_X509_FMT_PEM );
- LocaleFree( psz_localname );
-
- if( i < 0 )
- {
- msg_Warn( p_this, "cannot add x509 credentials (%s): %s",
- psz_path, gnutls_strerror( i ) );
- return VLC_EGENERIC;
- }
- else
- {
- msg_Dbg( p_this, "added x509 credentials (%s)",
- psz_path );
- return VLC_SUCCESS;
- }
- }
- else if( S_ISDIR( st.st_mode ) )
- {
- msg_Dbg( p_this,
- "looking recursively for x509 credentials in %s",
- psz_path );
- return gnutls_Addx509Directory( p_this, cred, psz_path, b_priv);
- }
- }
- else
- msg_Warn( p_this, "cannot add x509 credentials (%s): %m", psz_path );
- return VLC_EGENERIC;
-}
-
-
-/** TLS client session data */
-typedef struct tls_client_sys_t
-{
- struct tls_session_sys_t session;
- gnutls_certificate_credentials x509_cred;
-} tls_client_sys_t;
-
-
-/**
- * Initializes a client-side TLS session.
- */
-static int OpenClient (vlc_object_t *obj)
-{
- tls_session_t *p_session = (tls_session_t *)obj;
- int i_val;
-
- if (gnutls_Init (obj))
- return VLC_EGENERIC;
-
- tls_client_sys_t *p_sys = malloc (sizeof (*p_sys));
- if (p_sys == NULL)
- {
- gnutls_Deinit (obj);
- return VLC_ENOMEM;
- }
-
- p_session->p_sys = &p_sys->session;
- 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_sys->session.b_handshaked = VLC_FALSE;
- p_sys->session.psz_hostname = NULL;
-
- const char *homedir = obj->p_libvlc->psz_datadir,
- *datadir = config_GetDataDir ();
- size_t l1 = strlen (homedir), l2 = strlen (datadir);
- char path[((l1 > l2) ? l1 : l2) + sizeof ("/ssl/private")];
- // > sizeof ("/ssl/certs")
- // > sizeof ("/ca-certificates.crt")
-
- i_val = gnutls_certificate_allocate_credentials (&p_sys->x509_cred);
- if (i_val != 0)
- {
- msg_Err (obj, "cannot allocate X509 credentials: %s",
- gnutls_strerror (i_val));
- goto error;
- }
-
- if (var_CreateGetBool (obj, "tls-check-cert"))
- {
- sprintf (path, "%s/ssl/certs", homedir);
- gnutls_Addx509Directory (VLC_OBJECT (p_session),
- p_sys->x509_cred, path, VLC_FALSE);
-
- 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;