]> git.sesse.net Git - vlc/blob - src/misc/tls.c
Reuse TLS module/object when already present - closes #288
[vlc] / src / misc / tls.c
1 /*****************************************************************************
2  * tls.c
3  *****************************************************************************
4  * Copyright (C) 2004-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Remi 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <stdlib.h>
25 #include <vlc/vlc.h>
26
27 #include "vlc_tls.h"
28
29 static tls_t *
30 tls_Init( vlc_object_t *p_this )
31 {
32     tls_t *p_tls;
33     vlc_value_t lockval;
34
35     var_Create( p_this->p_libvlc, "tls_mutex", VLC_VAR_MUTEX );
36     var_Get( p_this->p_libvlc, "tls_mutex", &lockval );
37     vlc_mutex_lock( lockval.p_address );
38
39     p_tls = vlc_object_find( p_this, VLC_OBJECT_TLS, FIND_ANYWHERE );
40
41     if( p_tls == NULL )
42     {
43         p_tls = vlc_object_create( p_this, VLC_OBJECT_TLS );
44         if( p_tls == NULL )
45         {
46             vlc_mutex_unlock( lockval.p_address );
47             return NULL;
48         }
49
50         p_tls->p_module = module_Need( p_tls, "tls", 0, 0 );
51         if( p_tls->p_module == NULL )
52         {
53             msg_Err( p_tls, "TLS/SSL provider not found" );
54             vlc_mutex_unlock( lockval.p_address );
55             vlc_object_destroy( p_tls );
56             return NULL;
57         }
58
59         vlc_object_attach( p_tls, p_this->p_vlc );
60         vlc_object_yield( p_tls );
61         msg_Dbg( p_tls, "TLS/SSL provider initialized" );
62     }
63     vlc_mutex_unlock( lockval.p_address );
64
65     return p_tls;
66 }
67
68 static void
69 tls_Deinit( tls_t *p_tls )
70 {
71     int i;
72     vlc_value_t lockval;
73
74     var_Get( p_tls->p_libvlc, "tls_mutex", &lockval );
75     vlc_mutex_lock( lockval.p_address );
76
77     vlc_object_release( p_tls );
78     
79     i = p_tls->i_refcount;
80     if( i == 0 )
81         vlc_object_detach( p_tls );
82
83     vlc_mutex_unlock( lockval.p_address );
84
85     if( i == 0 )
86     {
87         module_Unneed( p_tls, p_tls->p_module );
88         msg_Dbg( p_tls, "TLS/SSL provider deinitialized" );
89         vlc_object_destroy( p_tls );
90     }
91 }
92
93 /*****************************************************************************
94  * tls_ServerCreate:
95  *****************************************************************************
96  * Allocates a whole server's TLS credentials.
97  * Returns NULL on error.
98  *****************************************************************************/
99 tls_server_t *
100 tls_ServerCreate( vlc_object_t *p_this, const char *psz_cert,
101                   const char *psz_key )
102 {
103     tls_t *p_tls;
104     tls_server_t *p_server;
105
106     p_tls = tls_Init( p_this );
107     if( p_tls == NULL )
108         return NULL;
109
110     if( psz_key == NULL )
111         psz_key = psz_cert;
112
113     p_server = p_tls->pf_server_create( p_tls, psz_cert, psz_key );
114     if( p_server != NULL )
115     {
116         msg_Dbg( p_tls, "TLS/SSL server initialized" );
117         return p_server;
118     }
119     else
120         msg_Err( p_tls, "TLS/SSL server error" );
121
122     tls_Deinit( p_tls );
123     return NULL;
124 }
125
126
127 /*****************************************************************************
128  * tls_ServerDelete:
129  *****************************************************************************
130  * Releases data allocated with tls_ServerCreate.
131  *****************************************************************************/
132 void
133 tls_ServerDelete( tls_server_t *p_server )
134 {
135     tls_t *p_tls = (tls_t *)p_server->p_parent;
136
137     p_server->pf_delete( p_server );
138
139     tls_Deinit( p_tls );
140 }
141
142
143 /*****************************************************************************
144  * tls_ClientCreate:
145  *****************************************************************************
146  * Allocates a client's TLS credentials and shakes hands through the network.
147  * Returns NULL on error. This is a blocking network operation.
148  *****************************************************************************/
149 tls_session_t *
150 tls_ClientCreate( vlc_object_t *p_this, int fd, const char *psz_hostname )
151 {
152     tls_t *p_tls;
153     tls_session_t *p_session;
154
155     p_tls = tls_Init( p_this );
156     if( p_tls == NULL )
157         return NULL;
158         
159     p_session = p_tls->pf_client_create( p_tls );
160     if( p_session != NULL )
161     {
162         int i_val;
163
164         for( i_val = tls_ClientSessionHandshake( p_session, fd,
165                                                  psz_hostname );
166              i_val > 0;
167              i_val = tls_SessionContinueHandshake( p_session ) );
168
169         if( i_val == 0 )
170         {
171             msg_Dbg( p_this, "TLS/SSL client initialized" );
172             return p_session;
173         }
174         msg_Err( p_this, "TLS/SSL session handshake error" );
175     }
176     else
177         msg_Err( p_this, "TLS/SSL client error" );
178
179     tls_Deinit( p_tls );
180     return NULL;
181 }
182
183
184 /*****************************************************************************
185  * tls_ClientDelete:
186  *****************************************************************************
187  * Releases data allocated with tls_ClientCreate.
188  *****************************************************************************/
189 void
190 tls_ClientDelete( tls_session_t *p_session )
191 {
192     tls_t *p_tls = (tls_t *)p_session->p_parent;
193
194     p_session->pf_close( p_session );
195
196     tls_Deinit( p_tls );
197 }