1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 VideoLAN
5 * $Id: httpd.c 8263 2004-07-24 09:06:58Z courmisch $
7 * Authors: Remi Denis-Courmont <courmisch@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
34 * - libgcrypt thread-safety !!!
36 * - gnutls version check,
37 * - client side stuff,
38 * - server-side client cert validation,
39 * - client-side server cert validation (?).
42 /* FIXME: proper configure check */
43 //#define HAVE_GNUTLS 1
46 # include <gnutls/gnutls.h>
53 gnutls_certificate_credentials x509_cred;
54 gnutls_dh_params dh_params;
60 gnutls_session session;
64 /* FIXME: is this legal in the VLC? */
65 unsigned i_servernum = 0;
69 tls_Init( vlc_object_t *p_this )
73 var_Create( p_this->p_libvlc, "tls_mutex", VLC_VAR_MUTEX );
74 var_Get( p_this->p_libvlc, "tls_mutex", &lock );
75 vlc_mutex_lock( lock.p_address );
77 /* Initialize GnuTLS only once */
78 /* FIXME: should check version number */
81 if( gnutls_global_init( ) )
83 msg_Warn( p_this, "cannot initialize GNUTLS" );
84 vlc_mutex_unlock( lock.p_address);
87 msg_Dbg( p_this, "GNUTLS initialized" );
91 vlc_mutex_unlock( lock.p_address );
98 tls_CleanUp( vlc_object_t *p_this )
102 var_Create( p_this->p_libvlc, "tls_mutex", VLC_VAR_MUTEX );
103 var_Get( p_this->p_libvlc, "tls_mutex", &lock );
104 vlc_mutex_lock( lock.p_address );
107 if( i_servernum == 0 )
109 gnutls_global_deinit( );
110 msg_Dbg( p_this, "GNUTLS deinitialized" );
113 vlc_mutex_unlock( lock.p_address);
119 /*****************************************************************************
121 *****************************************************************************
122 * Allocates a whole server's TLS credentials.
123 * Returns NULL on error.
124 *****************************************************************************/
126 tls_ServerCreate( vlc_object_t *p_this, const char *psz_cert_path,
127 const char *psz_key_path )
130 tls_server_t *p_server;
133 msg_Dbg( p_this, "Creating TLS server" );
134 if( tls_Init( p_this ) )
137 p_server = (tls_server_t *)malloc( sizeof(struct tls_server_t) );
139 /* FIXME: do not hard-code PEM file paths */
140 /* Sets server's credentials */
141 val = gnutls_certificate_allocate_credentials( &p_server->x509_cred );
144 msg_Err( p_this, "Cannot allocate X509 credentials : %s",
145 gnutls_strerror( val ) );
150 val = gnutls_certificate_set_x509_key_file( p_server->x509_cred,
151 psz_cert_path, psz_key_path,
152 GNUTLS_X509_FMT_PEM );
155 msg_Err( p_this, "Cannot set certificate chain or private key : %s",
156 gnutls_strerror( val ) );
157 gnutls_certificate_free_credentials( p_server->x509_cred );
162 /* FIXME: regenerate these regularly */
163 val = gnutls_dh_params_init( &p_server->dh_params );
166 msg_Dbg( p_this, "Computing Diffie Hellman ciphers parameters" );
167 val = gnutls_dh_params_generate2( p_server->dh_params, DH_BITS );
171 msg_Err( p_this, "Cannot initialize DH cipher suites : %s",
172 gnutls_strerror( val ) );
173 gnutls_certificate_free_credentials( p_server->x509_cred );
177 msg_Dbg( p_this, "Ciphers parameters computed" );
179 gnutls_certificate_set_dh_params( p_server->x509_cred,
180 p_server->dh_params);
182 p_server->p_this = p_this;
190 /*****************************************************************************
192 *****************************************************************************
193 * Adds one or more certificate authorities.
194 * TODO: we are not able to check the client credentials yet, so this function
196 * Returns -1 on error, 0 on success.
197 *****************************************************************************/
199 tls_ServerAddCA( tls_server_t *p_server, const char *psz_ca_path )
204 assert( p_server != NULL);
205 val = gnutls_certificate_set_x509_trust_file( p_server->x509_cred,
207 GNUTLS_X509_FMT_PEM );
210 msg_Err( p_server->p_this, "Cannot add trusted CA (%s) : %s",
211 psz_ca_path, gnutls_strerror( val ) );
215 msg_Dbg( p_server->p_this, " %d trusted CA added (%s)", val,
224 /*****************************************************************************
226 *****************************************************************************
227 * Adds a certificates revocation list to be sent to TLS clients.
228 * Returns -1 on error, 0 on success.
229 *****************************************************************************/
231 tls_ServerAddCRL( tls_server_t *p_server, const char *psz_crl_path )
236 val = gnutls_certificate_set_x509_crl_file( p_server->x509_cred,
238 GNUTLS_X509_FMT_PEM );
241 msg_Err( p_server->p_this, "Cannot add CRL (%s) : %s",
242 psz_crl_path, gnutls_strerror( val ) );
246 msg_Dbg( p_server->p_this, "%d CRL added (%s)", val, psz_crl_path );
255 /*****************************************************************************
257 *****************************************************************************
258 * Releases data allocated with tls_ServerCreate
259 *****************************************************************************/
261 tls_ServerDelete( tls_server_t *p_server )
263 assert( p_server != NULL );
266 gnutls_certificate_free_credentials( p_server->x509_cred );
267 tls_CleanUp( p_server->p_this );
273 /*****************************************************************************
274 * tls_ServerSessionPrepare:
275 *****************************************************************************
276 * Initializes a server-side TLS session data
277 *****************************************************************************/
279 tls_ServerSessionPrepare( const tls_server_t *p_server )
282 tls_session_t *p_session;
283 gnutls_session session;
286 assert( p_server != NULL );
288 val = gnutls_init( &session, GNUTLS_SERVER );
291 msg_Err( p_server->p_this, "Cannot initialize TLS session : %s",
292 gnutls_strerror( val ) );
296 val = gnutls_set_default_priority( session );
299 msg_Err( p_server->p_this, "Cannot set ciphers priorities : %s",
300 gnutls_strerror( val ) );
301 gnutls_deinit( session );
305 val = gnutls_credentials_set( session, GNUTLS_CRD_CERTIFICATE,
306 p_server->x509_cred );
309 msg_Err( p_server->p_this, "Cannot set TLS session credentials : %s",
310 gnutls_strerror( val ) );
311 gnutls_deinit( session );
315 /* TODO: support for client authentication */
316 /*gnutls_certificate_server_set_request( p_session->session,
317 GNUTLS_CERT_REQUEST ); */
319 gnutls_dh_set_prime_bits( session, DH_BITS );
321 p_session = malloc( sizeof (struct tls_session_t) );
322 p_session->session = session;
323 p_session->p_this = p_server->p_this;
332 /*****************************************************************************
333 * tls_SessionHandshake:
334 *****************************************************************************
335 * Establishes TLS session with a peer through socket <fd>
336 * Returns NULL on error (do NOT call tls_SessionClose in case of error or
337 * re-use the session structure).
338 *****************************************************************************/
340 tls_SessionHandshake( tls_session_t *p_session, int fd )
345 assert( p_session != NULL );
347 gnutls_transport_set_ptr( p_session->session, (gnutls_transport_ptr)fd);
348 val = gnutls_handshake( p_session->session);
351 gnutls_deinit( p_session->session );
352 msg_Err( p_session->p_this, "TLS handshake failed : %s",
353 gnutls_strerror( val ) );
364 /*****************************************************************************
366 *****************************************************************************
367 * Terminates a TLS session and releases session data.
368 *****************************************************************************/
370 tls_SessionClose( tls_session_t *p_session )
372 assert( p_session != NULL );
375 gnutls_bye( p_session->session, GNUTLS_SHUT_WR );
376 gnutls_deinit (p_session->session );
382 /*****************************************************************************
384 *****************************************************************************
385 * Sends data through a TLS session.
386 *****************************************************************************/
388 tls_Send( tls_session_t *p_session, const char *buf, int i_length )
393 assert( p_session != NULL );
395 val = gnutls_record_send( p_session->session, buf, i_length );
398 /*msg_Warn( p_session->p_this, "TLS problem : %s",
399 gnutls_strerror( val ) );*/
409 /*****************************************************************************
411 *****************************************************************************
412 * Receives data through a TLS session
413 *****************************************************************************/
415 tls_Recv( tls_session_t *p_session, char *buf, int i_length )
420 assert( p_session != NULL );
422 val = gnutls_record_recv( p_session->session, buf, i_length );
425 /*msg_Warn( p_session->p_this, "TLS problem : %s",
426 gnutls_strerror( val ) );*/