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

- optional SSL hostname verification

parent f2a0cc3f
...@@ -881,7 +881,8 @@ static int Connect( access_t *p_access, int64_t i_tell ) ...@@ -881,7 +881,8 @@ static int Connect( access_t *p_access, int64_t i_tell )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_sys->p_tls = tls_ClientCreate( VLC_OBJECT(p_access), p_sys->fd, NULL ); p_sys->p_tls = tls_ClientCreate( VLC_OBJECT(p_access), p_sys->fd,
srv.psz_host );
if( p_sys->p_tls == NULL ) if( p_sys->p_tls == NULL )
{ {
msg_Err( p_access, "cannot establish HTTP/SSL session" ); msg_Err( p_access, "cannot establish HTTP/SSL session" );
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <gcrypt.h> #include <gcrypt.h>
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#define DH_BITS 1024 #define DH_BITS 1024
#define CACHE_EXPIRATION 3600 #define CACHE_EXPIRATION 3600
...@@ -96,10 +97,8 @@ vlc_module_begin(); ...@@ -96,10 +97,8 @@ vlc_module_begin();
add_bool( "tls-check-cert", VLC_FALSE, NULL, CHECK_CERT_TEXT, add_bool( "tls-check-cert", VLC_FALSE, NULL, CHECK_CERT_TEXT,
CHECK_CERT_LONGTEXT, VLC_FALSE ); CHECK_CERT_LONGTEXT, VLC_FALSE );
#if 0
add_bool( "tls-check-hostname", VLC_FALSE, NULL, CHECK_HOSTNAME_TEXT, add_bool( "tls-check-hostname", VLC_FALSE, NULL, CHECK_HOSTNAME_TEXT,
CHECK_HOSTNAME_LONGTEXT, VLC_FALSE ); CHECK_HOSTNAME_LONGTEXT, VLC_FALSE );
#endif
add_integer( "dh-bits", DH_BITS, NULL, DH_BITS_TEXT, add_integer( "dh-bits", DH_BITS, NULL, DH_BITS_TEXT,
DH_BITS_LONGTEXT, VLC_TRUE ); DH_BITS_LONGTEXT, VLC_TRUE );
...@@ -140,6 +139,7 @@ typedef struct tls_server_sys_t ...@@ -140,6 +139,7 @@ typedef struct tls_server_sys_t
typedef struct tls_session_sys_t typedef struct tls_session_sys_t
{ {
gnutls_session session; gnutls_session session;
char *psz_hostname;
vlc_bool_t b_handshaked; vlc_bool_t b_handshaked;
} tls_session_sys_t; } tls_session_sys_t;
...@@ -263,10 +263,13 @@ gnutls_HandshakeAndValidate( tls_session_t *p_session ) ...@@ -263,10 +263,13 @@ gnutls_HandshakeAndValidate( tls_session_t *p_session )
if( val == 0 ) if( val == 0 )
{ {
int status; int status;
gnutls_x509_crt cert;
const gnutls_datum *p_data;
tls_session_sys_t *p_sys;
val = gnutls_certificate_verify_peers2( ((tls_session_sys_t *) p_sys = (tls_session_sys_t *)(p_session->p_sys);
(p_session->p_sys))->session, /* certificates chain verification */
&status ); val = gnutls_certificate_verify_peers2( p_sys->session, &status );
if( val ) if( val )
{ {
...@@ -292,6 +295,49 @@ gnutls_HandshakeAndValidate( tls_session_t *p_session ) ...@@ -292,6 +295,49 @@ gnutls_HandshakeAndValidate( tls_session_t *p_session )
} }
msg_Dbg( p_session, "TLS certificate verified" ); msg_Dbg( p_session, "TLS certificate verified" );
if( p_sys->psz_hostname == NULL )
return 0;
/* certificate (host)name verification */
p_data = gnutls_certificate_get_peers( p_sys->session, &val );
if( p_data == NULL )
{
msg_Err( p_session, "TLS peer certificate not available" );
p_session->pf_close( p_session );
return -1;
}
val = gnutls_x509_crt_init( &cert );
if( val )
{
msg_Err( p_session, "x509 fatal error : %s",
gnutls_strerror( val ) );
p_session->pf_close( p_session );
return -1;
}
val = gnutls_x509_crt_import( cert, p_data, GNUTLS_X509_FMT_DER );
if( val )
{
msg_Err( p_session, "x509 certificate import error : %s",
gnutls_strerror( val ) );
gnutls_x509_crt_deinit( cert );
p_session->pf_close( p_session );
return -1;
}
if( gnutls_x509_crt_check_hostname( cert, p_sys->psz_hostname ) == 0 )
{
msg_Err( p_session, "x509 certificate does not match \"%s\"",
p_sys->psz_hostname );
gnutls_x509_crt_deinit( cert );
p_session->pf_close( p_session );
return -1;
}
gnutls_x509_crt_deinit( cert );
msg_Dbg( p_session, "x509 hostname verified" );
return 0; return 0;
} }
...@@ -307,9 +353,22 @@ gnutls_BeginHandshake( tls_session_t *p_session, int fd, ...@@ -307,9 +353,22 @@ gnutls_BeginHandshake( tls_session_t *p_session, int fd,
p_sys = (tls_session_sys_t *)(p_session->p_sys); p_sys = (tls_session_sys_t *)(p_session->p_sys);
gnutls_transport_set_ptr (p_sys->session, (gnutls_transport_ptr)fd); gnutls_transport_set_ptr (p_sys->session, (gnutls_transport_ptr)fd);
p_sys->psz_hostname = NULL;
if( psz_hostname != NULL ) if( psz_hostname != NULL )
{
gnutls_server_name_set( p_sys->session, GNUTLS_NAME_DNS, psz_hostname, gnutls_server_name_set( p_sys->session, GNUTLS_NAME_DNS, psz_hostname,
strlen( psz_hostname ) ); strlen( psz_hostname ) );
if( get_Bool( p_session, "tls-check-hostname" ) )
{
p_sys->psz_hostname = strdup( psz_hostname );
if( p_sys->psz_hostname == NULL )
{
p_session->pf_close( p_session );
return -1;
}
}
}
return p_session->pf_handshake2( p_session ); return p_session->pf_handshake2( p_session );
} }
...@@ -330,6 +389,9 @@ gnutls_SessionClose( tls_session_t *p_session ) ...@@ -330,6 +389,9 @@ gnutls_SessionClose( tls_session_t *p_session )
gnutls_bye( p_sys->session, GNUTLS_SHUT_WR ); gnutls_bye( p_sys->session, GNUTLS_SHUT_WR );
gnutls_deinit( p_sys->session ); gnutls_deinit( p_sys->session );
if( p_sys->psz_hostname != NULL )
free( p_sys->psz_hostname );
vlc_object_detach( p_session ); vlc_object_detach( p_session );
vlc_object_destroy( p_session ); vlc_object_destroy( p_session );
...@@ -470,17 +532,18 @@ gnutls_ClientCreate( tls_t *p_tls ) ...@@ -470,17 +532,18 @@ gnutls_ClientCreate( tls_t *p_tls )
psz_homedir = p_tls->p_vlc->psz_homedir; psz_homedir = p_tls->p_vlc->psz_homedir;
psz_path = (char *)malloc( strlen( psz_homedir ) psz_path = (char *)malloc( strlen( psz_homedir )
+ sizeof( CONFIG_DIR ) + 5 ); + sizeof( CONFIG_DIR ) + 12 );
if( psz_path == NULL ) if( psz_path == NULL )
{ {
gnutls_certificate_free_credentials( p_sys->x509_cred ); gnutls_certificate_free_credentials( p_sys->x509_cred );
goto error; goto error;
} }
sprintf( psz_path, "%s/"CONFIG_DIR"/ssl", psz_homedir ); sprintf( psz_path, "%s/"CONFIG_DIR"/ssl/certs", psz_homedir );
gnutls_AddCADirectory( (vlc_object_t *)p_session, p_sys->x509_cred, gnutls_AddCADirectory( (vlc_object_t *)p_session, p_sys->x509_cred,
psz_path ); psz_path );
free( psz_path );
p_session->pf_handshake2 = gnutls_HandshakeAndValidate; p_session->pf_handshake2 = gnutls_HandshakeAndValidate;
} }
else else
......
...@@ -27,12 +27,6 @@ ...@@ -27,12 +27,6 @@
#include "vlc_tls.h" #include "vlc_tls.h"
/*
* TODO:
* - server-side client cert validation,
* - client-side server cert validation (?).
*/
/***************************************************************************** /*****************************************************************************
* tls_ServerCreate: * tls_ServerCreate:
***************************************************************************** *****************************************************************************
......
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