#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
-#if (GNUTLS_VERSION_NUMBER < 0x030014)
-# define gnutls_certificate_set_x509_system_trust(c) \
- (c, GNUTLS_E_UNIMPLEMENTED_FEATURE)
-#endif
-#if (GNUTLS_VERSION_NUMBER < 0x03000D)
-# define gnutls_verify_stored_pubkey(db,tdb,host,serv,ctype,cert,fl) \
- (db, host, serv, ctype, cert, fl, GNUTLS_E_NO_CERTIFICATE_FOUND)
-# define gnutls_store_pubkey(db,tdb,host,serv,ctype,cert,e,fl) \
- (db, host, serv, ctype, cert, fl, GNUTLS_E_UNIMPLEMENTED_FEATURE)
-#endif
#include "dhparams.h"
/*****************************************************************************
set_capability( "tls client", 1 )
set_callbacks( OpenClient, CloseClient )
set_category( CAT_ADVANCED )
- set_subcategory( SUBCAT_ADVANCED_MISC )
+ set_subcategory( SUBCAT_ADVANCED_NETWORK )
add_submodule ()
set_description( N_("GNU TLS server") )
set_capability( "tls server", 1 )
set_category( CAT_ADVANCED )
- set_subcategory( SUBCAT_ADVANCED_MISC )
+ set_subcategory( SUBCAT_ADVANCED_NETWORK )
set_callbacks( OpenServer, CloseServer )
add_string ("gnutls-priorities", "NORMAL", PRIORITIES_TEXT,
goto error;
}
- const char *psz_version = gnutls_check_version ("2.6.6");
+ const char *psz_version = gnutls_check_version ("3.0.20");
if (psz_version == NULL)
{
msg_Err (p_this, "unsupported GnuTLS version");
switch (val)
{
case GNUTLS_E_AGAIN:
-#ifdef WIN32
+#ifdef _WIN32
WSASetLastError (WSAEWOULDBLOCK);
#else
errno = EAGAIN;
break;
case GNUTLS_E_INTERRUPTED:
-#ifdef WIN32
+#ifdef _WIN32
WSASetLastError (WSAEINTR);
#else
errno = EINTR;
if (!gnutls_error_is_fatal (val))
msg_Err (obj, "Error above should be handled");
#endif
-#ifdef WIN32
+#ifdef _WIN32
WSASetLastError (WSAECONNRESET);
#else
errno = ECONNRESET;
vlc_tls_sys_t *sys = session->sys;
int val;
-#ifdef WIN32
+#ifdef _WIN32
WSASetLastError (0);
#endif
- val = gnutls_handshake (sys->session);
- if ((val == GNUTLS_E_AGAIN) || (val == GNUTLS_E_INTERRUPTED))
- return 1 + gnutls_record_get_direction (sys->session);
+ do
+ {
+ val = gnutls_handshake (sys->session);
+ msg_Dbg (session, "TLS handshake: %s", gnutls_strerror (val));
+
+ if ((val == GNUTLS_E_AGAIN) || (val == GNUTLS_E_INTERRUPTED))
+ /* I/O event: return to caller's poll() loop */
+ return 1 + gnutls_record_get_direction (sys->session);
+ }
+ while (val < 0 && !gnutls_error_is_fatal (val));
if (val < 0)
{
-#ifdef WIN32
+#ifdef _WIN32
msg_Dbg (session, "Winsock error %d", WSAGetLastError ());
#endif
msg_Err (session, "TLS handshake error: %s", gnutls_strerror (val));
const gnutls_datum_t *restrict datum)
{
assert (host != NULL);
+
/* Look up mismatching certificate in store */
int val = gnutls_verify_stored_pubkey (NULL, NULL, host, service,
GNUTLS_CRT_X509, datum, 0);
+ const char *msg;
switch (val)
{
case 0:
return 0;
case GNUTLS_E_NO_CERTIFICATE_FOUND:
msg_Dbg (obj, "no known certificates for %s", host);
+ msg = N_("You attempted to reach %s. "
+ "However the security certificate presented by the server "
+ "is unknown and could not be authenticated by any trusted "
+ "Certification Authority. "
+ "This problem may be caused by a configuration error "
+ "or an attempt to breach your security or your privacy.\n\n"
+ "If in doubt, abort now.\n");
break;
case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
msg_Dbg (obj, "certificate keys mismatch for %s", host);
+ msg = N_("You attempted to reach %s. "
+ "However the security certificate presented by the server "
+ "changed since the previous visit "
+ "and was not authenticated by any trusted "
+ "Certification Authority. "
+ "This problem may be caused by a configuration error "
+ "or an attempt to breach your security or your privacy.\n\n"
+ "If in doubt, abort now.\n");
break;
default:
msg_Err (obj, "certificate key match error for %s: %s", host,
return -1;
}
- if (dialog_Question (obj, N_("Insecure site"),
- N_("You attempted to reach %s, but security certificate presented by "
- "the server could not be verified."
- "This problem may be caused by a configuration error "
- "on the server or by a serious breach of network security.\n\n"
- "If in doubt, abort now.\n"),
- N_("Abort"), N_("View certificate"), NULL, host) != 2)
- return -1;
+ if (dialog_Question (obj, _("Insecure site"), vlc_gettext (msg),
+ _("Abort"), _("View certificate"), NULL, host) != 2)
+ return -1;
gnutls_x509_crt_t cert;
gnutls_datum_t desc;
}
gnutls_x509_crt_deinit (cert);
- val = dialog_Question (obj, N_("Insecure site"),
- N_("This is the certificate presented by %s:\n%s\n\n"
- "If in doubt, abort now.\n"),
- N_("Abort"), N_("Accept 24 hours"),
- N_("Accept permanently"), host, desc.data);
+ val = dialog_Question (obj, _("Insecure site"),
+ _("This is the certificate presented by %s:\n%s\n\n"
+ "If in doubt, abort now.\n"),
+ _("Abort"), _("Accept 24 hours"),
+ _("Accept permanently"), host, desc.data);
gnutls_free (desc.data);
time_t expiry = 0;
time (&expiry);
expiry += 24 * 60 * 60;
case 3:
- gnutls_store_pubkey (NULL, NULL, host, service, GNUTLS_CRT_X509,
- datum, expiry, 0);
+ val = gnutls_store_pubkey (NULL, NULL, host, service,
+ GNUTLS_CRT_X509, datum, expiry, 0);
+ if (val)
+ msg_Err (obj, "cannot store X.509 certificate: %s",
+ gnutls_strerror (val));
return 0;
}
return -1;
static struct
{
- int flag;
- const char msg[43];
- bool strict;
+ unsigned flag;
+ const char msg[29];
} cert_errs[] =
{
- { GNUTLS_CERT_INVALID,
- "Certificate could not be verified", false },
- { GNUTLS_CERT_REVOKED,
- "Certificate was revoked", true },
- { GNUTLS_CERT_SIGNER_NOT_FOUND,
- "Certificate's signer was not found", false },
- { GNUTLS_CERT_SIGNER_NOT_CA,
- "Certificate's signer is not a CA", true },
- { GNUTLS_CERT_INSECURE_ALGORITHM,
- "Insecure certificate signature algorithm", true },
- { GNUTLS_CERT_NOT_ACTIVATED,
- "Certificate is not yet activated", true },
- { GNUTLS_CERT_EXPIRED,
- "Certificate has expired", true },
+ { GNUTLS_CERT_INVALID, "Certificate not verified" },
+ { GNUTLS_CERT_REVOKED, "Certificate revoked" },
+ { GNUTLS_CERT_SIGNER_NOT_FOUND, "Signer not found" },
+ { GNUTLS_CERT_SIGNER_NOT_CA, "Signer not a CA" },
+ { GNUTLS_CERT_INSECURE_ALGORITHM, "Signature algorithm insecure" },
+ { GNUTLS_CERT_NOT_ACTIVATED, "Certificate not activated" },
+ { GNUTLS_CERT_EXPIRED, "Certificate expired" },
};
gnutls_strerror (val));
return -1;
}
-
if (status)
{
- msg_Err (session, "Certificate verification failure:");
+ msg_Err (session, "Certificate verification failure (0x%04X)", status);
for (size_t i = 0; i < sizeof (cert_errs) / sizeof (cert_errs[0]); i++)
if (status & cert_errs[i].flag)
- {
msg_Err (session, " * %s", cert_errs[i].msg);
- status &= ~cert_errs[i].flag;
- if (cert_errs[i].strict)
- val = -1;
- }
-
- if (status)
- {
- msg_Err (session, " * Unknown verification error 0x%04X", status);
- val = -1;
- }
- status = -1;
+ if (status & ~(GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND))
+ return -1;
}
/* certificate (host)name verification */
val = gnutls_CertSearch (session, host, service, data);
}
error:
- gnutls_x509_crt_init (&cert);
- return val ? -1 : 0;
+ gnutls_x509_crt_deinit (cert);
+ return val;
}
static int