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

Big cleanup of TLS interface

parent 378456a6
......@@ -344,10 +344,6 @@ typedef int (*httpd_handler_callback_t)( httpd_handler_sys_t *, httpd_handler_t
typedef struct httpd_redirect_t httpd_redirect_t;
typedef struct httpd_stream_t httpd_stream_t;
/* TLS support */
typedef struct tls_server_t tls_server_t;
typedef struct tls_session_t tls_session_t;
/* Hashing */
typedef struct md5_s md5_t;
......
......@@ -146,8 +146,8 @@ VLC_API int net_SetCSCov( int fd, int sendcov, int recvcov );
struct virtual_socket_t
{
void *p_sys;
int (*pf_recv) ( void *, void *, int );
int (*pf_send) ( void *, const void *, int );
int (*pf_recv) ( void *, void *, size_t );
int (*pf_send) ( void *, const void *, size_t );
};
VLC_API ssize_t net_Read( vlc_object_t *p_this, int fd, const v_socket_t *, void *p_data, size_t i_data, bool b_retry );
......
/*****************************************************************************
* tls.c: Transport Layer Security API
* vlc_tls.h: Transport Layer Security API
*****************************************************************************
* Copyright (C) 2004-2007 the VideoLAN team
* $Id$
*
* Authors: Rémi Denis-Courmont <rem # videolan.org>
* Copyright (C) 2004-2011 Rémi Denis-Courmont
* Copyright (C) 2005-2006 the VideoLAN team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -31,52 +29,56 @@
# include <vlc_network.h>
typedef struct tls_server_sys_t tls_server_sys_t;
typedef struct vlc_tls_sys vlc_tls_sys_t;
struct tls_server_t
typedef struct vlc_tls
{
VLC_COMMON_MEMBERS
module_t *p_module;
tls_server_sys_t *p_sys;
union {
module_t *module; /**< Plugin handle (client) */
void (*close) (struct vlc_tls *); /**< Close callback (server) */
} u;
vlc_tls_sys_t *sys;
int (*pf_add_CA) ( tls_server_t *, const char * );
int (*pf_add_CRL) ( tls_server_t *, const char * );
struct virtual_socket_t sock;
int (*handshake) (struct vlc_tls *);
} vlc_tls_t;
tls_session_t * (*pf_open) ( tls_server_t * );
void (*pf_close) ( tls_server_t *, tls_session_t * );
};
VLC_API vlc_tls_t *vlc_tls_ClientCreate (vlc_object_t *, int fd,
const char *hostname);
VLC_API void vlc_tls_ClientDelete (vlc_tls_t *);
typedef struct tls_session_sys_t tls_session_sys_t;
/* NOTE: It is assumed that a->sock.p_sys = a */
# define tls_Send( a, b, c ) (((vlc_tls_t *)a)->sock.pf_send (a, b, c))
struct tls_session_t
{
VLC_COMMON_MEMBERS
# define tls_Recv( a, b, c ) (((vlc_tls_t *)a)->sock.pf_recv (a, b, c))
module_t *p_module;
tls_session_sys_t *p_sys;
struct virtual_socket_t sock;
void (*pf_set_fd) ( tls_session_t *, int );
int (*pf_handshake) ( tls_session_t * );
};
typedef struct vlc_tls_creds_sys vlc_tls_creds_sys_t;
/** TLS (server-side) credentials */
typedef struct vlc_tls_creds
{
VLC_COMMON_MEMBERS
tls_server_t *tls_ServerCreate (vlc_object_t *, const char *, const char *);
void tls_ServerDelete (tls_server_t *);
int tls_ServerAddCA (tls_server_t *srv, const char *path);
int tls_ServerAddCRL (tls_server_t *srv, const char *path);
module_t *module;
vlc_tls_creds_sys_t *sys;
tls_session_t *tls_ServerSessionCreate (tls_server_t *, int fd);
int tls_ServerSessionHandshake (tls_session_t *);
void tls_ServerSessionDelete (tls_session_t *);
int (*add_CA) (struct vlc_tls_creds *, const char *path);
int (*add_CRL) (struct vlc_tls_creds *, const char *path);
VLC_API tls_session_t * tls_ClientCreate( vlc_object_t *, int, const char * );
VLC_API void tls_ClientDelete( tls_session_t * );
vlc_tls_t *(*open) (struct vlc_tls_creds *, int fd);
} vlc_tls_creds_t;
/* NOTE: It is assumed that a->sock.p_sys = a */
# define tls_Send( a, b, c ) (((tls_session_t *)a)->sock.pf_send (a, b, c ))
vlc_tls_creds_t *vlc_tls_ServerCreate (vlc_object_t *,
const char *cert, const char *key);
void vlc_tls_ServerDelete (vlc_tls_creds_t *);
int vlc_tls_ServerAddCA (vlc_tls_creds_t *srv, const char *path);
int vlc_tls_ServerAddCRL (vlc_tls_creds_t *srv, const char *path);
# define tls_Recv( a, b, c ) (((tls_session_t *)a)->sock.pf_recv (a, b, c ))
vlc_tls_t *vlc_tls_ServerSessionCreate (vlc_tls_creds_t *, int fd);
int vlc_tls_ServerSessionHandshake (vlc_tls_t *);
void vlc_tls_ServerSessionDelete (vlc_tls_t *);
#endif
......@@ -142,8 +142,8 @@ struct access_sys_t
{
int fd;
bool b_error;
tls_session_t *p_tls;
v_socket_t *p_vs;
vlc_tls_t *p_tls;
v_socket_t *p_vs;
/* From uri */
vlc_url_t url;
......@@ -1195,8 +1195,8 @@ static int Connect( access_t *p_access, uint64_t i_tell )
}
/* TLS/SSL handshake */
p_sys->p_tls = tls_ClientCreate( VLC_OBJECT(p_access), p_sys->fd,
p_sys->url.psz_host );
p_sys->p_tls = vlc_tls_ClientCreate( VLC_OBJECT(p_access), p_sys->fd,
p_sys->url.psz_host );
if( p_sys->p_tls == NULL )
{
msg_Err( p_access, "cannot establish HTTP/TLS session" );
......@@ -1621,7 +1621,7 @@ static void Disconnect( access_t *p_access )
if( p_sys->p_tls != NULL)
{
tls_ClientDelete( p_sys->p_tls );
vlc_tls_ClientDelete( p_sys->p_tls );
p_sys->p_tls = NULL;
p_sys->p_vs = NULL;
}
......
This diff is collapsed.
......@@ -436,8 +436,8 @@ subpicture_Update
subpicture_region_ChainDelete
subpicture_region_Delete
subpicture_region_New
tls_ClientCreate
tls_ClientDelete
vlc_tls_ClientCreate
vlc_tls_ClientDelete
ToCharset
ToLocale
ToLocaleDup
......
......@@ -108,7 +108,7 @@ struct httpd_host_t
httpd_client_t **client;
/* TLS data */
tls_server_t *p_tls;
vlc_tls_creds_t *p_tls;
};
......@@ -180,7 +180,7 @@ struct httpd_client_t
httpd_message_t answer; /* httpd -> client */
/* TLS data */
tls_session_t *p_tls;
vlc_tls_t *p_tls;
};
......@@ -982,7 +982,7 @@ httpd_host_t *httpd_TLSHostNew( vlc_object_t *p_this, const char *psz_hostname,
{
httpd_t *httpd;
httpd_host_t *host;
tls_server_t *p_tls;
vlc_tls_creds_t *p_tls;
char *psz_host;
int i;
......@@ -1043,20 +1043,20 @@ httpd_host_t *httpd_TLSHostNew( vlc_object_t *p_this, const char *psz_hostname,
/* determine TLS configuration */
if ( psz_cert != NULL )
{
p_tls = tls_ServerCreate( p_this, psz_cert, psz_key );
p_tls = vlc_tls_ServerCreate( p_this, psz_cert, psz_key );
if ( p_tls == NULL )
{
msg_Err( p_this, "TLS initialization error" );
goto error;
}
if ( ( psz_ca != NULL) && tls_ServerAddCA( p_tls, psz_ca ) )
if ( ( psz_ca != NULL) && vlc_tls_ServerAddCA( p_tls, psz_ca ) )
{
msg_Err( p_this, "TLS CA error" );
goto error;
}
if ( ( psz_crl != NULL) && tls_ServerAddCRL( p_tls, psz_crl ) )
if ( ( psz_crl != NULL) && vlc_tls_ServerAddCRL( p_tls, psz_crl ) )
{
msg_Err( p_this, "TLS CRL error" );
goto error;
......@@ -1132,7 +1132,7 @@ error:
}
if( p_tls != NULL )
tls_ServerDelete( p_tls );
vlc_tls_ServerDelete( p_tls );
return NULL;
}
......@@ -1184,7 +1184,7 @@ void httpd_HostDelete( httpd_host_t *host )
}
if( host->p_tls != NULL)
tls_ServerDelete( host->p_tls );
vlc_tls_ServerDelete( host->p_tls );
net_ListenClose( host->fds );
free( host->psz_hostname );
......@@ -1429,7 +1429,7 @@ static void httpd_ClientClean( httpd_client_t *cl )
if( cl->fd >= 0 )
{
if( cl->p_tls != NULL )
tls_ServerSessionDelete( cl->p_tls );
vlc_tls_ServerSessionDelete( cl->p_tls );
net_Close( cl->fd );
cl->fd = -1;
}
......@@ -1441,7 +1441,7 @@ static void httpd_ClientClean( httpd_client_t *cl )
cl->p_buffer = NULL;
}
static httpd_client_t *httpd_ClientNew( int fd, tls_session_t *p_tls, mtime_t now )
static httpd_client_t *httpd_ClientNew( int fd, vlc_tls_t *p_tls, mtime_t now )
{
httpd_client_t *cl = malloc( sizeof( httpd_client_t ) );
......@@ -1460,7 +1460,7 @@ static httpd_client_t *httpd_ClientNew( int fd, tls_session_t *p_tls, mtime_t no
static
ssize_t httpd_NetRecv (httpd_client_t *cl, uint8_t *p, size_t i_len)
{
tls_session_t *p_tls;
vlc_tls_t *p_tls;
ssize_t val;
p_tls = cl->p_tls;
......@@ -1474,7 +1474,7 @@ ssize_t httpd_NetRecv (httpd_client_t *cl, uint8_t *p, size_t i_len)
static
ssize_t httpd_NetSend (httpd_client_t *cl, const uint8_t *p, size_t i_len)
{
tls_session_t *p_tls;
vlc_tls_t *p_tls;
ssize_t val;
p_tls = cl->p_tls;
......@@ -2015,7 +2015,7 @@ static void httpd_ClientSend( httpd_client_t *cl )
static void httpd_ClientTlsHsIn( httpd_client_t *cl )
{
switch( tls_ServerSessionHandshake( cl->p_tls ) )
switch( vlc_tls_ServerSessionHandshake( cl->p_tls ) )
{
case 0:
cl->i_state = HTTPD_CLIENT_RECEIVING;
......@@ -2033,7 +2033,7 @@ static void httpd_ClientTlsHsIn( httpd_client_t *cl )
static void httpd_ClientTlsHsOut( httpd_client_t *cl )
{
switch( tls_ServerSessionHandshake( cl->p_tls ) )
switch( vlc_tls_ServerSessionHandshake( cl->p_tls ) )
{
case 0:
cl->i_state = HTTPD_CLIENT_RECEIVING;
......@@ -2533,12 +2533,12 @@ static void* httpd_HostThread( void *data )
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
&(int){ 1 }, sizeof(int));
tls_session_t *p_tls;
vlc_tls_t *p_tls;
if( host->p_tls != NULL )
{
p_tls = tls_ServerSessionCreate( host->p_tls, fd );
switch( tls_ServerSessionHandshake( p_tls ) )
p_tls = vlc_tls_ServerSessionCreate( host->p_tls, fd );
switch( vlc_tls_ServerSessionHandshake( p_tls ) )
{
case -1:
msg_Err( host, "Rejecting TLS connection" );
......
......@@ -46,14 +46,12 @@
*
* @return NULL on error.
*/
tls_server_t *
tls_ServerCreate (vlc_object_t *obj, const char *cert_path,
const char *key_path)
vlc_tls_creds_t *
vlc_tls_ServerCreate (vlc_object_t *obj, const char *cert_path,
const char *key_path)
{
tls_server_t *srv;
srv = (tls_server_t *)vlc_custom_create (obj, sizeof (*srv), "tls server");
if (srv == NULL)
vlc_tls_creds_t *srv = vlc_custom_create (obj, sizeof (*srv), "tls creds");
if (unlikely(srv == NULL))
return NULL;
var_Create (srv, "tls-x509-cert", VLC_VAR_STRING);
......@@ -68,8 +66,8 @@ tls_ServerCreate (vlc_object_t *obj, const char *cert_path,
var_SetString (srv, "tls-x509-key", key_path);
}
srv->p_module = module_need (srv, "tls server", NULL, false );
if (srv->p_module == NULL)
srv->module = module_need (srv, "tls server", NULL, false );
if (srv->module == NULL)
{
msg_Err (srv, "TLS server plugin not available");
vlc_object_release (srv);
......@@ -82,15 +80,15 @@ tls_ServerCreate (vlc_object_t *obj, const char *cert_path,
/**
* Releases data allocated with tls_ServerCreate.
* Releases data allocated with vlc_tls_ServerCreate().
* @param srv TLS server object to be destroyed, or NULL
*/
void tls_ServerDelete (tls_server_t *srv)
void vlc_tls_ServerDelete (vlc_tls_creds_t *srv)
{
if (srv == NULL)
return;
module_unneed (srv, srv->p_module);
module_unneed (srv, srv->module);
vlc_object_release (srv);
}
......@@ -99,9 +97,9 @@ void tls_ServerDelete (tls_server_t *srv)
* Adds one or more certificate authorities from a file.
* @return -1 on error, 0 on success.
*/
int tls_ServerAddCA (tls_server_t *srv, const char *path)
int vlc_tls_ServerAddCA (vlc_tls_creds_t *srv, const char *path)
{
return srv->pf_add_CA (srv, path);
return srv->add_CA (srv, path);
}
......@@ -109,37 +107,54 @@ int tls_ServerAddCA (tls_server_t *srv, const char *path)
* Adds one or more certificate revocation list from a file.
* @return -1 on error, 0 on success.
*/
int tls_ServerAddCRL (tls_server_t *srv, const char *path)
int vlc_tls_ServerAddCRL (vlc_tls_creds_t *srv, const char *path)
{
return srv->pf_add_CRL (srv, path);
return srv->add_CRL (srv, path);
}
tls_session_t *tls_ServerSessionCreate (tls_server_t *srv, int fd)
vlc_tls_t *vlc_tls_ServerSessionCreate (vlc_tls_creds_t *srv, int fd)
{
tls_session_t *ses = srv->pf_open (srv);
if (ses != NULL)
ses->pf_set_fd (ses, fd);
return ses;
return srv->open (srv, fd);
}
void tls_ServerSessionDelete (tls_session_t *ses)
void vlc_tls_ServerSessionDelete (vlc_tls_t *ses)
{
tls_server_t *srv = (tls_server_t *)(ses->p_parent);
srv->pf_close (srv, ses);
ses->u.close (ses);
}
int tls_ServerSessionHandshake (tls_session_t *ses)
int vlc_tls_ServerSessionHandshake (vlc_tls_t *ses)
{
int val = ses->pf_handshake (ses);
int val = ses->handshake (ses);
if (val < 0)
tls_ServerSessionDelete (ses);
vlc_tls_ServerSessionDelete (ses);
return val;
}
/*** TLS client session ***/
/* TODO: cache certificates for the whole VLC instance lifetime */
static int tls_client_start(void *func, va_list ap)
{
int (*activate) (vlc_tls_t *, int fd, const char *hostname) = func;
vlc_tls_t *session = va_arg (ap, vlc_tls_t *);
int fd = va_arg (ap, int);
const char *hostname = va_arg (ap, const char *);
return activate (session, fd, hostname);
}
static void tls_client_stop(void *func, va_list ap)
{
void (*deactivate) (vlc_tls_t *) = func;
vlc_tls_t *session = va_arg (ap, vlc_tls_t *);
deactivate (session);
}
/**
* Allocates a client's TLS credentials and shakes hands through the network.
* This is a blocking network operation.
......@@ -150,61 +165,49 @@ int tls_ServerSessionHandshake (tls_session_t *ses)
*
* @return NULL on error.
**/
tls_session_t *
tls_ClientCreate (vlc_object_t *obj, int fd, const char *psz_hostname)
vlc_tls_t *
vlc_tls_ClientCreate (vlc_object_t *obj, int fd, const char *hostname)
{
tls_session_t *cl;
int val;
cl = (tls_session_t *)vlc_custom_create (obj, sizeof (*cl), "tls client");
if (cl == NULL)
vlc_tls_t *cl = vlc_custom_create (obj, sizeof (*cl), "tls client");
if (unlikely(cl == NULL))
return NULL;
var_Create (cl, "tls-server-name", VLC_VAR_STRING);
if (psz_hostname != NULL)
{
msg_Dbg (cl, "requested server name: %s", psz_hostname);
var_SetString (cl, "tls-server-name", psz_hostname);
}
else
msg_Dbg (cl, "requested anonymous server");
cl->p_module = module_need (cl, "tls client", NULL, false );
if (cl->p_module == NULL)
cl->u.module = vlc_module_load (cl, "tls client", NULL, false,
tls_client_start, cl, fd, hostname);
if (cl->u.module == NULL)
{
msg_Err (cl, "TLS client plugin not available");
vlc_object_release (cl);
return NULL;
}
cl->pf_set_fd (cl, fd);
/* TODO: do this directly in the TLS plugin */
int val;
do
val = cl->pf_handshake (cl);
val = cl->handshake (cl);
while (val > 0);
if (val == 0)
if (val != 0)
{
msg_Dbg (cl, "TLS client session initialized");
return cl;
msg_Err (cl, "TLS client session handshake error");
vlc_module_unload (cl->u.module, tls_client_stop, cl);
vlc_object_release (cl);
return NULL;
}
msg_Err (cl, "TLS client session handshake error");
module_unneed (cl, cl->p_module);
vlc_object_release (cl);
return NULL;
msg_Dbg (cl, "TLS client session initialized");
return cl;
}
/**
* Releases data allocated with tls_ClientCreate.
* Releases data allocated with vlc_tls_ClientCreate().
* It is your job to close the underlying socket.
*/
void tls_ClientDelete (tls_session_t *cl)
void vlc_tls_ClientDelete (vlc_tls_t *cl)
{
if (cl == NULL)
return;
module_unneed (cl, cl->p_module);
vlc_module_unload (cl->u.module, tls_client_stop, cl);
vlc_object_release (cl);
}
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