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

tls: pass host name to handshake function, simplify

parent 75ffd9ea
...@@ -42,13 +42,13 @@ struct vlc_tls ...@@ -42,13 +42,13 @@ struct vlc_tls
vlc_tls_sys_t *sys; vlc_tls_sys_t *sys;
struct virtual_socket_t sock; struct virtual_socket_t sock;
int (*handshake) (struct vlc_tls *); int (*handshake) (vlc_tls_t *, const char *host);
}; };
VLC_API vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *, int fd, VLC_API vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *, int fd,
const char *host); const char *host);
vlc_tls_t *vlc_tls_ServerSessionCreate (vlc_tls_creds_t *, int fd); vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *, int fd, const char *host);
int vlc_tls_SessionHandshake (vlc_tls_t *); int vlc_tls_SessionHandshake (vlc_tls_t *, const char *host);
VLC_API void vlc_tls_SessionDelete (vlc_tls_t *); VLC_API void vlc_tls_SessionDelete (vlc_tls_t *);
/* NOTE: It is assumed that a->sock.p_sys = a */ /* NOTE: It is assumed that a->sock.p_sys = a */
......
...@@ -176,7 +176,6 @@ static int gnutls_Error (vlc_object_t *obj, int val) ...@@ -176,7 +176,6 @@ static int gnutls_Error (vlc_object_t *obj, int val)
struct vlc_tls_sys struct vlc_tls_sys
{ {
gnutls_session_t session; gnutls_session_t session;
char *hostname; /* XXX: client only */
bool handshaked; bool handshaked;
}; };
...@@ -214,7 +213,7 @@ static int gnutls_Recv (void *opaque, void *buf, size_t length) ...@@ -214,7 +213,7 @@ static int gnutls_Recv (void *opaque, void *buf, size_t length)
* 1 if more would-be blocking recv is needed, * 1 if more would-be blocking recv is needed,
* 2 if more would-be blocking send is required. * 2 if more would-be blocking send is required.
*/ */
static int gnutls_ContinueHandshake (vlc_tls_t *session) static int gnutls_ContinueHandshake (vlc_tls_t *session, const char *host)
{ {
vlc_tls_sys_t *sys = session->sys; vlc_tls_sys_t *sys = session->sys;
int val; int val;
...@@ -236,6 +235,7 @@ static int gnutls_ContinueHandshake (vlc_tls_t *session) ...@@ -236,6 +235,7 @@ static int gnutls_ContinueHandshake (vlc_tls_t *session)
} }
sys->handshaked = true; sys->handshaked = true;
(void) host;
return 0; return 0;
} }
...@@ -263,11 +263,11 @@ static struct ...@@ -263,11 +263,11 @@ static struct
}; };
static int gnutls_HandshakeAndValidate (vlc_tls_t *session) static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host)
{ {
vlc_tls_sys_t *sys = session->sys; vlc_tls_sys_t *sys = session->sys;
int val = gnutls_ContinueHandshake (session); int val = gnutls_ContinueHandshake (session, host);
if (val) if (val)
return val; return val;
...@@ -322,15 +322,13 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session) ...@@ -322,15 +322,13 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session)
goto error; goto error;
} }
if (sys->hostname != NULL if (host != NULL && !gnutls_x509_crt_check_hostname (cert, host))
&& !gnutls_x509_crt_check_hostname (cert, sys->hostname))
{ {
msg_Err (session, "Certificate does not match \"%s\"", sys->hostname); msg_Err (session, "Certificate does not match \"%s\"", host);
goto error; goto error;
} }
gnutls_x509_crt_deinit (cert); gnutls_x509_crt_deinit (cert);
msg_Dbg (session, "TLS/X.509 certificate verified");
return 0; return 0;
error: error:
...@@ -367,7 +365,7 @@ struct vlc_tls_creds_sys ...@@ -367,7 +365,7 @@ struct vlc_tls_creds_sys
{ {
gnutls_certificate_credentials_t x509_cred; gnutls_certificate_credentials_t x509_cred;
gnutls_dh_params_t dh_params; /* XXX: used for server only */ gnutls_dh_params_t dh_params; /* XXX: used for server only */
int (*handshake) (vlc_tls_t *); /* XXX: useful for server only */ int (*handshake) (vlc_tls_t *, const char *); /* XXX: useful for server only */
}; };
...@@ -383,7 +381,6 @@ static void gnutls_SessionClose (vlc_tls_creds_t *crd, vlc_tls_t *session) ...@@ -383,7 +381,6 @@ static void gnutls_SessionClose (vlc_tls_creds_t *crd, vlc_tls_t *session)
gnutls_bye (sys->session, GNUTLS_SHUT_WR); gnutls_bye (sys->session, GNUTLS_SHUT_WR);
gnutls_deinit (sys->session); gnutls_deinit (sys->session);
free (sys->hostname);
free (sys); free (sys);
(void) crd; (void) crd;
} }
...@@ -405,7 +402,6 @@ static int gnutls_SessionOpen (vlc_tls_creds_t *crd, vlc_tls_t *session, ...@@ -405,7 +402,6 @@ static int gnutls_SessionOpen (vlc_tls_creds_t *crd, vlc_tls_t *session,
session->sock.pf_recv = gnutls_Recv; session->sock.pf_recv = gnutls_Recv;
session->handshake = crd->sys->handshake; session->handshake = crd->sys->handshake;
sys->handshaked = false; sys->handshaked = false;
sys->hostname = NULL;
int val = gnutls_init (&sys->session, type); int val = gnutls_init (&sys->session, type);
if (val != 0) if (val != 0)
...@@ -463,22 +459,12 @@ static int gnutls_ClientSessionOpen (vlc_tls_creds_t *crd, vlc_tls_t *session, ...@@ -463,22 +459,12 @@ static int gnutls_ClientSessionOpen (vlc_tls_creds_t *crd, vlc_tls_t *session,
/* minimum DH prime bits */ /* minimum DH prime bits */
gnutls_dh_set_prime_bits (sys->session, 1024); gnutls_dh_set_prime_bits (sys->session, 1024);
/* server name */
if (likely(hostname != NULL)) if (likely(hostname != NULL))
{
/* fill Server Name Indication */ /* fill Server Name Indication */
gnutls_server_name_set (sys->session, GNUTLS_NAME_DNS, gnutls_server_name_set (sys->session, GNUTLS_NAME_DNS,
hostname, strlen (hostname)); hostname, strlen (hostname));
/* keep hostname to match CNAME after handshake */
sys->hostname = strdup (hostname);
if (unlikely(sys->hostname == NULL))
goto error;
}
return VLC_SUCCESS; return VLC_SUCCESS;
error:
gnutls_SessionClose (crd, session);
return VLC_EGENERIC;
} }
......
...@@ -1880,7 +1880,7 @@ static void httpd_ClientSend( httpd_client_t *cl ) ...@@ -1880,7 +1880,7 @@ static void httpd_ClientSend( httpd_client_t *cl )
static void httpd_ClientTlsHandshake( httpd_client_t *cl ) static void httpd_ClientTlsHandshake( httpd_client_t *cl )
{ {
switch( vlc_tls_SessionHandshake( cl->p_tls ) ) switch( vlc_tls_SessionHandshake( cl->p_tls, NULL ) )
{ {
case 0: case 0:
cl->i_state = HTTPD_CLIENT_RECEIVING; cl->i_state = HTTPD_CLIENT_RECEIVING;
...@@ -2312,7 +2312,7 @@ static void* httpd_HostThread( void *data ) ...@@ -2312,7 +2312,7 @@ static void* httpd_HostThread( void *data )
vlc_tls_t *p_tls; vlc_tls_t *p_tls;
if( host->p_tls != NULL ) if( host->p_tls != NULL )
p_tls = vlc_tls_ServerSessionCreate( host->p_tls, fd ); p_tls = vlc_tls_SessionCreate( host->p_tls, fd, NULL );
else else
p_tls = NULL; p_tls = NULL;
......
...@@ -160,12 +160,12 @@ int vlc_tls_ServerAddCRL (vlc_tls_creds_t *srv, const char *path) ...@@ -160,12 +160,12 @@ int vlc_tls_ServerAddCRL (vlc_tls_creds_t *srv, const char *path)
/*** TLS session ***/ /*** TLS session ***/
static vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *crd, int fd, vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *crd, int fd,
const char *hostname) const char *host)
{ {
vlc_tls_t *session = vlc_custom_create (crd, sizeof (*session), vlc_tls_t *session = vlc_custom_create (crd, sizeof (*session),
"tls session"); "tls session");
int val = crd->open (crd, session, fd, hostname); int val = crd->open (crd, session, fd, host);
if (val == VLC_SUCCESS) if (val == VLC_SUCCESS)
return session; return session;
vlc_object_release (session); vlc_object_release (session);
...@@ -180,38 +180,31 @@ void vlc_tls_SessionDelete (vlc_tls_t *session) ...@@ -180,38 +180,31 @@ void vlc_tls_SessionDelete (vlc_tls_t *session)
vlc_object_release (session); vlc_object_release (session);
} }
vlc_tls_t *vlc_tls_ServerSessionCreate (vlc_tls_creds_t *crd, int fd) int vlc_tls_SessionHandshake (vlc_tls_t *session, const char *host)
{ {
return vlc_tls_SessionCreate (crd, fd, NULL); return session->handshake (session, host);
}
int vlc_tls_SessionHandshake (vlc_tls_t *session)
{
return session->handshake (session);
} }
/** /**
* Performs client side of TLS handshake through a connected socket, and * Performs client side of TLS handshake through a connected socket, and
* establishes a secure channel. This is a blocking network operation. * establishes a secure channel. This is a blocking network operation.
* *
* @param fd stream socket through which to establish the secure communication * @param fd socket through which to establish the secure channel
* layer.
* @param hostname expected server name, used both as Server Name Indication * @param hostname expected server name, used both as Server Name Indication
* and as expected Common Name of the peer's certificate. * and as expected Common Name of the peer certificate
* *
* @return NULL on error. * @return NULL on error.
**/ **/
vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd, vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
const char *hostname) const char *host)
{ {
vlc_tls_t *session = vlc_tls_SessionCreate (crd, fd, hostname); vlc_tls_t *session = vlc_tls_SessionCreate (crd, fd, host);
if (session == NULL) if (session == NULL)
return NULL; return NULL;
/* TODO: do this directly in the TLS plugin */
int val; int val;
do do
val = session->handshake (session); val = vlc_tls_SessionHandshake (session, host);
while (val > 0); while (val > 0);
if (val != 0) if (val != 0)
......
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