Update translations from 2.2.x branch
[vlc.git] / modules / misc / gnutls.c
blob1cca9c14a7bfc550b205536a05befb243a73873c
1 /*****************************************************************************
2 * gnutls.c
3 *****************************************************************************
4 * Copyright (C) 2004-2017 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <limits.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <errno.h>
30 #include <assert.h>
31 #include <unistd.h>
32 #ifdef HAVE_SYS_UIO_H
33 # include <sys/uio.h>
34 #endif
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38 #include <vlc_tls.h>
39 #include <vlc_block.h>
40 #include <vlc_dialog.h>
42 #include <gnutls/gnutls.h>
43 #include <gnutls/x509.h>
45 typedef struct vlc_tls_gnutls
47 vlc_tls_t tls;
48 gnutls_session_t session;
49 vlc_object_t *obj;
50 } vlc_tls_gnutls_t;
52 static int gnutls_Init (vlc_object_t *obj)
54 const char *version = gnutls_check_version ("3.3.0");
55 if (version == NULL)
57 msg_Err (obj, "unsupported GnuTLS version");
58 return -1;
60 msg_Dbg (obj, "using GnuTLS version %s", version);
61 return 0;
64 static int gnutls_Error(vlc_tls_gnutls_t *priv, int val)
66 switch (val)
68 case GNUTLS_E_AGAIN:
69 #ifdef _WIN32
70 WSASetLastError (WSAEWOULDBLOCK);
71 #endif
72 errno = EAGAIN;
73 break;
75 case GNUTLS_E_INTERRUPTED:
76 #ifdef _WIN32
77 WSASetLastError (WSAEINTR);
78 #endif
79 errno = EINTR;
80 break;
82 default:
83 msg_Err(priv->obj, "%s", gnutls_strerror (val));
84 #ifndef NDEBUG
85 if (!gnutls_error_is_fatal (val))
86 msg_Err(priv->obj, "Error above should be handled");
87 #endif
88 #ifdef _WIN32
89 WSASetLastError (WSAECONNRESET);
90 #endif
91 errno = ECONNRESET;
93 return -1;
96 static ssize_t vlc_gnutls_read(gnutls_transport_ptr_t ptr, void *buf,
97 size_t length)
99 vlc_tls_t *sock = ptr;
100 struct iovec iov = {
101 .iov_base = buf,
102 .iov_len = length,
105 return sock->readv(sock, &iov, 1);
108 static ssize_t vlc_gnutls_writev(gnutls_transport_ptr_t ptr,
109 const giovec_t *giov, int iovcnt)
111 #ifdef IOV_MAX
112 const long iovmax = IOV_MAX;
113 #else
114 const long iovmax = sysconf(_SC_IOV_MAX);
115 #endif
116 if (unlikely(iovcnt > iovmax))
118 errno = EINVAL;
119 return -1;
121 if (unlikely(iovcnt == 0))
122 return 0;
124 vlc_tls_t *sock = ptr;
125 struct iovec iov[iovcnt];
127 for (int i = 0; i < iovcnt; i++)
129 iov[i].iov_base = giov[i].iov_base;
130 iov[i].iov_len = giov[i].iov_len;
133 return sock->writev(sock, iov, iovcnt);
136 static int gnutls_GetFD(vlc_tls_t *tls)
138 vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
139 vlc_tls_t *sock = gnutls_transport_get_ptr(priv->session);
141 return vlc_tls_GetFD(sock);
144 static ssize_t gnutls_Recv(vlc_tls_t *tls, struct iovec *iov, unsigned count)
146 vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
147 gnutls_session_t session = priv->session;
148 size_t rcvd = 0;
150 while (count > 0)
152 ssize_t val = gnutls_record_recv(session, iov->iov_base, iov->iov_len);
153 if (val < 0)
154 return rcvd ? (ssize_t)rcvd : gnutls_Error(priv, val);
156 rcvd += val;
158 if ((size_t)val < iov->iov_len)
159 break;
161 iov++;
162 count--;
165 return rcvd;
168 static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov,
169 unsigned count)
171 vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
172 gnutls_session_t session = priv->session;
173 ssize_t val;
175 if (!gnutls_record_check_corked(session))
177 gnutls_record_cork(session);
179 while (count > 0)
181 val = gnutls_record_send(session, iov->iov_base, iov->iov_len);
182 if (val < (ssize_t)iov->iov_len)
183 break;
185 iov++;
186 count--;
190 val = gnutls_record_uncork(session, 0);
191 return (val < 0) ? gnutls_Error(priv, val) : val;
194 static int gnutls_Shutdown(vlc_tls_t *tls, bool duplex)
196 vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
197 gnutls_session_t session = priv->session;
198 ssize_t val;
200 /* Flush any pending data */
201 val = gnutls_record_uncork(session, 0);
202 if (val < 0)
203 return gnutls_Error(priv, val);
205 val = gnutls_bye(session, duplex ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
206 if (val < 0)
207 return gnutls_Error(priv, val);
209 return 0;
212 static void gnutls_Close (vlc_tls_t *tls)
214 vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
216 gnutls_deinit(priv->session);
217 free(priv);
220 static vlc_tls_gnutls_t *gnutls_SessionOpen(vlc_tls_creds_t *creds, int type,
221 gnutls_certificate_credentials_t x509,
222 vlc_tls_t *sock,
223 const char *const *alpn)
225 vlc_tls_gnutls_t *priv = malloc(sizeof (*priv));
226 if (unlikely(priv == NULL))
227 return NULL;
229 gnutls_session_t session;
230 const char *errp;
231 int val;
233 type |= GNUTLS_NONBLOCK;
234 #if (GNUTLS_VERSION_NUMBER >= 0x030500)
235 type |= GNUTLS_ENABLE_FALSE_START;
236 #endif
238 val = gnutls_init(&session, type);
239 if (val != 0)
241 msg_Err(creds, "cannot initialize TLS session: %s",
242 gnutls_strerror(val));
243 free(priv);
244 return NULL;
247 char *priorities = var_InheritString(creds, "gnutls-priorities");
248 if (unlikely(priorities == NULL))
249 goto error;
251 val = gnutls_priority_set_direct (session, priorities, &errp);
252 if (val < 0)
253 msg_Err(creds, "cannot set TLS priorities \"%s\": %s", errp,
254 gnutls_strerror(val));
255 free (priorities);
256 if (val < 0)
257 goto error;
259 val = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509);
260 if (val < 0)
262 msg_Err(creds, "cannot set TLS session credentials: %s",
263 gnutls_strerror(val));
264 goto error;
267 if (alpn != NULL)
269 gnutls_datum_t *protv = NULL;
270 unsigned protc = 0;
272 while (*alpn != NULL)
274 gnutls_datum_t *n = realloc(protv, sizeof (*protv) * (protc + 1));
275 if (unlikely(n == NULL))
277 free(protv);
278 goto error;
280 protv = n;
282 protv[protc].data = (void *)*alpn;
283 protv[protc].size = strlen(*alpn);
284 protc++;
285 alpn++;
288 val = gnutls_alpn_set_protocols (session, protv, protc, 0);
289 free (protv);
292 gnutls_transport_set_ptr(session, sock);
293 gnutls_transport_set_vec_push_function(session, vlc_gnutls_writev);
294 gnutls_transport_set_pull_function(session, vlc_gnutls_read);
296 priv->session = session;
297 priv->obj = VLC_OBJECT(creds);
299 vlc_tls_t *tls = &priv->tls;
301 tls->get_fd = gnutls_GetFD;
302 tls->readv = gnutls_Recv;
303 tls->writev = gnutls_Send;
304 tls->shutdown = gnutls_Shutdown;
305 tls->close = gnutls_Close;
306 return priv;
308 error:
309 gnutls_deinit (session);
310 free(priv);
311 return NULL;
315 * Starts or continues the TLS handshake.
317 * @return -1 on fatal error, 0 on successful handshake completion,
318 * 1 if more would-be blocking recv is needed,
319 * 2 if more would-be blocking send is required.
321 static int gnutls_ContinueHandshake(vlc_tls_creds_t *crd,
322 vlc_tls_gnutls_t *priv,
323 char **restrict alp)
325 gnutls_session_t session = priv->session;
326 int val;
328 #ifdef _WIN32
329 WSASetLastError (0);
330 #endif
333 val = gnutls_handshake (session);
334 msg_Dbg(crd, "TLS handshake: %s", gnutls_strerror (val));
336 switch (val)
338 case GNUTLS_E_SUCCESS:
339 goto done;
340 case GNUTLS_E_AGAIN:
341 case GNUTLS_E_INTERRUPTED:
342 /* I/O event: return to caller's poll() loop */
343 return 1 + gnutls_record_get_direction (session);
346 while (!gnutls_error_is_fatal (val));
348 #ifdef _WIN32
349 msg_Dbg(crd, "Winsock error %d", WSAGetLastError ());
350 #endif
351 msg_Err(crd, "TLS handshake error: %s", gnutls_strerror (val));
352 return -1;
354 done:
355 #if (GNUTLS_VERSION_NUMBER >= 0x030500)
356 /* intentionally left blank */;
358 unsigned flags = gnutls_session_get_flags(session);
360 if (flags & GNUTLS_SFLAGS_SAFE_RENEGOTIATION)
361 msg_Dbg(crd, " - safe renegotiation (RFC5746) enabled");
362 if (flags & GNUTLS_SFLAGS_EXT_MASTER_SECRET)
363 msg_Dbg(crd, " - extended master secret (RFC7627) enabled");
364 if (flags & GNUTLS_SFLAGS_ETM)
365 msg_Dbg(crd, " - encrypt then MAC (RFC7366) enabled");
366 if (flags & GNUTLS_SFLAGS_FALSE_START)
367 msg_Dbg(crd, " - false start (RFC7918) enabled");
368 #endif
370 if (alp != NULL)
372 gnutls_datum_t datum;
374 val = gnutls_alpn_get_selected_protocol (session, &datum);
375 if (val == 0)
377 if (memchr (datum.data, 0, datum.size) != NULL)
378 return -1; /* Other end is doing something fishy?! */
380 *alp = strndup ((char *)datum.data, datum.size);
381 if (unlikely(*alp == NULL))
382 return -1;
384 else
385 *alp = NULL;
387 return 0;
390 static vlc_tls_t *gnutls_ClientSessionOpen(vlc_tls_creds_t *crd,
391 vlc_tls_t *sk, const char *hostname,
392 const char *const *alpn)
394 vlc_tls_gnutls_t *priv;
396 priv = gnutls_SessionOpen(crd, GNUTLS_CLIENT, crd->sys, sk, alpn);
397 if (priv == NULL)
398 return NULL;
400 gnutls_session_t session = priv->session;
402 /* minimum DH prime bits */
403 gnutls_dh_set_prime_bits (session, 1024);
405 if (likely(hostname != NULL))
406 /* fill Server Name Indication */
407 gnutls_server_name_set (session, GNUTLS_NAME_DNS,
408 hostname, strlen (hostname));
410 return &priv->tls;
413 static int gnutls_ClientHandshake(vlc_tls_creds_t *creds, vlc_tls_t *tls,
414 const char *host, const char *service,
415 char **restrict alp)
417 vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
419 int val = gnutls_ContinueHandshake(creds, priv, alp);
420 if (val)
421 return val;
423 /* certificates chain verification */
424 gnutls_session_t session = priv->session;
425 unsigned status;
427 val = gnutls_certificate_verify_peers3 (session, host, &status);
428 if (val)
430 msg_Err(creds, "Certificate verification error: %s",
431 gnutls_strerror(val));
432 goto error;
435 if (status == 0) /* Good certificate */
436 return 0;
438 /* Bad certificate */
439 gnutls_datum_t desc;
441 if (gnutls_certificate_verification_status_print(status,
442 gnutls_certificate_type_get (session), &desc, 0) == 0)
444 msg_Err(creds, "Certificate verification failure: %s", desc.data);
445 gnutls_free (desc.data);
448 status &= ~GNUTLS_CERT_INVALID; /* always set / catch-all error */
449 status &= ~GNUTLS_CERT_SIGNER_NOT_FOUND; /* unknown CA */
450 status &= ~GNUTLS_CERT_UNEXPECTED_OWNER; /* mismatched hostname */
452 if (status != 0 || host == NULL)
453 goto error; /* Really bad certificate */
455 /* Look up mismatching certificate in store */
456 const gnutls_datum_t *datum;
457 unsigned count;
459 datum = gnutls_certificate_get_peers (session, &count);
460 if (datum == NULL || count == 0)
462 msg_Err(creds, "Peer certificate not available");
463 goto error;
466 msg_Dbg(creds, "%u certificate(s) in the list", count);
467 val = gnutls_verify_stored_pubkey (NULL, NULL, host, service,
468 GNUTLS_CRT_X509, datum, 0);
469 const char *msg;
470 switch (val)
472 case 0:
473 msg_Dbg(creds, "certificate key match for %s", host);
474 return 0;
475 case GNUTLS_E_NO_CERTIFICATE_FOUND:
476 msg_Dbg(creds, "no known certificates for %s", host);
477 msg = N_("However, the security certificate presented by the "
478 "server is unknown and could not be authenticated by any "
479 "trusted Certificate Authority.");
480 break;
481 case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
482 msg_Dbg(creds, "certificate keys mismatch for %s", host);
483 msg = N_("However, the security certificate presented by the "
484 "server changed since the previous visit and was not "
485 "authenticated by any trusted Certificate Authority.");
486 break;
487 default:
488 msg_Err(creds, "certificate key match error for %s: %s", host,
489 gnutls_strerror(val));
490 goto error;
493 if (vlc_dialog_wait_question(creds, VLC_DIALOG_QUESTION_WARNING,
494 _("Abort"), _("View certificate"), NULL,
495 _("Insecure site"),
496 _("You attempted to reach %s. %s\n"
497 "This problem may be stem from an attempt to breach your security, "
498 "compromise your privacy, or a configuration error.\n\n"
499 "If in doubt, abort now.\n"), host, vlc_gettext(msg)) != 1)
500 goto error;
502 gnutls_x509_crt_t cert;
504 if (gnutls_x509_crt_init (&cert))
505 goto error;
506 if (gnutls_x509_crt_import (cert, datum, GNUTLS_X509_FMT_DER)
507 || gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_ONELINE, &desc))
509 gnutls_x509_crt_deinit (cert);
510 goto error;
512 gnutls_x509_crt_deinit (cert);
514 val = vlc_dialog_wait_question(creds, VLC_DIALOG_QUESTION_WARNING,
515 _("Abort"), _("Accept 24 hours"), _("Accept permanently"),
516 _("Insecure site"),
517 _("This is the certificate presented by %s:\n%s\n\n"
518 "If in doubt, abort now.\n"), host, desc.data);
519 gnutls_free (desc.data);
521 time_t expiry = 0;
522 switch (val)
524 case 1:
525 time (&expiry);
526 expiry += 24 * 60 * 60;
527 /* fall through */
528 case 2:
529 val = gnutls_store_pubkey (NULL, NULL, host, service,
530 GNUTLS_CRT_X509, datum, expiry, 0);
531 if (val)
532 msg_Err(creds, "cannot store X.509 certificate: %s",
533 gnutls_strerror (val));
534 break;
535 default:
536 goto error;
538 return 0;
540 error:
541 if (alp != NULL)
542 free(*alp);
543 return -1;
547 * Initializes a client-side TLS credentials.
549 static int OpenClient (vlc_tls_creds_t *crd)
551 gnutls_certificate_credentials_t x509;
553 if (gnutls_Init (VLC_OBJECT(crd)))
554 return VLC_EGENERIC;
556 int val = gnutls_certificate_allocate_credentials (&x509);
557 if (val != 0)
559 msg_Err (crd, "cannot allocate credentials: %s",
560 gnutls_strerror (val));
561 return VLC_EGENERIC;
564 if (var_InheritBool(crd, "gnutls-system-trust"))
566 val = gnutls_certificate_set_x509_system_trust(x509);
567 if (val < 0)
568 msg_Err(crd, "cannot load trusted Certificate Authorities "
569 "from %s: %s", "system", gnutls_strerror(val));
570 else
571 msg_Dbg(crd, "loaded %d trusted CAs from %s", val, "system");
574 char *dir = var_InheritString(crd, "gnutls-dir-trust");
575 if (dir != NULL)
577 val = gnutls_certificate_set_x509_trust_dir(x509, dir,
578 GNUTLS_X509_FMT_PEM);
579 if (val < 0)
580 msg_Err(crd, "cannot load trusted Certificate Authorities "
581 "from %s: %s", dir, gnutls_strerror(val));
582 else
583 msg_Dbg(crd, "loaded %d trusted CAs from %s", val, dir);
584 free(dir);
587 gnutls_certificate_set_verify_flags (x509,
588 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
590 crd->sys = x509;
591 crd->open = gnutls_ClientSessionOpen;
592 crd->handshake = gnutls_ClientHandshake;
594 return VLC_SUCCESS;
597 static void CloseClient (vlc_tls_creds_t *crd)
599 gnutls_certificate_credentials_t x509 = crd->sys;
601 gnutls_certificate_free_credentials (x509);
604 #ifdef ENABLE_SOUT
606 * Server-side TLS credentials private data
608 typedef struct vlc_tls_creds_sys
610 gnutls_certificate_credentials_t x509_cred;
611 gnutls_dh_params_t dh_params;
612 } vlc_tls_creds_sys_t;
615 * Initializes a server-side TLS session.
617 static vlc_tls_t *gnutls_ServerSessionOpen(vlc_tls_creds_t *crd,
618 vlc_tls_t *sk, const char *hostname,
619 const char *const *alpn)
621 vlc_tls_creds_sys_t *sys = crd->sys;
622 vlc_tls_gnutls_t *priv;
624 assert (hostname == NULL);
625 priv = gnutls_SessionOpen(crd, GNUTLS_SERVER, sys->x509_cred, sk, alpn);
626 return (priv != NULL) ? &priv->tls : NULL;
629 static int gnutls_ServerHandshake(vlc_tls_creds_t *crd, vlc_tls_t *tls,
630 const char *host, const char *service,
631 char **restrict alp)
633 vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
635 (void) host; (void) service;
636 return gnutls_ContinueHandshake(crd, priv, alp);
640 * Allocates a whole server's TLS credentials.
642 static int OpenServer (vlc_tls_creds_t *crd, const char *cert, const char *key)
644 int val;
646 if (gnutls_Init (VLC_OBJECT(crd)))
647 return VLC_EGENERIC;
649 vlc_tls_creds_sys_t *sys = malloc (sizeof (*sys));
650 if (unlikely(sys == NULL))
651 return VLC_ENOMEM;
653 /* Sets server's credentials */
654 val = gnutls_certificate_allocate_credentials (&sys->x509_cred);
655 if (val != 0)
657 msg_Err (crd, "cannot allocate credentials: %s",
658 gnutls_strerror (val));
659 free (sys);
660 return VLC_ENOMEM;
663 block_t *certblock = block_FilePath(cert, false);
664 if (certblock == NULL)
666 msg_Err (crd, "cannot read certificate chain from %s: %s", cert,
667 vlc_strerror_c(errno));
668 goto error;
671 block_t *keyblock = block_FilePath(key, false);
672 if (keyblock == NULL)
674 msg_Err (crd, "cannot read private key from %s: %s", key,
675 vlc_strerror_c(errno));
676 block_Release (certblock);
677 goto error;
680 gnutls_datum_t pub = {
681 .data = certblock->p_buffer,
682 .size = certblock->i_buffer,
683 }, priv = {
684 .data = keyblock->p_buffer,
685 .size = keyblock->i_buffer,
688 val = gnutls_certificate_set_x509_key_mem (sys->x509_cred, &pub, &priv,
689 GNUTLS_X509_FMT_PEM);
690 block_Release (keyblock);
691 block_Release (certblock);
692 if (val < 0)
694 msg_Err (crd, "cannot load X.509 key: %s", gnutls_strerror (val));
695 goto error;
698 /* FIXME:
699 * - regenerate these regularly
700 * - support other cipher suites
702 val = gnutls_dh_params_init (&sys->dh_params);
703 if (val >= 0)
705 gnutls_sec_param_t sec = GNUTLS_SEC_PARAM_MEDIUM;
706 unsigned bits = gnutls_sec_param_to_pk_bits (GNUTLS_PK_DH, sec);
708 msg_Dbg (crd, "generating Diffie-Hellman %u-bits parameters...", bits);
709 val = gnutls_dh_params_generate2 (sys->dh_params, bits);
710 if (val == 0)
711 gnutls_certificate_set_dh_params (sys->x509_cred,
712 sys->dh_params);
714 if (val < 0)
716 msg_Err (crd, "cannot initialize DHE cipher suites: %s",
717 gnutls_strerror (val));
720 msg_Dbg (crd, "ciphers parameters loaded");
722 crd->sys = sys;
723 crd->open = gnutls_ServerSessionOpen;
724 crd->handshake = gnutls_ServerHandshake;
726 return VLC_SUCCESS;
728 error:
729 gnutls_certificate_free_credentials (sys->x509_cred);
730 free (sys);
731 return VLC_EGENERIC;
735 * Destroys a TLS server object.
737 static void CloseServer (vlc_tls_creds_t *crd)
739 vlc_tls_creds_sys_t *sys = crd->sys;
741 /* all sessions depending on the server are now deinitialized */
742 gnutls_certificate_free_credentials (sys->x509_cred);
743 gnutls_dh_params_deinit (sys->dh_params);
744 free (sys);
746 #endif
748 #define SYSTEM_TRUST_TEXT N_("Use system trust database")
749 #define SYSTEM_TRUST_LONGTEXT N_( \
750 "Trust the root certificates of Certificate Authorities stored in " \
751 "the operating system trust database to authenticate TLS sessions.")
753 #define DIR_TRUST_TEXT N_("Trust directory")
754 #define DIR_TRUST_LONGTEXT N_( \
755 "Trust the root certificates of Certificate Authorities stored in " \
756 "the specified directory to authenticate TLS sessions.")
758 #define PRIORITIES_TEXT N_("TLS cipher priorities")
759 #define PRIORITIES_LONGTEXT N_("Ciphers, key exchange methods, " \
760 "hash functions and compression methods can be selected. " \
761 "Refer to GNU TLS documentation for detailed syntax.")
762 static const char *const priorities_values[] = {
763 "PERFORMANCE",
764 "NORMAL",
765 "SECURE128",
766 "SECURE256",
767 "EXPORT",
769 static const char *const priorities_text[] = {
770 N_("Performance (prioritize faster ciphers)"),
771 N_("Normal"),
772 N_("Secure 128-bits (exclude 256-bits ciphers)"),
773 N_("Secure 256-bits (prioritize 256-bits ciphers)"),
774 N_("Export (include insecure ciphers)"),
777 vlc_module_begin ()
778 set_shortname( "GNU TLS" )
779 set_description( N_("GNU TLS transport layer security") )
780 set_capability( "tls client", 1 )
781 set_callbacks( OpenClient, CloseClient )
782 set_category( CAT_ADVANCED )
783 set_subcategory( SUBCAT_ADVANCED_NETWORK )
784 add_bool("gnutls-system-trust", true, SYSTEM_TRUST_TEXT,
785 SYSTEM_TRUST_LONGTEXT, true)
786 add_string("gnutls-dir-trust", NULL, DIR_TRUST_TEXT,
787 DIR_TRUST_TEXT, true)
788 add_string ("gnutls-priorities", "NORMAL", PRIORITIES_TEXT,
789 PRIORITIES_LONGTEXT, false)
790 change_string_list (priorities_values, priorities_text)
791 #ifdef ENABLE_SOUT
792 add_submodule ()
793 set_description( N_("GNU TLS server") )
794 set_capability( "tls server", 1 )
795 set_category( CAT_ADVANCED )
796 set_subcategory( SUBCAT_ADVANCED_NETWORK )
797 set_callbacks( OpenServer, CloseServer )
798 #endif
799 vlc_module_end ()