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@xxxxxxxxxxxxxxx> + * @author Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> * * 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel