]> git.sesse.net Git - vlc/blob - src/network/tls.c
d9279c9067869616861d8b04cfa067c033474b68
[vlc] / src / network / tls.c
1 /*****************************************************************************
2  * tls.c
3  *****************************************************************************
4  * Copyright © 2004-2007 Rémi Denis-Courmont
5  * $Id$
6  *
7  * Authors: Rémi Denis-Courmont <rem # videolan.org>
8  *
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.
13  *
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.
18  *
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /**
25  * @file
26  * libvlc interface to the Transport Layer Security (TLS) plugins.
27  */
28
29 #include <vlc/vlc.h>
30
31 #include <vlc_tls.h>
32
33 static tls_t *
34 tls_Init( vlc_object_t *p_this )
35 {
36     tls_t *p_tls;
37     vlc_value_t lockval;
38
39     var_Create( p_this->p_libvlc, "tls_mutex", VLC_VAR_MUTEX );
40     var_Get( p_this->p_libvlc, "tls_mutex", &lockval );
41     vlc_mutex_lock( lockval.p_address );
42
43     p_tls = vlc_object_find( p_this, VLC_OBJECT_TLS, FIND_ANYWHERE );
44
45     if( p_tls == NULL )
46     {
47         p_tls = vlc_object_create( p_this, VLC_OBJECT_TLS );
48         if( p_tls == NULL )
49         {
50             vlc_mutex_unlock( lockval.p_address );
51             return NULL;
52         }
53
54         p_tls->p_module = module_Need( p_tls, "tls", 0, 0 );
55         if( p_tls->p_module == NULL )
56         {
57             msg_Err( p_tls, "TLS/SSL provider not found" );
58             vlc_mutex_unlock( lockval.p_address );
59             vlc_object_destroy( p_tls );
60             return NULL;
61         }
62
63         vlc_object_attach( p_tls, p_this->p_libvlc );
64         vlc_object_yield( p_tls );
65         msg_Dbg( p_tls, "TLS/SSL provider initialized" );
66     }
67     vlc_mutex_unlock( lockval.p_address );
68
69     return p_tls;
70 }
71
72 static void
73 tls_Deinit( tls_t *p_tls )
74 {
75     int i;
76     vlc_value_t lockval;
77
78     var_Get( p_tls->p_libvlc, "tls_mutex", &lockval );
79     vlc_mutex_lock( lockval.p_address );
80
81     vlc_object_release( p_tls );
82     
83     i = p_tls->i_refcount;
84     if( i == 0 )
85         vlc_object_detach( p_tls );
86
87     vlc_mutex_unlock( lockval.p_address );
88
89     if( i == 0 )
90     {
91         module_Unneed( p_tls, p_tls->p_module );
92         msg_Dbg( p_tls, "TLS/SSL provider deinitialized" );
93         vlc_object_destroy( p_tls );
94     }
95 }
96
97 /**
98  * Allocates a whole server's TLS credentials.
99  *
100  * @param psz_cert required (Unicode) path to an x509 certificate.
101  * @param psz_key required (Unicode) path to the PKCS private key for
102  * the certificate.
103  *
104  * @return NULL on error.
105  */
106 tls_server_t *
107 tls_ServerCreate( vlc_object_t *p_this, const char *psz_cert,
108                   const char *psz_key )
109 {
110     tls_t *p_tls;
111     tls_server_t *p_server;
112
113     p_tls = tls_Init( p_this );
114     if( p_tls == NULL )
115         return NULL;
116
117     if( psz_key == NULL )
118         psz_key = psz_cert;
119
120     p_server = p_tls->pf_server_create( p_tls, psz_cert, psz_key );
121     if( p_server != NULL )
122     {
123         msg_Dbg( p_tls, "TLS/SSL server initialized" );
124         return p_server;
125     }
126     else
127         msg_Err( p_tls, "TLS/SSL server error" );
128
129     tls_Deinit( p_tls );
130     return NULL;
131 }
132
133
134 /**
135  * Releases data allocated with tls_ServerCreate.
136  */
137 void
138 tls_ServerDelete( tls_server_t *p_server )
139 {
140     tls_t *p_tls = (tls_t *)p_server->p_parent;
141
142     p_server->pf_delete( p_server );
143
144     tls_Deinit( p_tls );
145 }
146
147
148 /**
149  * Allocates a client's TLS credentials and shakes hands through the network.
150  * This is a blocking network operation.
151  *
152  * @param fd stream socket through which to establish the secure communication
153  * layer.
154  * @param psz_hostname Server Name Indication to pass to the server, or NULL.
155  *
156  * @return NULL on error.
157  **/
158 tls_session_t *
159 tls_ClientCreate( vlc_object_t *p_this, int fd, const char *psz_hostname )
160 {
161     tls_t *p_tls;
162     tls_session_t *p_session;
163
164     p_tls = tls_Init( p_this );
165     if( p_tls == NULL )
166         return NULL;
167         
168     p_session = p_tls->pf_client_create( p_tls );
169     if( p_session != NULL )
170     {
171         int i_val;
172
173         for( i_val = tls_ClientSessionHandshake( p_session, fd,
174                                                  psz_hostname );
175              i_val > 0;
176              i_val = tls_SessionContinueHandshake( p_session ) );
177
178         if( i_val == 0 )
179         {
180             msg_Dbg( p_this, "TLS/SSL client initialized" );
181             return p_session;
182         }
183         msg_Err( p_this, "TLS/SSL session handshake error" );
184     }
185     else
186         msg_Err( p_this, "TLS/SSL client error" );
187
188     tls_Deinit( p_tls );
189     return NULL;
190 }
191
192
193 /**
194  * Releases data allocated with tls_ClientCreate.
195  * It is your job to close the underlying socket.
196  */
197 void
198 tls_ClientDelete( tls_session_t *p_session )
199 {
200     tls_t *p_tls = (tls_t *)p_session->p_parent;
201
202     p_session->pf_close( p_session );
203
204     tls_Deinit( p_tls );
205 }