[Spice-devel] [PATCHv3 spice-gtk 07/14] http-proxy: add https proxy
Marc-André Lureau
marcandre.lureau at gmail.com
Mon Feb 17 13:35:46 PST 2014
This will require glib 2.28 for GTls support, atm
---
gtk/spice-session.c | 3 +
gtk/wocky-http-proxy.c | 161 ++++++++++++++++++++++++++++++++++++++++++-------
gtk/wocky-http-proxy.h | 14 +++++
3 files changed, 155 insertions(+), 23 deletions(-)
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 5d1c1c1..475306a 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -637,6 +637,9 @@ static void spice_session_class_init(SpiceSessionClass *klass)
#if GLIB_CHECK_VERSION(2, 26, 0)
_wocky_http_proxy_get_type();
#endif
+#if GLIB_CHECK_VERSION(2, 28, 0)
+ _wocky_https_proxy_get_type();
+#endif
gobject_class->dispose = spice_session_dispose;
gobject_class->finalize = spice_session_finalize;
diff --git a/gtk/wocky-http-proxy.c b/gtk/wocky-http-proxy.c
index 11f557e..4226b10 100644
--- a/gtk/wocky-http-proxy.c
+++ b/gtk/wocky-http-proxy.c
@@ -1,7 +1,9 @@
/* wocky-http-proxy.c: Source for WockyHttpProxy
*
* Copyright (C) 2010 Collabora, Ltd.
+ * Copyright (C) 2014 Red Hat, Inc.
* @author Nicolas Dufresne <nicolas.dufresne at collabora.co.uk>
+ * @author Marc-André Lureau <marcandre.lureau at redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -180,9 +182,32 @@ wocky_http_proxy_connect (GProxy *proxy,
{
GInputStream *in;
GOutputStream *out;
- GDataInputStream *data_in;
- gchar *buffer;
+ GDataInputStream *data_in = NULL;
+ gchar *buffer = NULL;
gboolean has_cred;
+ GIOStream *tlsconn = NULL;
+
+#if GLIB_CHECK_VERSION(2, 28, 0)
+ if (WOCKY_IS_HTTPS_PROXY (proxy))
+ {
+ tlsconn = g_tls_client_connection_new (io_stream,
+ G_SOCKET_CONNECTABLE(proxy_address),
+ error);
+ if (!tlsconn)
+ goto error;
+
+ GTlsCertificateFlags tls_validation_flags = G_TLS_CERTIFICATE_VALIDATE_ALL;
+#ifdef DEBUG
+ tls_validation_flags &= ~(G_TLS_CERTIFICATE_UNKNOWN_CA | G_TLS_CERTIFICATE_BAD_IDENTITY);
+#endif
+ g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn),
+ tls_validation_flags);
+ if (!g_tls_connection_handshake (G_TLS_CONNECTION (tlsconn), cancellable, error))
+ goto error;
+
+ io_stream = tlsconn;
+ }
+#endif
in = g_io_stream_get_input_stream (io_stream);
out = g_io_stream_get_output_stream (io_stream);
@@ -215,12 +240,14 @@ wocky_http_proxy_connect (GProxy *proxy,
g_free (buffer);
- return g_object_ref (io_stream);
+ g_object_ref (io_stream);
+ g_clear_object (&tlsconn);
-error:
- if (data_in != NULL)
- g_object_unref (data_in);
+ return io_stream;
+error:
+ g_clear_object (&tlsconn);
+ g_clear_object (&data_in);
g_free (buffer);
return NULL;
}
@@ -291,6 +318,41 @@ do_write (GAsyncReadyCallback callback, ConnectAsyncData *data)
}
static void
+stream_connected (ConnectAsyncData *data,
+ GIOStream *io_stream)
+{
+ GInputStream *in;
+
+ data->io_stream = g_object_ref (io_stream);
+ in = g_io_stream_get_input_stream (io_stream);
+ data->data_in = g_data_input_stream_new (in);
+ g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (data->data_in),
+ FALSE);
+
+ do_write (request_write_cb, data);
+}
+
+#if GLIB_CHECK_VERSION(2, 28, 0)
+static void
+handshake_completed (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GTlsConnection *conn = G_TLS_CONNECTION (source_object);
+ ConnectAsyncData *data = user_data;
+ GError *error = NULL;
+
+ if (!g_tls_connection_handshake_finish (conn, res, &error))
+ {
+ complete_async_from_error (data, error);
+ return;
+ }
+
+ stream_connected (data, G_IO_STREAM (conn));
+}
+#endif
+
+static void
wocky_http_proxy_connect_async (GProxy *proxy,
GIOStream *io_stream,
GProxyAddress *proxy_address,
@@ -300,34 +362,55 @@ wocky_http_proxy_connect_async (GProxy *proxy,
{
GSimpleAsyncResult *simple;
ConnectAsyncData *data;
- GInputStream *in;
simple = g_simple_async_result_new (G_OBJECT (proxy),
- callback, user_data,
- wocky_http_proxy_connect_async);
+ callback, user_data,
+ wocky_http_proxy_connect_async);
data = g_slice_new0 (ConnectAsyncData);
-
- data->simple = simple;
- data->io_stream = g_object_ref (io_stream);
-
if (cancellable != NULL)
data->cancellable = g_object_ref (cancellable);
-
- in = g_io_stream_get_input_stream (io_stream);
-
- data->data_in = g_data_input_stream_new (in);
- g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (data->data_in),
- FALSE);
-
- g_simple_async_result_set_op_res_gpointer (simple, data,
- (GDestroyNotify) free_connect_data);
+ data->simple = simple;
data->buffer = create_request (proxy_address, &data->has_cred);
data->length = strlen (data->buffer);
data->offset = 0;
- do_write (request_write_cb, data);
+ g_simple_async_result_set_op_res_gpointer (simple, data,
+ (GDestroyNotify) free_connect_data);
+
+#if GLIB_CHECK_VERSION(2, 28, 0)
+ if (WOCKY_IS_HTTPS_PROXY (proxy))
+ {
+ GError *error = NULL;
+ GIOStream *tlsconn;
+
+ tlsconn = g_tls_client_connection_new (io_stream,
+ G_SOCKET_CONNECTABLE(proxy_address),
+ &error);
+ if (!tlsconn)
+ {
+ complete_async_from_error (data, error);
+ return;
+ }
+
+ g_return_if_fail (tlsconn != NULL);
+
+ GTlsCertificateFlags tls_validation_flags = G_TLS_CERTIFICATE_VALIDATE_ALL;
+#ifdef DEBUG
+ tls_validation_flags &= ~(G_TLS_CERTIFICATE_UNKNOWN_CA | G_TLS_CERTIFICATE_BAD_IDENTITY);
+#endif
+ g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn),
+ tls_validation_flags);
+ g_tls_connection_handshake_async (G_TLS_CONNECTION (tlsconn),
+ G_PRIORITY_DEFAULT, cancellable,
+ handshake_completed, data);
+ }
+ else
+#endif
+ {
+ stream_connected (data, io_stream);
+ }
}
static void
@@ -427,3 +510,35 @@ wocky_http_proxy_iface_init (GProxyInterface *proxy_iface)
proxy_iface->connect_finish = wocky_http_proxy_connect_finish;
proxy_iface->supports_hostname = wocky_http_proxy_supports_hostname;
}
+
+#if GLIB_CHECK_VERSION(2, 28, 0)
+struct _WockyHttpsProxy
+{
+ WockyHttpProxy parent;
+};
+
+struct _WockyHttpsProxyClass
+{
+ WockyHttpProxyClass parent_class;
+};
+
+#define wocky_https_proxy_get_type _wocky_https_proxy_get_type
+G_DEFINE_TYPE_WITH_CODE (WockyHttpsProxy, wocky_https_proxy, WOCKY_TYPE_HTTP_PROXY,
+ G_IMPLEMENT_INTERFACE (G_TYPE_PROXY,
+ wocky_http_proxy_iface_init)
+ g_io_extension_point_set_required_type (
+ g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME),
+ G_TYPE_PROXY);
+ g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME,
+ g_define_type_id, "https", 0))
+
+static void
+wocky_https_proxy_init (WockyHttpsProxy *proxy)
+{
+}
+
+static void
+wocky_https_proxy_class_init (WockyHttpsProxyClass *class)
+{
+}
+#endif
diff --git a/gtk/wocky-http-proxy.h b/gtk/wocky-http-proxy.h
index 3b91e63..9484b51 100644
--- a/gtk/wocky-http-proxy.h
+++ b/gtk/wocky-http-proxy.h
@@ -37,6 +37,20 @@ typedef struct _WockyHttpProxyClass WockyHttpProxyClass;
GType _wocky_http_proxy_get_type (void);
+#if GLIB_CHECK_VERSION(2, 28, 0)
+#define WOCKY_TYPE_HTTPS_PROXY (_wocky_https_proxy_get_type ())
+#define WOCKY_HTTPS_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), WOCKY_TYPE_HTTPS_PROXY, WockyHttpsProxy))
+#define WOCKY_HTTPS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), WOCKY_TYPE_HTTPS_PROXY, WockyHttpsProxyClass))
+#define WOCKY_IS_HTTPS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), WOCKY_TYPE_HTTPS_PROXY))
+#define WOCKY_IS_HTTPS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), WOCKY_TYPE_HTTPS_PROXY))
+#define WOCKY_HTTPS_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), WOCKY_TYPE_HTTPS_PROXY, WockyHttpsProxyClass))
+
+typedef struct _WockyHttpsProxy WockyHttpsProxy;
+typedef struct _WockyHttpsProxyClass WockyHttpsProxyClass;
+
+GType _wocky_https_proxy_get_type (void);
+#endif
+
G_END_DECLS
#endif /* _WOCKY_HTTP_PROXY_H_ */
--
1.8.4.2
More information about the Spice-devel
mailing list