/***************************************************************************** * tls.c ***************************************************************************** * Copyright © 2004-2007 Rémi Denis-Courmont * $Id$ * * Authors: Rémi Denis-Courmont <rem # videolan.org> * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /** * @file * libvlc interface to the Transport Layer Security (TLS) plugins. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "vlc_common.h" #include "libvlc.h" #include "vlc_tls.h" /** * Allocates a whole server's TLS credentials. * * @param cert_path required (Unicode) path to an x509 certificate, * if NULL, anonymous key exchange will be used. * @param key_path (UTF-8) path to the PKCS private key for the certificate, * if NULL; cert_path will be used. * * @return NULL on error. */ tls_server_t * 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), VLC_OBJECT_GENERIC, "tls server"); if (srv == NULL) return NULL; var_Create (srv, "tls-x509-cert", VLC_VAR_STRING); var_Create (srv, "tls-x509-key", VLC_VAR_STRING); if (cert_path != NULL) { var_SetString (srv, "tls-x509-cert", cert_path); if (key_path == NULL) key_path = cert_path; var_SetString (srv, "tls-x509-key", key_path); } srv->p_module = module_Need (srv, "tls server", 0, 0); if (srv->p_module == NULL) { msg_Err (srv, "TLS server plugin not available"); vlc_object_release (srv); return NULL; } vlc_object_attach (srv, obj); msg_Dbg (srv, "TLS server plugin initialized"); return srv; } /** * Releases data allocated with tls_ServerCreate. * @param srv TLS server object to be destroyed, or NULL */ void tls_ServerDelete (tls_server_t *srv) { if (srv == NULL) return; module_Unneed (srv, srv->p_module); vlc_object_detach (srv); vlc_object_release (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) { 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. * * @param fd stream socket through which to establish the secure communication * layer. * @param psz_hostname Server Name Indication to pass to the server, or NULL. * * @return NULL on error. **/ tls_session_t * 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, "tls client"); if (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", 0, 0); if (cl->p_module == NULL) { msg_Err (cl, "TLS client plugin not available"); vlc_object_release (cl); return NULL; } cl->pf_set_fd (cl, fd); do val = cl->pf_handshake (cl); while (val > 0); if (val == 0) { msg_Dbg (cl, "TLS client session initialized"); vlc_object_attach (cl, obj); return cl; } msg_Err (cl, "TLS client session handshake error"); module_Unneed (cl, cl->p_module); vlc_object_release (cl); return NULL; } /** * Releases data allocated with tls_ClientCreate. * It is your job to close the underlying socket. */ void tls_ClientDelete (tls_session_t *cl) { if (cl == NULL) return; module_Unneed (cl, cl->p_module); vlc_object_detach (cl); vlc_object_release (cl); }