[vlc-devel] [PATCH 1/2] gnutls: show a dialog allowing the user to bypass certificate issues
Ludovic Fauvet
etix at videolan.org
Thu Jun 21 01:35:58 CEST 2012
---
include/vlc_tls.h | 2 +-
modules/access/http.c | 4 +++-
modules/misc/gnutls.c | 37 ++++++++++++++++++++++++++++++++++---
src/network/tls.c | 9 +++++----
4 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/include/vlc_tls.h b/include/vlc_tls.h
index 66fcafd..32f3b4e 100644
--- a/include/vlc_tls.h
+++ b/include/vlc_tls.h
@@ -46,7 +46,7 @@ typedef struct vlc_tls
} vlc_tls_t;
VLC_API vlc_tls_t *vlc_tls_ClientCreate (vlc_object_t *, int fd,
- const char *hostname);
+ const char *hostname, bool *pb_ssltrust);
VLC_API void vlc_tls_ClientDelete (vlc_tls_t *);
/* NOTE: It is assumed that a->sock.p_sys = a */
diff --git a/modules/access/http.c b/modules/access/http.c
index f7a1e85..257255b 100644
--- a/modules/access/http.c
+++ b/modules/access/http.c
@@ -188,6 +188,7 @@ struct access_sys_t
bool b_pace_control;
bool b_persist;
bool b_has_size;
+ bool b_ssltrust; /* invalid cert trusted by the user */
vlc_array_t * cookies;
};
@@ -287,6 +288,7 @@ static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
p_sys->i_remaining = 0;
p_sys->b_persist = false;
p_sys->b_has_size = false;
+ p_sys->b_ssltrust = false;
p_access->info.i_size = 0;
p_access->info.i_pos = 0;
p_access->info.b_eof = false;
@@ -1218,7 +1220,7 @@ static int Connect( access_t *p_access, uint64_t i_tell )
/* TLS/SSL handshake */
p_sys->p_tls = vlc_tls_ClientCreate( VLC_OBJECT(p_access), p_sys->fd,
- p_sys->url.psz_host );
+ p_sys->url.psz_host, &p_sys->b_ssltrust );
if( p_sys->p_tls == NULL )
{
msg_Err( p_access, "cannot establish HTTP/TLS session" );
diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
index c9fef1f..33c3e54 100644
--- a/modules/misc/gnutls.c
+++ b/modules/misc/gnutls.c
@@ -47,6 +47,8 @@
#include <vlc_fs.h>
#include <vlc_block.h>
+#include <vlc_dialog.h>
+
#include <gcrypt.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
@@ -59,7 +61,7 @@
/*****************************************************************************
* Module descriptor
*****************************************************************************/
-static int OpenClient (vlc_tls_t *, int, const char *);
+static int OpenClient (vlc_tls_t *, int, const char *, bool *);
static void CloseClient (vlc_tls_t *);
static int OpenServer (vlc_object_t *);
static void CloseServer (vlc_object_t *);
@@ -195,6 +197,7 @@ struct vlc_tls_sys
gnutls_certificate_credentials_t x509_cred;
char *hostname;
bool handshaked;
+ bool *ssltrust;
};
@@ -302,18 +305,44 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session)
return -1;
}
- if (status)
+ if (status && !(*sys->ssltrust))
{
+ char str_errors[512] = {0};
+ char *str_dialog;
+ int s = 0;
+
msg_Err (session, "TLS session: access denied (status 0x%X)", status);
for (const error_msg_t *e = cert_errors; e->flag; e++)
{
if (status & e->flag)
{
msg_Err (session, "%s", e->msg);
+ s += sprintf(str_errors + s, "- %s\n", e->msg);
status &= ~e->flag;
}
}
+ if (asprintf(&str_dialog, "%s\n%s\n%s",
+ _( "The remote server cannot be trusted "
+ "because of the following issues:" ),
+ str_errors,
+ _( "Would you like to continue despite the risk?" ) ) == -1)
+ return -1;
+
+
+ switch (dialog_Question(session, _("Peer certificate cannot be trusted"),
+ str_dialog,
+ _( "Yes" ), _( "No" ), NULL))
+ {
+ case 1:
+ free(str_dialog);
+ *sys->ssltrust = true;
+ goto ignorewarning;
+ default:
+ free(str_dialog);
+ break;
+ }
+
if (status)
msg_Err (session,
"unknown certificate error (you found a bug in VLC)");
@@ -322,6 +351,7 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session)
/* certificate (host)name verification */
const gnutls_datum_t *data;
+ignorewarning:
data = gnutls_certificate_get_peers (sys->session, &(unsigned){0});
if (data == NULL)
{
@@ -499,7 +529,7 @@ gnutls_loadOSCAList (vlc_object_t *p_this,
/**
* Initializes a client-side TLS session.
*/
-static int OpenClient (vlc_tls_t *session, int fd, const char *hostname)
+static int OpenClient (vlc_tls_t *session, int fd, const char *hostname, bool *pb_ssltrust)
{
if (gnutls_Init (VLC_OBJECT(session)))
return VLC_EGENERIC;
@@ -516,6 +546,7 @@ static int OpenClient (vlc_tls_t *session, int fd, const char *hostname)
session->sock.pf_send = gnutls_Send;
session->sock.pf_recv = gnutls_Recv;
sys->handshaked = false;
+ sys->ssltrust = pb_ssltrust;
int val = gnutls_certificate_allocate_credentials (&sys->x509_cred);
if (val != 0)
diff --git a/src/network/tls.c b/src/network/tls.c
index 93892aa..a4dc583 100644
--- a/src/network/tls.c
+++ b/src/network/tls.c
@@ -139,12 +139,13 @@ int vlc_tls_ServerSessionHandshake (vlc_tls_t *ses)
static int tls_client_start(void *func, va_list ap)
{
- int (*activate) (vlc_tls_t *, int fd, const char *hostname) = func;
+ int (*activate) (vlc_tls_t *, int fd, const char *hostname, bool *pb_ssltrust) = func;
vlc_tls_t *session = va_arg (ap, vlc_tls_t *);
int fd = va_arg (ap, int);
const char *hostname = va_arg (ap, const char *);
+ bool *ssltrust = va_arg (ap, bool *);
- return activate (session, fd, hostname);
+ return activate (session, fd, hostname, ssltrust);
}
static void tls_client_stop(void *func, va_list ap)
@@ -166,14 +167,14 @@ static void tls_client_stop(void *func, va_list ap)
* @return NULL on error.
**/
vlc_tls_t *
-vlc_tls_ClientCreate (vlc_object_t *obj, int fd, const char *hostname)
+vlc_tls_ClientCreate (vlc_object_t *obj, int fd, const char *hostname, bool *pb_ssltrust)
{
vlc_tls_t *cl = vlc_custom_create (obj, sizeof (*cl), "tls client");
if (unlikely(cl == NULL))
return NULL;
cl->u.module = vlc_module_load (cl, "tls client", NULL, false,
- tls_client_start, cl, fd, hostname);
+ tls_client_start, cl, fd, hostname, pb_ssltrust);
if (cl->u.module == NULL)
{
msg_Err (cl, "TLS client plugin not available");
--
1.7.10.4
More information about the vlc-devel
mailing list