From bb7929f7faf60a4c738ccb2d65667d8c23f15823 Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Sun, 3 Jul 2016 21:20:56 +0300 Subject: [PATCH 1/2] Remove wocky-http-proxy, upstreamed in GIO now The wocky http proxy has now moved in GIO, so we no longer need to maintain it here. I have kept the unit test for the moment, to verify that the code in gio works the same as the one that we used to ship in wocky. There was one difference in the code from GIO, though. It includes "Basic" as part of the authorization string. According to RFC this is correct, so it looks like the wocky proxy client code was doing this wrong. I have updated the test to reflect that. https://bugs.freedesktop.org/show_bug.cgi?id=94031 --- configure.ac | 8 - docs/reference/wocky-docs.sgml | 1 - tests/Makefile.am | 5 +- tests/wocky-http-proxy-test.c | 15 +- wocky/Makefile.am | 10 - wocky/wocky-connector.c | 58 +++--- wocky/wocky-http-proxy.c | 430 ----------------------------------------- wocky/wocky-http-proxy.h | 46 ----- 8 files changed, 28 insertions(+), 545 deletions(-) delete mode 100644 wocky/wocky-http-proxy.c delete mode 100644 wocky/wocky-http-proxy.h diff --git a/configure.ac b/configure.ac index 4e103ca..0e99203 100644 --- a/configure.ac +++ b/configure.ac @@ -127,14 +127,6 @@ AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_32], [Prevent post 2.32 AP AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) -dnl Check GIO proxy support -PKG_CHECK_EXISTS([gio-2.0 >= 2.25.15], - [HAVE_GIO_PROXY=yes - AC_DEFINE(HAVE_GIO_PROXY, [1], [Defined if GIO supports proxy])], - [HAVE_GIO_PROXY=no]) -AM_CONDITIONAL(HAVE_GIO_PROXY, [test "x${HAVE_GIO_PROXY}" = "xyes"]) - - dnl Choose an SSL/TLS backend (default gnutls) AC_ARG_WITH([tls], AC_HELP_STRING([--with-tls=BACKEND], diff --git a/docs/reference/wocky-docs.sgml b/docs/reference/wocky-docs.sgml index 922e096..69daa83 100644 --- a/docs/reference/wocky-docs.sgml +++ b/docs/reference/wocky-docs.sgml @@ -26,7 +26,6 @@ - diff --git a/tests/Makefile.am b/tests/Makefile.am index 03fd6fb..f371007 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -71,6 +71,7 @@ TEST_PROGS = \ wocky-xmpp-node-test \ wocky-xmpp-reader-test \ wocky-xmpp-readwrite-test \ + wocky-http-proxy-test \ $(NULL) noinst_PROGRAMS = @@ -80,10 +81,6 @@ if HAVE_LIBSASL2 noinst_PROGRAMS += wocky-dummy-xmpp-server endif -if HAVE_GIO_PROXY - TEST_PROGS += wocky-http-proxy-test -endif - wocky_bare_contact_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ diff --git a/tests/wocky-http-proxy-test.c b/tests/wocky-http-proxy-test.c index ce9a854..24de3c5 100644 --- a/tests/wocky-http-proxy-test.c +++ b/tests/wocky-http-proxy-test.c @@ -9,13 +9,6 @@ #include -/* WockyHttpProxy isn't public API, so we need to be a bit sneaky to get the - * header. - */ -#define WOCKY_COMPILATION -#include -#undef WOCKY_COMPILATION - typedef enum { DOMAIN_NONE = 0, @@ -164,7 +157,6 @@ test_http_proxy_instantiation (void) proxy = g_proxy_get_default_for_protocol ("http"); g_assert (G_IS_PROXY (proxy)); - g_assert (WOCKY_IS_HTTP_PROXY (proxy)); g_object_unref (proxy); } @@ -226,6 +218,11 @@ server_thread (gpointer user_data) while (*received_cred == ' ') received_cred++; + g_assert (str_has_prefix_case (received_cred, "Basic")); + received_cred += 5; + while (*received_cred == ' ') + received_cred++; + g_assert_cmpstr (base64_cred, ==, received_cred); g_free (base64_cred); } @@ -377,8 +374,6 @@ int main (int argc, test_init (argc, argv); - _wocky_http_proxy_get_type (); - g_test_add_func ("/http-proxy/instantiation", test_http_proxy_instantiation); diff --git a/wocky/Makefile.am b/wocky/Makefile.am index 1917a58..9871311 100644 --- a/wocky/Makefile.am +++ b/wocky/Makefile.am @@ -46,10 +46,6 @@ OPENSSL_SRC = \ GNUTLS_SRC = wocky-tls.c -PROXY_SRC = \ - wocky-http-proxy.h \ - wocky-http-proxy.c - handwritten_headers = \ wocky.h \ wocky-auth-handler.h \ @@ -189,12 +185,6 @@ else EXTRA_DIST += $(OPENSSL_SRC) endif -if HAVE_GIO_PROXY - handwritten_sources += $(PROXY_SRC) -else - EXTRA_DIST += $(PROXY_SRC) -endif - libwocky_la_SOURCES = $(handwritten_sources) $(built_sources) \ $(handwritten_headers) $(built_headers) diff --git a/wocky/wocky-connector.c b/wocky/wocky-connector.c index 89f4369..f3bb3c8 100644 --- a/wocky/wocky-connector.c +++ b/wocky/wocky-connector.c @@ -101,7 +101,6 @@ #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_CONNECTOR #include "wocky-debug-internal.h" -#include "wocky-http-proxy.h" #include "wocky-sasl-auth.h" #include "wocky-tls-handler.h" #include "wocky-tls-connector.h" @@ -580,11 +579,6 @@ wocky_connector_class_init (WockyConnectorClass *klass) oclass->dispose = wocky_connector_dispose; oclass->finalize = wocky_connector_finalize; -#if HAVE_GIO_PROXY - /* Ensure that HTTP Proxy extension is registered */ - _wocky_http_proxy_get_type (); -#endif - /** * WockyConnector:plaintext-auth-allowed: * @@ -837,37 +831,29 @@ connect_to_host_async (WockyConnector *connector, guint default_port) { WockyConnectorPrivate *priv = connector->priv; + const gchar *uri_format = "%s://%s"; + gchar *uri; -#if HAVE_GIO_PROXY - { - const gchar *uri_format = "%s://%s"; - gchar *uri; - - /* If host_and_port is an ipv6 address we must ensure it has [] around it */ - if (host_and_port[0] != '[') - { - const gchar *p; - - /* if host_and_port contains 2 ':' chars, it must be an ipv6 address */ - p = g_strstr_len (host_and_port, -1, ":"); - if (p != NULL) - p = g_strstr_len (p + 1, -1, ":"); - if (p != NULL) - uri_format = "%s://[%s]"; - } - - /* Legacy SSL mode is just like doing HTTPS, so let's trigger HTTPS - * proxy setting if any */ - uri = g_strdup_printf (uri_format, - priv->legacy_ssl ? "https" : "xmpp-client", host_and_port); - g_socket_client_connect_to_uri_async (priv->client, - uri, default_port, NULL, tcp_host_connected, connector); - g_free (uri); - } -#else - g_socket_client_connect_to_host_async (priv->client, - host_and_port, default_port, NULL, tcp_host_connected, connector); -#endif + /* If host_and_port is an ipv6 address we must ensure it has [] around it */ + if (host_and_port[0] != '[') + { + const gchar *p; + + /* if host_and_port contains 2 ':' chars, it must be an ipv6 address */ + p = g_strstr_len (host_and_port, -1, ":"); + if (p != NULL) + p = g_strstr_len (p + 1, -1, ":"); + if (p != NULL) + uri_format = "%s://[%s]"; + } + + /* Legacy SSL mode is just like doing HTTPS, so let's trigger HTTPS + * proxy setting if any */ + uri = g_strdup_printf (uri_format, + priv->legacy_ssl ? "https" : "xmpp-client", host_and_port); + g_socket_client_connect_to_uri_async (priv->client, + uri, default_port, NULL, tcp_host_connected, connector); + g_free (uri); } static void diff --git a/wocky/wocky-http-proxy.c b/wocky/wocky-http-proxy.c deleted file mode 100644 index b79b6ad..0000000 --- a/wocky/wocky-http-proxy.c +++ /dev/null @@ -1,430 +0,0 @@ - /* wocky-http-proxy.c: Source for WockyHttpProxy - * - * Copyright (C) 2010 Collabora, Ltd. - * @author Nicolas Dufresne - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include "wocky-http-proxy.h" - -#include -#include - - -struct _WockyHttpProxy -{ - GObject parent; -}; - -struct _WockyHttpProxyClass -{ - GObjectClass parent_class; -}; - -static void wocky_http_proxy_iface_init (GProxyInterface *proxy_iface); - -#define wocky_http_proxy_get_type _wocky_http_proxy_get_type -G_DEFINE_TYPE_WITH_CODE (WockyHttpProxy, wocky_http_proxy, G_TYPE_OBJECT, - 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, "http", 0)) - -static void -wocky_http_proxy_init (WockyHttpProxy *proxy) -{ -} - -#define HTTP_END_MARKER "\r\n\r\n" - -static gchar * -create_request (GProxyAddress *proxy_address, gboolean *has_cred) -{ - const gchar *hostname; - gint port; - const gchar *username; - const gchar *password; - GString *request; - gchar *ascii_hostname; - - if (has_cred) - *has_cred = FALSE; - - hostname = g_proxy_address_get_destination_hostname (proxy_address); - port = g_proxy_address_get_destination_port (proxy_address); - username = g_proxy_address_get_username (proxy_address); - password = g_proxy_address_get_password (proxy_address); - - request = g_string_new (NULL); - - ascii_hostname = g_hostname_to_ascii (hostname); - g_string_append_printf (request, - "CONNECT %s:%i HTTP/1.0\r\n" - "Host: %s:%i\r\n" - "Proxy-Connection: keep-alive\r\n" - "User-Agent: GLib/%i.%i\r\n", - ascii_hostname, port, - ascii_hostname, port, - GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION); - g_free (ascii_hostname); - - if (username != NULL && password != NULL) - { - gchar *cred; - gchar *base64_cred; - - if (has_cred) - *has_cred = TRUE; - - cred = g_strdup_printf ("%s:%s", username, password); - base64_cred = g_base64_encode ((guchar *) cred, strlen (cred)); - g_free (cred); - g_string_append_printf (request, - "Proxy-Authorization: %s\r\n", - base64_cred); - g_free (base64_cred); - } - - g_string_append (request, "\r\n"); - - return g_string_free (request, FALSE); -} - -static gboolean -check_reply (const gchar *buffer, gboolean has_cred, GError **error) -{ - gint err_code; - const gchar *ptr = buffer + 7; - - if (strncmp (buffer, "HTTP/1.", 7) != 0 - || (*ptr != '0' && *ptr != '1')) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, - "Bad HTTP proxy reply"); - return FALSE; - } - - ptr++; - while (*ptr == ' ') ptr++; - - err_code = atoi (ptr); - - if (err_code < 200 || err_code >= 300) - { - const gchar *msg_start; - gchar *msg; - - while (g_ascii_isdigit (*ptr)) - ptr++; - - while (*ptr == ' ') - ptr++; - - msg_start = ptr; - - ptr = strchr (msg_start, '\r'); - - if (ptr == NULL) - ptr = strchr (msg_start, '\0'); - - msg = g_strndup (msg_start, ptr - msg_start); - - if (err_code == 407) - { - if (has_cred) - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED, - "HTTP proxy authentication failed"); - else - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_NEED_AUTH, - "HTTP proxy authentication required"); - } - else if (msg[0] == '\0') - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, - "Connection failed due to broken HTTP reply"); - else - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, - "HTTP proxy connection failed: %i %s", - err_code, msg); - - g_free (msg); - return FALSE; - } - - return TRUE; -} - -static GIOStream * -wocky_http_proxy_connect (GProxy *proxy, - GIOStream *io_stream, - GProxyAddress *proxy_address, - GCancellable *cancellable, - GError **error) -{ - GInputStream *in; - GOutputStream *out; - GDataInputStream *data_in; - gchar *buffer; - gboolean has_cred; - - in = g_io_stream_get_input_stream (io_stream); - out = g_io_stream_get_output_stream (io_stream); - - data_in = g_data_input_stream_new (in); - g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (data_in), - FALSE); - - buffer = create_request (proxy_address, &has_cred); - - if (!g_output_stream_write_all (out, buffer, strlen (buffer), NULL, - cancellable, error)) - goto error; - - g_free (buffer); - buffer = g_data_input_stream_read_until (data_in, HTTP_END_MARKER, NULL, - cancellable, error); - g_object_unref (data_in); - data_in = NULL; - - if (buffer == NULL) - { - if (error && (*error == NULL)) - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, - "HTTP proxy server closed connection unexpectedly."); - goto error; - } - - if (!check_reply (buffer, has_cred, error)) - goto error; - - g_free (buffer); - - return g_object_ref (io_stream); - -error: - if (data_in != NULL) - g_object_unref (data_in); - - g_free (buffer); - return NULL; -} - - -typedef struct -{ - GSimpleAsyncResult *simple; - GIOStream *io_stream; - gchar *buffer; - gssize length; - gssize offset; - GDataInputStream *data_in; - gboolean has_cred; - GCancellable *cancellable; -} ConnectAsyncData; - -static void request_write_cb (GObject *source, - GAsyncResult *res, - gpointer user_data); -static void reply_read_cb (GObject *source, - GAsyncResult *res, - gpointer user_data); - -static void -free_connect_data (ConnectAsyncData *data) -{ - if (data->io_stream != NULL) - g_object_unref (data->io_stream); - - g_free (data->buffer); - - if (data->data_in != NULL) - g_object_unref (data->data_in); - - if (data->cancellable != NULL) - g_object_unref (data->cancellable); - - g_slice_free (ConnectAsyncData, data); -} - -static void -complete_async_from_error (ConnectAsyncData *data, GError *error) -{ - GSimpleAsyncResult *simple = data->simple; - - if (error == NULL) - g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, - "HTTP proxy server closed connection unexpectedly."); - - g_simple_async_result_set_from_error (data->simple, error); - g_error_free (error); - g_simple_async_result_set_op_res_gpointer (simple, NULL, NULL); - g_simple_async_result_complete (simple); - g_object_unref (simple); -} - -static void -do_write (GAsyncReadyCallback callback, ConnectAsyncData *data) -{ - GOutputStream *out; - out = g_io_stream_get_output_stream (data->io_stream); - g_output_stream_write_async (out, - data->buffer + data->offset, - data->length - data->offset, - G_PRIORITY_DEFAULT, data->cancellable, - callback, data); -} - -static void -wocky_http_proxy_connect_async (GProxy *proxy, - GIOStream *io_stream, - GProxyAddress *proxy_address, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - ConnectAsyncData *data; - GInputStream *in; - - simple = g_simple_async_result_new (G_OBJECT (proxy), - 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->buffer = create_request (proxy_address, &data->has_cred); - data->length = strlen (data->buffer); - data->offset = 0; - - do_write (request_write_cb, data); -} - -static void -request_write_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - GError *error = NULL; - ConnectAsyncData *data = user_data; - gssize written; - - written = g_output_stream_write_finish (G_OUTPUT_STREAM (source), - res, &error); - if (written < 0) - { - complete_async_from_error (data, error); - return; - } - - data->offset += written; - - if (data->offset == data->length) - { - g_free (data->buffer); - data->buffer = NULL; - - g_data_input_stream_read_until_async (data->data_in, - HTTP_END_MARKER, - G_PRIORITY_DEFAULT, - data->cancellable, - reply_read_cb, data); - - } - else - { - do_write (request_write_cb, data); - } -} - -static void -reply_read_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - GError *error = NULL; - ConnectAsyncData *data = user_data; - - data->buffer = g_data_input_stream_read_until_finish (data->data_in, - res, NULL, &error); - - if (data->buffer == NULL) - { - complete_async_from_error (data, error); - return; - } - - if (!check_reply (data->buffer, data->has_cred, &error)) - { - complete_async_from_error (data, error); - return; - } - - g_simple_async_result_complete (data->simple); - g_object_unref (data->simple); -} - -static GIOStream * -wocky_http_proxy_connect_finish (GProxy *proxy, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - ConnectAsyncData *data = g_simple_async_result_get_op_res_gpointer (simple); - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - - return g_object_ref (data->io_stream); -} - -static gboolean -wocky_http_proxy_supports_hostname (GProxy *proxy) -{ - return TRUE; -} - -static void -wocky_http_proxy_class_init (WockyHttpProxyClass *class) -{ -} - -static void -wocky_http_proxy_iface_init (GProxyInterface *proxy_iface) -{ - proxy_iface->connect = wocky_http_proxy_connect; - proxy_iface->connect_async = wocky_http_proxy_connect_async; - proxy_iface->connect_finish = wocky_http_proxy_connect_finish; - proxy_iface->supports_hostname = wocky_http_proxy_supports_hostname; -} diff --git a/wocky/wocky-http-proxy.h b/wocky/wocky-http-proxy.h deleted file mode 100644 index b9f9485..0000000 --- a/wocky/wocky-http-proxy.h +++ /dev/null @@ -1,46 +0,0 @@ - /* wocky-http-proxy.h: Header for WockyHttpProxy - * - * Copyright (C) 2010 Collabora, Ltd. - * @author Nicolas Dufresne - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#if !defined (WOCKY_COMPILATION) -# error "This is an internal header." -#endif - -#ifndef _WOCKY_HTTP_PROXY_H_ -#define _WOCKY_HTTP_PROXY_H_ - -#include - -G_BEGIN_DECLS - -#define WOCKY_TYPE_HTTP_PROXY (_wocky_http_proxy_get_type ()) -#define WOCKY_HTTP_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxy)) -#define WOCKY_HTTP_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxyClass)) -#define WOCKY_IS_HTTP_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), WOCKY_TYPE_HTTP_PROXY)) -#define WOCKY_IS_HTTP_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), WOCKY_TYPE_HTTP_PROXY)) -#define WOCKY_HTTP_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxyClass)) - -typedef struct _WockyHttpProxy WockyHttpProxy; -typedef struct _WockyHttpProxyClass WockyHttpProxyClass; - -GType _wocky_http_proxy_get_type (void); - -G_END_DECLS - -#endif /* _WOCKY_HTTP_PROXY_H_ */ -- 2.8.1