LGPL
[vlc.git] / 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 it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * 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 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include "libvlc.h"
35
36 #include <vlc_tls.h>
37 #include <vlc_modules.h>
38
39 /**
40  * Allocates a whole server's TLS credentials.
41  *
42  * @param cert_path required (Unicode) path to an x509 certificate,
43  *                  if NULL, anonymous key exchange will be used.
44  * @param key_path (UTF-8) path to the PKCS private key for the certificate,
45  *                 if NULL; cert_path will be used.
46  *
47  * @return NULL on error.
48  */
49 vlc_tls_creds_t *
50 vlc_tls_ServerCreate (vlc_object_t *obj, const char *cert_path,
51                       const char *key_path)
52 {
53     vlc_tls_creds_t *srv = vlc_custom_create (obj, sizeof (*srv), "tls creds");
54     if (unlikely(srv == NULL))
55         return NULL;
56
57     var_Create (srv, "tls-x509-cert", VLC_VAR_STRING);
58     var_Create (srv, "tls-x509-key", VLC_VAR_STRING);
59
60     if (cert_path != NULL)
61     {
62         var_SetString (srv, "tls-x509-cert", cert_path);
63
64         if (key_path == NULL)
65             key_path = cert_path;
66         var_SetString (srv, "tls-x509-key", key_path);
67     }
68
69     srv->module = module_need (srv, "tls server", NULL, false );
70     if (srv->module == NULL)
71     {
72         msg_Err (srv, "TLS server plugin not available");
73         vlc_object_release (srv);
74         return NULL;
75     }
76
77     msg_Dbg (srv, "TLS server plugin initialized");
78     return srv;
79 }
80
81
82 /**
83  * Releases data allocated with vlc_tls_ServerCreate().
84  * @param srv TLS server object to be destroyed, or NULL
85  */
86 void vlc_tls_ServerDelete (vlc_tls_creds_t *srv)
87 {
88     if (srv == NULL)
89         return;
90
91     module_unneed (srv, srv->module);
92     vlc_object_release (srv);
93 }
94
95
96 /**
97  * Adds one or more certificate authorities from a file.
98  * @return -1 on error, 0 on success.
99  */
100 int vlc_tls_ServerAddCA (vlc_tls_creds_t *srv, const char *path)
101 {
102     return srv->add_CA (srv, path);
103 }
104
105
106 /**
107  * Adds one or more certificate revocation list from a file.
108  * @return -1 on error, 0 on success.
109  */
110 int vlc_tls_ServerAddCRL (vlc_tls_creds_t *srv, const char *path)
111 {
112     return srv->add_CRL (srv, path);
113 }
114
115
116 vlc_tls_t *vlc_tls_ServerSessionCreate (vlc_tls_creds_t *srv, int fd)
117 {
118     return srv->open (srv, fd);
119 }
120
121
122 void vlc_tls_ServerSessionDelete (vlc_tls_t *ses)
123 {
124     ses->u.close (ses);
125 }
126
127
128 int vlc_tls_ServerSessionHandshake (vlc_tls_t *ses)
129 {
130     int val = ses->handshake (ses);
131     if (val < 0)
132         vlc_tls_ServerSessionDelete (ses);
133     return val;
134 }
135
136
137 /*** TLS client session ***/
138 /* TODO: cache certificates for the whole VLC instance lifetime */
139
140 static int tls_client_start(void *func, va_list ap)
141 {
142     int (*activate) (vlc_tls_t *, int fd, const char *hostname) = func;
143     vlc_tls_t *session = va_arg (ap, vlc_tls_t *);
144     int fd = va_arg (ap, int);
145     const char *hostname = va_arg (ap, const char *);
146
147     return activate (session, fd, hostname);
148 }
149
150 static void tls_client_stop(void *func, va_list ap)
151 {
152     void (*deactivate) (vlc_tls_t *) = func;
153     vlc_tls_t *session = va_arg (ap, vlc_tls_t *);
154
155     deactivate (session);
156 }
157
158 /**
159  * Allocates a client's TLS credentials and shakes hands through the network.
160  * This is a blocking network operation.
161  *
162  * @param fd stream socket through which to establish the secure communication
163  * layer.
164  * @param psz_hostname Server Name Indication to pass to the server, or NULL.
165  *
166  * @return NULL on error.
167  **/
168 vlc_tls_t *
169 vlc_tls_ClientCreate (vlc_object_t *obj, int fd, const char *hostname)
170 {
171     vlc_tls_t *cl = vlc_custom_create (obj, sizeof (*cl), "tls client");
172     if (unlikely(cl == NULL))
173         return NULL;
174
175     cl->u.module = vlc_module_load (cl, "tls client", NULL, false,
176                                     tls_client_start, cl, fd, hostname);
177     if (cl->u.module == NULL)
178     {
179         msg_Err (cl, "TLS client plugin not available");
180         vlc_object_release (cl);
181         return NULL;
182     }
183
184     /* TODO: do this directly in the TLS plugin */
185     int val;
186     do
187         val = cl->handshake (cl);
188     while (val > 0);
189
190     if (val != 0)
191     {
192         msg_Err (cl, "TLS client session handshake error");
193         vlc_module_unload (cl->u.module, tls_client_stop, cl);
194         vlc_object_release (cl);
195         return NULL;
196     }
197     msg_Dbg (cl, "TLS client session initialized");
198     return cl;
199 }
200
201
202 /**
203  * Releases data allocated with vlc_tls_ClientCreate().
204  * It is your job to close the underlying socket.
205  */
206 void vlc_tls_ClientDelete (vlc_tls_t *cl)
207 {
208     if (cl == NULL)
209         return;
210
211     vlc_module_unload (cl->u.module, tls_client_stop, cl);
212     vlc_object_release (cl);
213 }