1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright © 2004-2007 Rémi Denis-Courmont
7 * Authors: Rémi Denis-Courmont <rem # videolan.org>
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.
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.
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 *****************************************************************************/
26 * libvlc interface to the Transport Layer Security (TLS) plugins.
38 #include <vlc_common.h>
42 #include <vlc_modules.h>
44 /*** TLS credentials ***/
46 static int tls_server_load(void *func, va_list ap)
48 int (*activate) (vlc_tls_creds_t *, const char *, const char *) = func;
49 vlc_tls_creds_t *crd = va_arg (ap, vlc_tls_creds_t *);
50 const char *cert = va_arg (ap, const char *);
51 const char *key = va_arg (ap, const char *);
53 return activate (crd, cert, key);
56 static int tls_client_load(void *func, va_list ap)
58 int (*activate) (vlc_tls_creds_t *) = func;
59 vlc_tls_creds_t *crd = va_arg (ap, vlc_tls_creds_t *);
61 return activate (crd);
64 static void tls_unload(void *func, va_list ap)
66 void (*deactivate) (vlc_tls_creds_t *) = func;
67 vlc_tls_creds_t *crd = va_arg (ap, vlc_tls_creds_t *);
73 * Allocates a whole server's TLS credentials.
75 * @param cert_path required (Unicode) path to an x509 certificate,
76 * if NULL, anonymous key exchange will be used.
77 * @param key_path (UTF-8) path to the PKCS private key for the certificate,
78 * if NULL; cert_path will be used.
80 * @return NULL on error.
83 vlc_tls_ServerCreate (vlc_object_t *obj, const char *cert_path,
86 vlc_tls_creds_t *srv = vlc_custom_create (obj, sizeof (*srv),
88 if (unlikely(srv == NULL))
94 srv->module = vlc_module_load (srv, "tls server", NULL, false,
95 tls_server_load, srv, cert_path, key_path);
96 if (srv->module == NULL)
98 msg_Err (srv, "TLS server plugin not available");
99 vlc_object_release (srv);
107 * Allocates TLS credentials for a client.
108 * Credentials can be cached and reused across multiple TLS sessions.
110 * @return TLS credentials object, or NULL on error.
112 vlc_tls_creds_t *vlc_tls_ClientCreate (vlc_object_t *obj)
114 vlc_tls_creds_t *crd = vlc_custom_create (obj, sizeof (*crd),
116 if (unlikely(crd == NULL))
119 crd->module = vlc_module_load (crd, "tls client", NULL, false,
120 tls_client_load, crd);
121 if (crd->module == NULL)
123 msg_Err (crd, "TLS client plugin not available");
124 vlc_object_release (crd);
132 * Releases data allocated with vlc_tls_ClientCreate() or
133 * vlc_tls_ServerCreate().
134 * @param srv TLS server object to be destroyed, or NULL
136 void vlc_tls_Delete (vlc_tls_creds_t *crd)
141 vlc_module_unload (crd->module, tls_unload, crd);
142 vlc_object_release (crd);
146 /*** TLS session ***/
148 vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *crd, int fd,
149 const char *host, const char *const *alpn)
151 vlc_tls_t *session = vlc_custom_create (crd, sizeof (*session),
153 int val = crd->open (crd, session, fd, host, alpn);
154 if (val == VLC_SUCCESS)
156 vlc_object_release (session);
160 int vlc_tls_SessionHandshake (vlc_tls_t *session, const char *host,
161 const char *service, char **restrict alp)
163 vlc_tls_creds_t *crd = (vlc_tls_creds_t *)(session->p_parent);
165 return crd->handshake (session, host, service, alp);
168 void vlc_tls_SessionDelete (vlc_tls_t *session)
170 vlc_tls_creds_t *crd = (vlc_tls_creds_t *)(session->p_parent);
172 crd->close (session);
173 vlc_object_release (session);
177 * Performs client side of TLS handshake through a connected socket, and
178 * establishes a secure channel. This is a blocking network operation.
180 * @param fd socket through which to establish the secure channel
181 * @param hostname expected server name, used both as Server Name Indication
182 * and as expected Common Name of the peer certificate
183 * @param service unique identifier for the service to connect to
184 * (only used locally for certificates database)
185 * @param alpn NULL-terminated list of Application Layer Protocols
186 * to negotiate, or NULL to not negotiate protocols
187 * @param alp storage space for the negotiated Application Layer
188 * Protocol or NULL if negotiation was not performed[OUT]
190 * @return NULL on error.
192 vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
193 const char *host, const char *service,
194 const char *const *alpn, char **alp)
196 vlc_tls_t *session = vlc_tls_SessionCreate (crd, fd, host, alpn);
200 mtime_t deadline = mdate ();
201 deadline += var_InheritInteger (crd, "ipv4-timeout") * 1000;
203 struct pollfd ufd[1];
207 while ((val = vlc_tls_SessionHandshake (session, host, service, alp)) != 0)
211 msg_Err (session, "TLS client session handshake error");
215 mtime_t now = mdate ();
220 ufd[0] .events = (val == 1) ? POLLIN : POLLOUT;
222 if (poll (ufd, 1, (deadline - now) / 1000) == 0)
224 msg_Err (session, "TLS client session handshake timeout");
230 vlc_tls_SessionDelete (session);