int (*pf_add_CA) ( tls_server_t *, const char * );
int (*pf_add_CRL) ( tls_server_t *, const char * );
- tls_session_t * (*pf_session_prepare) ( tls_server_t * );
+ tls_session_t * (*pf_open) ( tls_server_t * );
+ void (*pf_close) ( tls_server_t *, tls_session_t * );
};
typedef struct tls_session_sys_t tls_session_sys_t;
tls_session_sys_t *p_sys;
struct virtual_socket_t sock;
- int (*pf_handshake) ( tls_session_t *, int );
- int (*pf_handshake2) ( tls_session_t * );
- void (*pf_close) ( tls_session_t * );
+ void (*pf_set_fd) ( tls_session_t *, int );
+ int (*pf_handshake) ( tls_session_t * );
};
-/*****************************************************************************
- * tls_ServerCreate:
- *****************************************************************************
- * Allocates a whole server's TLS credentials.
- * Returns NULL on error.
- *****************************************************************************/
-VLC_EXPORT( tls_server_t *, tls_ServerCreate, ( vlc_object_t *, const char *, const char * ) );
-
-/*****************************************************************************
- * tls_ServerAddCA:
- *****************************************************************************
- * Adds one or more certificate authorities.
- * Returns -1 on error, 0 on success.
- *****************************************************************************/
-# define tls_ServerAddCA( a, b ) (((tls_server_t *)a)->pf_add_CA (a, b))
-
-
-/*****************************************************************************
- * tls_ServerAddCRL:
- *****************************************************************************
- * Adds a certificates revocation list to be sent to TLS clients.
- * Returns -1 on error, 0 on success.
- *****************************************************************************/
-# define tls_ServerAddCRL( a, b ) (((tls_server_t *)a)->pf_add_CRL (a, b))
-
-
-VLC_EXPORT( void, tls_ServerDelete, ( tls_server_t * ) );
+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);
-
-# define tls_ServerSessionPrepare( a ) (((tls_server_t *)a)->pf_session_prepare (a))
-# define tls_ServerSessionHandshake( a, b ) (((tls_session_t *)a)->pf_handshake (a, b))
-# define tls_ServerSessionClose( a ) (((tls_session_t *)a)->pf_close (a))
+tls_session_t *tls_ServerSessionPrepare (tls_server_t *);
+int tls_ServerSessionHandshake (tls_session_t *, int fd);
+int tls_SessionContinueHandshake (tls_session_t *);
+void tls_ServerSessionClose (tls_session_t *);
VLC_EXPORT( tls_session_t *, tls_ClientCreate, ( vlc_object_t *, int, const char * ) );
VLC_EXPORT( void, tls_ClientDelete, ( tls_session_t * ) );
-# define tls_ClientSessionHandshake( a, b ) (((tls_session_t *)a)->pf_handshake (a, b))
-
-# define tls_SessionContinueHandshake( a ) (((tls_session_t *)a)->pf_handshake2 (a))
-
-
/* 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 ))
/**
- * @return -1 on error (you need not and must not call tls_SessionClose())
- * 0 on succesful handshake completion, 1 if more would-be blocking recv is
- * needed, 2 if more would-be blocking send is required.
+ * Starts or continues the TLS handshake.
+ *
+ * @return -1 on fatal error, 0 on succesful handshake completion,
+ * 1 if more would-be blocking recv is needed,
+ * 2 if more would-be blocking send is required.
*/
static int
gnutls_ContinueHandshake (tls_session_t *p_session)
#endif
msg_Err( p_session, "TLS handshake error: %s",
gnutls_strerror( val ) );
- p_session->pf_close( p_session );
return -1;
}
{
msg_Err( session, "Certificate verification failed: %s",
gnutls_strerror( val ) );
- goto error;
+ return -1;
}
if( status )
msg_Err( session,
"unknown certificate error (you found a bug in VLC)" );
- goto error;
+ return -1;
}
/* certificate (host)name verification */
if( data == NULL )
{
msg_Err( session, "Peer certificate not available" );
- goto error;
+ return -1;
}
gnutls_x509_crt cert;
if( val )
{
msg_Err( session, "x509 fatal error: %s", gnutls_strerror( val ) );
- goto error;
+ return -1;
}
val = gnutls_x509_crt_import( cert, data, GNUTLS_X509_FMT_DER );
{
msg_Err( session, "Certificate import error: %s",
gnutls_strerror( val ) );
- goto crt_error;
+ goto error;
}
if( p_sys->psz_hostname != NULL )
{
msg_Err( session, "Certificate does not match \"%s\"",
p_sys->psz_hostname );
- goto crt_error;
+ goto error;
}
}
else
if( gnutls_x509_crt_get_expiration_time( cert ) < time( NULL ) )
{
msg_Err( session, "Certificate expired" );
- goto crt_error;
+ goto error;
}
if( gnutls_x509_crt_get_activation_time( cert ) > time ( NULL ) )
{
msg_Err( session, "Certificate not yet valid" );
- goto crt_error;
+ goto error;
}
gnutls_x509_crt_deinit( cert );
msg_Dbg( session, "TLS/x509 certificate verified" );
return 0;
-crt_error:
- gnutls_x509_crt_deinit( cert );
error:
- session->pf_close( session );
+ gnutls_x509_crt_deinit( cert );
return -1;
}
/**
- * Starts negociation of a TLS session.
+ * Sets the operating system file descriptor backend for the TLS sesison.
*
* @param fd stream socket already connected with the peer.
- *
- * @return -1 on error (you need not and must not call tls_SessionClose),
- * 0 on succesful handshake completion, 1 if more would-be blocking recv is
- * needed, 2 if more would-be blocking send is required.
*/
-static int
-gnutls_BeginHandshake( tls_session_t *p_session, int fd )
+static void
+gnutls_SetFD (tls_session_t *p_session, int fd)
{
- tls_session_sys_t *p_sys = p_session->p_sys;
-
- gnutls_transport_set_ptr (p_sys->session, (gnutls_transport_ptr)(intptr_t)fd);
-
- return p_session->pf_handshake2( p_session );
+ gnutls_transport_set_ptr (p_session->p_sys->session,
+ (gnutls_transport_ptr)(intptr_t)fd);
}
typedef int (*tls_prio_func) (gnutls_session_t, const int *);
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_session->pf_set_fd = gnutls_SetFD;
p_sys->session.b_handshaked = VLC_FALSE;
p_sys->session.psz_hostname = NULL;
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;
+ p_session->pf_handshake = gnutls_HandshakeAndValidate;
}
else
- p_session->pf_handshake2 = gnutls_ContinueHandshake;
+ p_session->pf_handshake = gnutls_ContinueHandshake;
sprintf (path, "%s/ssl/private", homedir);
gnutls_Addx509Directory (VLC_OBJECT (p_session), p_sys->x509_cred,
int i_cache_size;
vlc_mutex_t cache_lock;
- int (*pf_handshake2)( tls_session_t * );
+ int (*pf_handshake)( tls_session_t * );
};
* You still have to close the socket yourself.
*/
static void
-gnutls_SessionClose( tls_session_t *p_session )
+gnutls_SessionClose (tls_server_t *p_server, tls_session_t *p_session)
{
tls_session_sys_t *p_sys = p_session->p_sys;
+ (void)p_server;
if( p_sys->b_handshaked == VLC_TRUE )
gnutls_bye( p_sys->session, GNUTLS_SHUT_WR );
return NULL;
}
- vlc_object_attach( p_session, p_server );
-
p_server_sys = p_server->p_sys;
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_handshake2 = p_server_sys->pf_handshake2;
- p_session->pf_close = gnutls_SessionClose;
+ p_session->pf_set_fd = gnutls_SetFD;
+ p_session->pf_handshake = p_server_sys->pf_handshake;
p_session->p_sys->b_handshaked = VLC_FALSE;
p_session->p_sys->psz_hostname = NULL;
goto error;
}
- if( p_session->pf_handshake2 == gnutls_HandshakeAndValidate )
- gnutls_certificate_server_set_request( session, GNUTLS_CERT_REQUIRE );
+ if (p_session->pf_handshake == gnutls_HandshakeAndValidate)
+ gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE);
i_val = config_GetInt (p_server, "gnutls-dh-bits");
gnutls_dh_set_prime_bits (session, i_val);
msg_Dbg( p_server, " %d trusted CA added (%s)", val, psz_ca_path );
/* enables peer's certificate verification */
- p_sys->pf_handshake2 = gnutls_HandshakeAndValidate;
+ p_sys->pf_handshake = gnutls_HandshakeAndValidate;
return VLC_SUCCESS;
}
p_sys->p_store = p_sys->p_cache;
p_server->p_sys = p_sys;
- p_server->pf_add_CA = gnutls_ServerAddCA;
+ p_server->pf_add_CA = gnutls_ServerAddCA;
p_server->pf_add_CRL = gnutls_ServerAddCRL;
- p_server->pf_session_prepare = gnutls_ServerSessionPrepare;
+ p_server->pf_open = gnutls_ServerSessionPrepare;
+ p_server->pf_close = gnutls_SessionClose;
/* No certificate validation by default */
- p_sys->pf_handshake2 = gnutls_ContinueHandshake;
+ p_sys->pf_handshake = gnutls_ContinueHandshake;
vlc_mutex_init( p_server, &p_sys->cache_lock );
}
+/**
+ * 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)
+{
+ return srv->pf_add_CA (srv, 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)
+{
+ return srv->pf_add_CRL (srv, path);
+}
+
+
+tls_session_t *tls_ServerSessionPrepare (tls_server_t *srv)
+{
+ tls_session_t *ses;
+
+ ses = srv->pf_open (srv);
+ if (ses == NULL)
+ return NULL;
+
+ vlc_object_attach (ses, srv);
+ return ses;
+}
+
+
+void tls_ServerSessionClose (tls_session_t *ses)
+{
+ tls_server_t *srv = (tls_server_t *)(ses->p_parent);
+ srv->pf_close (srv, ses);
+}
+
+
+int tls_ServerSessionHandshake (tls_session_t *ses, int fd)
+{
+ ses->pf_set_fd (ses, fd);
+ return 2;
+}
+
+
+int tls_SessionContinueHandshake (tls_session_t *ses)
+{
+ int val = ses->pf_handshake (ses);
+ if (val < 0)
+ tls_ServerSessionClose (ses);
+ return val;
+}
+
+
/**
* Allocates a client's TLS credentials and shakes hands through the network.
* This is a blocking network operation.
tls_ClientCreate (vlc_object_t *obj, int fd, const char *psz_hostname)
{
tls_session_t *cl;
+ int val;
cl = (tls_session_t *)vlc_custom_create (obj, sizeof (*cl),
VLC_OBJECT_GENERIC,
return NULL;
}
- int val = tls_ClientSessionHandshake (cl, fd);
- while (val > 0)
- val = tls_SessionContinueHandshake (cl);
+ cl->pf_set_fd (cl, fd);
+
+ do
+ val = cl->pf_handshake (cl);
+ while (val > 0);
if (val == 0)
{