Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gupnp for openSUSE:Factory checked in at 2021-06-05 23:30:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gupnp (Old) and /work/SRC/openSUSE:Factory/.gupnp.new.1898 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gupnp" Sat Jun 5 23:30:52 2021 rev:64 rq:896638 version:1.2.6 Changes: -------- --- /work/SRC/openSUSE:Factory/gupnp/gupnp.changes 2020-08-12 10:56:59.988758361 +0200 +++ /work/SRC/openSUSE:Factory/.gupnp.new.1898/gupnp.changes 2021-06-05 23:31:17.252412451 +0200 @@ -1,0 +2,45 @@ +Tue Jun 1 01:19:08 UTC 2021 - Ferdinand Thiessen <[email protected]> + +- Update to version 1.2.6 + + Fix CVE-2021-33516 ( boo#1186590 ) + + Fix potential fd leak in linux CM + + Fix potential NULL pointer dereference when evaluating unset + ServiceProxyActions + + Fix leaking the message string if an action is never sent + + Fix leaking the ServiceProxyAction if sending fails in + call_action + + Fix potential use-after-free if service proxy is + destroxed before libsoup request finishes in control point + + Fix potential data leak due to being vulnerable to DNS + rebind attacs + + Fix introspection annotation for send_action and + call_action_finish to prevent a double-free + + Fix introspection annotation for send_action_list + + Make ServiceIntrospection usable from gobject-introspection +- Fix dependencies + +------------------------------------------------------------------- +Thu May 27 17:02:15 UTC 2021 - Bj??rn Lie <[email protected]> + +- Update to version 1.2.6: + + Fix wrong dependency on GSSDP 1.2.4 +- Changes from version 1.2.5: + + Fix introspection annotation for send_action_list + + Fix potential fd leak in linux CM + + Fix potential NULL pointer dereference when evaluating unset + ServiceProxyActions + + Fix leaking the message string if an action is never sent + + Fix leaking the ServiceProxyAction if sending fails in + call_action + + Fix introspection annotation for send_action and + call_action_finish to prevent a double-free + + Make ServiceIntrospection usable from gobject-introspection + + Add Python example + + Add C example + + Fix JavaScript example + + Fix potential use-after-free if service proxy is destroxed + before libsoup request finishes in control point + + Fix potential data leak due to being vulnerable to DNS rebind + attacks + +------------------------------------------------------------------- Old: ---- gupnp-1.2.4.tar.xz New: ---- gupnp-1.2.6.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gupnp.spec ++++++ --- /var/tmp/diff_new_pack.zazn8g/_old 2021-06-05 23:31:17.884413550 +0200 +++ /var/tmp/diff_new_pack.zazn8g/_new 2021-06-05 23:31:17.884413550 +0200 @@ -1,7 +1,7 @@ # # spec file for package gupnp # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -21,7 +21,7 @@ %define sover 1.2 Name: gupnp -Version: 1.2.4 +Version: 1.2.6 Release: 0 Summary: Implementation of the UPnP specification License: LGPL-2.0-or-later @@ -29,16 +29,15 @@ URL: http://www.gupnp.org/ Source0: https://download.gnome.org/sources/gupnp/1.2/%{name}-%{version}.tar.xz Source1: baselibs.conf - BuildRequires: gtk-doc BuildRequires: meson BuildRequires: pkgconfig BuildRequires: pkgconfig(gio-2.0) >= 2.58 BuildRequires: pkgconfig(glib-2.0) >= 2.58 -BuildRequires: pkgconfig(gmodule-2.0) >= 2.58 -BuildRequires: pkgconfig(gobject-2.0) >= 2.58 +BuildRequires: pkgconfig(gmodule-2.0) >= 2.44 +BuildRequires: pkgconfig(gobject-2.0) >= 2.44 BuildRequires: pkgconfig(gobject-introspection-1.0) >= 0.6.4 -BuildRequires: pkgconfig(gssdp-1.2) >= 1.1.3 +BuildRequires: pkgconfig(gssdp-1.2) >= 1.2.3 BuildRequires: pkgconfig(libsoup-2.4) >= 2.48.0 BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(uuid) @@ -94,6 +93,7 @@ %prep %autosetup -p1 +sed -i 's|env python3|python3|' tools/gupnp-binding-tool-1.2 %build %meson \ ++++++ gupnp-1.2.4.tar.xz -> gupnp-1.2.6.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/NEWS new/gupnp-1.2.6/NEWS --- old/gupnp-1.2.4/NEWS 2020-08-09 23:13:20.448699000 +0200 +++ new/gupnp-1.2.6/NEWS 2021-05-24 16:34:52.796355200 +0200 @@ -1,3 +1,47 @@ +1.2.6 +===== +- Fix wrong dependency on GSSDP 1.2.4 + +Bugs fixed in this release: + - https://gitlab.gnome.org/GNOME/gupnp/issues/48 + +All contributors to this release: + - Jens Georg <[email protected]> + +1.2.5 +===== +- Fix introspection annotation for send_action_list +- Fix potential fd leak in linux CM +- Fix potential NULL pointer dereference when evaluating + unset ServiceProxyActions +- Fix leaking the message string if an action is never + sent +- Fix leaking the ServiceProxyAction if sending fails + in call_action +- Fix introspection annotation for send_action and + call_action_finish to prevent a double-free +- Make ServiceIntrospection usable from + gobject-introspection +- Add Python examle +- Add C example +- Fix JavaScript example +- Fix potential use-after-free if service proxy is + destroxed before libsoup request finishes in control + point +- Fix potential data leak due to being vulnerable to DNS + rebind attacs + +Bugs fixed in this release: + - https://gitlab.gnome.org/GNOME/gupnp/issues/47 + - https://gitlab.gnome.org/GNOME/gupnp/issues/46 + - https://gitlab.gnome.org/GNOME/gupnp/issues/23 + - https://gitlab.gnome.org/GNOME/gupnp/issues/24 + +All contributors to this release: + - Jens Georg <[email protected]> + - Doug Nazar <[email protected]> + - Andre Klapper <[email protected]> + 1.2.4 ===== - Fix subscription check on V6 link-local addresses diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/doc/meson.build new/gupnp-1.2.6/doc/meson.build --- old/gupnp-1.2.4/doc/meson.build 2020-08-09 23:13:20.448699000 +0200 +++ new/gupnp-1.2.6/doc/meson.build 2021-05-24 16:34:52.797355200 +0200 @@ -5,10 +5,9 @@ entities) if get_option('gtk_doc') -gnome.gtkdoc('gupnp', + gnome.gtkdoc('gupnp', main_xml : 'gupnp-docs.xml', - src_dir : [join_paths(meson.source_root(), 'libgupnp'), - join_paths(meson.build_root(), 'libgupnp')], + src_dir : ['libgupnp'], dependencies : libgupnp, scan_args : ['--ignore-decorators', 'G_DEPRECATED|G_GNUC_DEPRECATED,G_DEPRECATED_FOR'], ignore_headers : [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/examples/get-volume.c new/gupnp-1.2.6/examples/get-volume.c --- old/gupnp-1.2.4/examples/get-volume.c 1970-01-01 01:00:00.000000000 +0100 +++ new/gupnp-1.2.6/examples/get-volume.c 2021-05-24 16:34:52.798355300 +0200 @@ -0,0 +1,166 @@ +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. + +#include <glib.h> +#include <libgupnp/gupnp.h> + +char CONTENT_DIR[] = "urn:schemas-upnp-org:service:RenderingControl:1"; + +gboolean on_timeout(gpointer user_data) +{ + g_main_loop_quit ((GMainLoop*)(user_data)); + + return FALSE; +} + +void +gvalue_free (gpointer value) +{ + g_value_unset ((GValue *) value); + g_free (value); +} + +void +on_introspection (GObject *object, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + + GUPnPServiceIntrospection *i = gupnp_service_info_introspect_finish ( + GUPNP_SERVICE_INFO (object), + res, + &error); + + if (error != NULL) { + g_critical (error->message); + g_clear_error (&error); + } + + const GUPnPServiceActionInfo *info = + gupnp_service_introspection_get_action (i, "GetVolume"); + const char *state_variable_name = + ((GUPnPServiceActionArgInfo *) info->arguments->next->data) + ->related_state_variable; + + const char *channel = gupnp_service_introspection_get_state_variable ( + i, + state_variable_name) + ->allowed_values->data; + g_print ("Calling GetVolume for channel %s", channel); + GList *in_names = NULL; + in_names = g_list_prepend (in_names, g_strdup ("Channel")); + in_names = g_list_prepend (in_names, g_strdup ("InstanceID")); + GList *in_values = NULL; + GValue instance = G_VALUE_INIT; + g_value_init (&instance, G_TYPE_INT); + g_value_set_int (&instance, 0); + in_values = g_list_prepend (in_values, &instance); + GValue channel_v = G_VALUE_INIT; + g_value_init (&channel_v, G_TYPE_STRING); + g_value_set_string (&channel_v, channel); + + GUPnPServiceProxyAction *a = + gupnp_service_proxy_action_new_from_list ("GetVolume", + in_names, + in_values); + g_list_free_full (in_names, g_free); + g_list_free (in_values); + g_value_unset (&channel_v); + + g_boxed_copy (gupnp_service_proxy_action_get_type (), a); + + gupnp_service_proxy_call_action (GUPNP_SERVICE_PROXY (object), + a, + NULL, + &error); + g_boxed_free (gupnp_service_proxy_action_get_type (), a); + + + GList *out_names = NULL; + out_names = g_list_prepend (out_names, "CurrentVolume"); + GList *out_types = NULL; + out_types = + g_list_prepend (out_types, GSIZE_TO_POINTER (G_TYPE_STRING)); + GList *out_values = NULL; + + + gupnp_service_proxy_action_get_result_list (a, + out_names, + out_types, + &out_values, + &error); + g_list_free (out_types); + g_list_free (out_names); + + if (error != NULL) { + g_critical (error->message); + g_clear_error (&error); + } else { + g_print ("Current volume: %s\n", + g_value_get_string (out_values->data)); + } + g_list_free_full (out_values, gvalue_free); + + gupnp_service_proxy_action_unref (a); + g_object_unref (i); +} + + +void on_proxy_available (GUPnPControlPoint *cp, GUPnPServiceProxy *proxy, gpointer user_data) +{ + g_autofree char *id = + gupnp_service_info_get_id (GUPNP_SERVICE_INFO (proxy)); + + g_print ("Got ServiceProxy %s at %s\n", + id, + gupnp_service_info_get_location (GUPNP_SERVICE_INFO (proxy))); + g_print ("Introspecting service ...\n"); + gupnp_service_info_introspect_async (GUPNP_SERVICE_INFO (proxy), + NULL, + on_introspection, + NULL); +} + +int main(int argc, char *argv[]) +{ + GError *error = NULL; + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + + GUPnPContext *context = gupnp_context_new ("wlp3s0", 0, &error); + + if (error != NULL) { + g_error (error->message); + } + + GUPnPControlPoint *cp = gupnp_control_point_new (context, CONTENT_DIR); + g_signal_connect (cp, "service-proxy-available", G_CALLBACK (on_proxy_available), NULL); + gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE); + + g_timeout_add_seconds (10, on_timeout, loop); + + g_main_loop_run (loop); + + g_object_unref (cp); + g_object_unref (context); + g_main_loop_unref (loop); + + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/examples/get-volume.js new/gupnp-1.2.6/examples/get-volume.js --- old/gupnp-1.2.4/examples/get-volume.js 2020-08-09 23:13:20.448699000 +0200 +++ new/gupnp-1.2.6/examples/get-volume.js 2021-05-24 16:34:52.798355300 +0200 @@ -1,9 +1,4 @@ #!/usr/bin/gjs -// -// Copyright (c) 2016, Jens Georg <[email protected]> -// -// All rights reserved. -// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // @@ -29,27 +24,40 @@ imports.gi.versions.GUPnP = "1.2" const Mainloop = imports.mainloop; +const GObject = imports.gi.GObject; const GUPnP = imports.gi.GUPnP; +const GLib = imports.gi.GLib; -const CONTENT_DIR = "urn:schemas-upnp-org:service:RenderingControl:2"; +const CONTENT_DIR = "urn:schemas-upnp-org:service:RenderingControl:1"; + +function on_action(proxy, res) { + let action = proxy.call_action_finish (res); + let [success, volume] = action.get_result_list(["CurrentVolume"], [GObject.TYPE_FLOAT]); + print(volume); +} -function _on_ready () { +function on_service_introspection(proxy, res) { + var result = proxy.introspect_finish(res); + var action_info = result.get_action("GetVolume") + var state_variable_name = action_info.arguments[1].related_state_variable; + + var channel = result.get_state_variable (state_variable_name); + + print ("Calling GetVolume for channel ", channel.allowed_values[0]); + var action = GUPnP.ServiceProxyAction.new_from_list("GetVolume", ["InstanceID", "Channel"], [0, channel.allowed_values[0]]); + proxy.call_action_async (action, null, on_action); } function _on_sp_available (cp, proxy) { - print ("Got Proxy"); - for (var i = 0; i < 1000; ++i) { - proxy.send_action_list ("GetVolume", - ["InstanceId", "Channel"], - [0, 0], - [], - []); - } + print ("Got ServiceProxy ", proxy.get_id(), proxy.get_location()); + print ("Introspecting service..."); + proxy.introspect_async(null, on_service_introspection) } -var context = new GUPnP.Context ( {'interface': "lo"}); +var context = new GUPnP.Context ( {'interface': "wlp3s0"}); context.init(null); var cp = new GUPnP.ControlPoint ( {'client': context, 'target' : CONTENT_DIR}); cp.connect ("service-proxy-available", _on_sp_available); cp.active = true; -Mainloop.run (""); +GLib.timeout_add_seconds (GLib.PRIORITY_LOW, 10, () => { Mainloop.quit(); return false; }) +Mainloop.run (); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/examples/get-volume.py new/gupnp-1.2.6/examples/get-volume.py --- old/gupnp-1.2.4/examples/get-volume.py 1970-01-01 01:00:00.000000000 +0100 +++ new/gupnp-1.2.6/examples/get-volume.py 2021-05-24 16:34:52.799355300 +0200 @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. + +import gi +gi.require_version('GUPnP', '1.2') + +from gi.repository import GUPnP +from gi.repository import GLib +from gi.repository import GObject + +RENDERING_CONTROL = "urn:schemas-upnp-org:service:RenderingControl:1" + +def do_quit(): + global l + + l.quit() + return False + +def on_service_introspection(proxy, res): + result = proxy.introspect_finish(res) + action_info = result.get_action('GetVolume') + state_variable_name = action_info.arguments[1].related_state_variable + + channel = result.get_state_variable(state_variable_name) + print (f'Calling GetVolume for channel {channel.allowed_values[0]}') + + action = GUPnP.ServiceProxyAction.new_from_list('GetVolume', ["InstanceID", "Channel"], [0, channel.allowed_values[0]]) + proxy.call_action (action, None) + success, [volume] = action.get_result_list (["CurrentVolume"], [GObject.TYPE_FLOAT]) + print(volume) + +def on_sp_available(cp, proxy): + print(f'Got ServiceProxy {proxy.get_id()} at {proxy.get_location()}') + print('Introspecting service...') + proxy.introspect_async(None, on_service_introspection) + +if __name__ == '__main__': + global l + print("Looking for renderers and querying volumes fo 10s") + + l = GLib.MainLoop() + context = GUPnP.Context.new ('wlp3s0', 0) + cp = GUPnP.ControlPoint.new (context, RENDERING_CONTROL) + cp.set_active (True) + + cp.connect ('service-proxy-available', on_sp_available) + GLib.timeout_add_seconds (10, do_quit) + l.run() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/examples/meson.build new/gupnp-1.2.6/examples/meson.build --- old/gupnp-1.2.4/examples/meson.build 2020-08-09 23:13:20.448699000 +0200 +++ new/gupnp-1.2.6/examples/meson.build 2021-05-24 16:34:52.799355300 +0200 @@ -10,3 +10,9 @@ 'light-client.c', dependencies : gupnp ) + +executable( + 'get-volume', + 'get-volume.c', + dependencies: gupnp +) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/gupnp.doap new/gupnp-1.2.6/gupnp.doap --- old/gupnp-1.2.4/gupnp.doap 2020-08-09 23:13:20.448699000 +0200 +++ new/gupnp-1.2.6/gupnp.doap 2021-05-24 16:34:52.799355300 +0200 @@ -30,13 +30,6 @@ <maintainer> <foaf:Person> - <foaf:name>Ross Burton</foaf:name> - <foaf:mbox rdf:resource="mailto:[email protected]" /> - <gnome:userid>rburton</gnome:userid> - </foaf:Person> - </maintainer> - <maintainer> - <foaf:Person> <foaf:name>Jens Georg</foaf:name> <foaf:mbox rdf:resource="mailto:[email protected]" /> <gnome:userid>jensgeorg</gnome:userid> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-context-private.h new/gupnp-1.2.6/libgupnp/gupnp-context-private.h --- old/gupnp-1.2.4/libgupnp/gupnp-context-private.h 2020-08-09 23:13:20.452699200 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-context-private.h 2021-05-24 16:34:52.800355200 +0200 @@ -43,6 +43,14 @@ G_GNUC_INTERNAL gboolean gupnp_context_ip_is_ours (GUPnPContext *context, const char *address); +G_GNUC_INTERNAL gboolean +gupnp_context_validate_host_header (GUPnPContext *context, const char *host); + +gboolean +validate_host_header (const char *host_header, + const char *host_ip, + guint context_port); + G_END_DECLS #endif /* GUPNP_CONTEXT_PRIVATE_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-context.c new/gupnp-1.2.6/libgupnp/gupnp-context.c --- old/gupnp-1.2.4/libgupnp/gupnp-context.c 2020-08-09 23:13:20.452699200 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-context.c 2021-05-24 16:34:52.801355400 +0200 @@ -331,10 +331,7 @@ context = GUPNP_CONTEXT (object); priv = gupnp_context_get_instance_private (context); - if (priv->session) { - g_object_unref (priv->session); - priv->session = NULL; - } + g_clear_object (&priv->session); while (priv->host_path_datas) { HostPathData *data; @@ -344,10 +341,7 @@ gupnp_context_unhost_path (context, data->server_path); } - if (priv->server) { - g_object_unref (priv->server); - priv->server = NULL; - } + g_clear_object (&priv->server); /* Call super */ object_class = G_OBJECT_CLASS (gupnp_context_parent_class); @@ -1715,3 +1709,71 @@ return retval; } + +gboolean +validate_host_header (const char *host_header, + const char *host_ip, + guint context_port) +{ + + gboolean retval = FALSE; + // Be lazy and let GUri do the heavy lifting here, such as stripping the + // [] from v6 addresses, splitting of the port etc. + char *uri_from_host = g_strconcat ("http://", host_header, NULL); + + char *host = NULL; + int port = 0; + GError *error = NULL; + + g_uri_split_network (uri_from_host, + G_URI_FLAGS_NONE, + NULL, + &host, + &port, + &error); + + if (error != NULL) { + g_debug ("Failed to parse HOST header from request: %s", + error->message); + goto out; + } + + // -1 means there was no :port; according to UDA this is allowed and + // defaults to 80, the HTTP port then + if (port == -1) { + port = 80; + } + + if (!g_str_equal (host, host_ip)) { + g_debug ("Mismatch between host header and host IP (%s, " + "expected: %s)", + host, + host_ip); + } + + if (port != context_port) { + g_debug ("Mismatch between host header and host port (%d, " + "expected %d)", + port, + context_port); + } + + retval = g_str_equal (host, host_ip) && port == context_port; + +out: + g_clear_error (&error); + g_free (host); + g_free (uri_from_host); + + return retval; +} + +gboolean +gupnp_context_validate_host_header (GUPnPContext *context, + const char *host_header) +{ + return validate_host_header ( + host_header, + gssdp_client_get_host_ip (GSSDP_CLIENT (context)), + gupnp_context_get_port (context)); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-control-point.c new/gupnp-1.2.6/libgupnp/gupnp-control-point.c --- old/gupnp-1.2.4/libgupnp/gupnp-control-point.c 2020-08-09 23:13:20.452699200 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-control-point.c 2021-05-24 16:34:52.801355400 +0200 @@ -115,6 +115,7 @@ g_free (data->udn); g_free (data->service_type); g_free (data->description_url); + g_object_unref (data->control_point); g_slice_free (GetDescriptionURLData, data); } @@ -736,7 +737,7 @@ http_request_set_accept_language (data->message); - data->control_point = control_point; + data->control_point = g_object_ref (control_point); data->udn = g_strdup (udn); data->service_type = g_strdup (service_type); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-linux-context-manager.c new/gupnp-1.2.6/libgupnp/gupnp-linux-context-manager.c --- old/gupnp-1.2.4/libgupnp/gupnp-linux-context-manager.c 2020-08-09 23:13:20.452699200 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-linux-context-manager.c 2021-05-24 16:34:52.803355500 +0200 @@ -943,8 +943,6 @@ priv->fd = socket (AF_INET, SOCK_DGRAM, 0); if (priv->fd < 0) { - priv->fd = 0; - g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), @@ -1045,6 +1043,7 @@ GUPnPLinuxContextManagerPrivate *priv; priv = gupnp_linux_context_manager_get_instance_private (self); + priv->fd = -1; priv->nl_seq = 0; @@ -1087,8 +1086,10 @@ NULL); cleanup: if (error) { - if (priv->fd > 0) + if (priv->fd >= 0) { close (priv->fd); + priv->fd = -1; + } g_warning ("Failed to setup Linux context manager: %s", error->message); @@ -1129,9 +1130,9 @@ priv->netlink_socket = NULL; } - if (priv->fd != 0) { + if (priv->fd >= 0) { close (priv->fd); - priv->fd = 0; + priv->fd = -1; } if (priv->interfaces) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-service-introspection.c new/gupnp-1.2.6/libgupnp/gupnp-service-introspection.c --- old/gupnp-1.2.4/libgupnp/gupnp-service-introspection.c 2020-08-09 23:13:20.456699100 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-service-introspection.c 2021-05-24 16:34:52.805355300 +0200 @@ -103,10 +103,23 @@ } g_list_free_full (variable->allowed_values, g_free); +} + +static void +gupnp_service_state_variable_info_free ( + GUPnPServiceStateVariableInfo *variable); - g_slice_free (GUPnPServiceStateVariableInfo, variable); +static void +gupnp_service_state_variable_info_relase (GUPnPServiceStateVariableInfo *info) +{ + g_rc_box_release_full (info, (GDestroyNotify)gupnp_service_state_variable_info_free); } +G_DEFINE_BOXED_TYPE(GUPnPServiceStateVariableInfo, + gupnp_service_state_variable_info, + g_rc_box_acquire, + gupnp_service_state_variable_info_relase) + static void gupnp_service_introspection_init (GUPnPServiceIntrospection *introspection) { @@ -147,10 +160,22 @@ { g_free (argument->name); g_free (argument->related_state_variable); +} - g_slice_free (GUPnPServiceActionArgInfo, argument); +static void +gupnp_service_action_arg_info_unref (GUPnPServiceActionArgInfo *argument) +{ + g_rc_box_release_full ( + argument, + (GDestroyNotify) gupnp_service_action_arg_info_free); } +G_DEFINE_BOXED_TYPE (GUPnPServiceActionArgInfo, + gupnp_service_action_arg_info, + g_rc_box_acquire, + gupnp_service_action_arg_info_unref) + + /** * gupnp_service_action_info_free: * @argument: A #GUPnPServiceActionInfo @@ -163,10 +188,23 @@ { g_free (action_info->name); g_list_free_full (action_info->arguments, - (GDestroyNotify) gupnp_service_action_arg_info_free); - g_slice_free (GUPnPServiceActionInfo, action_info); + (GDestroyNotify) gupnp_service_action_arg_info_unref); +} + + +static void +gupnp_service_action_info_unref (GUPnPServiceActionInfo *argument) +{ + g_rc_box_release_full ( + argument, + (GDestroyNotify) gupnp_service_action_info_free); } +G_DEFINE_BOXED_TYPE (GUPnPServiceActionInfo, + gupnp_service_action_info, + g_rc_box_acquire, + gupnp_service_action_info_unref) + static void gupnp_service_introspection_finalize (GObject *object) { @@ -177,10 +215,10 @@ priv = gupnp_service_introspection_get_instance_private (introspection); g_list_free_full (priv->variables, - (GDestroyNotify) gupnp_service_state_variable_info_free); + (GDestroyNotify) gupnp_service_state_variable_info_relase); g_list_free_full (priv->actions, - (GDestroyNotify) gupnp_service_action_info_free); + (GDestroyNotify) gupnp_service_action_info_unref); /* Contents don't need to be freed, they were owned by priv->variables */ @@ -466,7 +504,7 @@ return NULL; } - variable = g_slice_new0 (GUPnPServiceStateVariableInfo); + variable = g_rc_box_new0(GUPnPServiceStateVariableInfo); success = set_variable_type (variable, data_type); g_free (data_type); @@ -522,7 +560,7 @@ return NULL; } - argument = g_slice_new0 (GUPnPServiceActionArgInfo); + argument = g_rc_box_new0 (GUPnPServiceActionArgInfo); argument->name = name; argument->related_state_variable = state_var; @@ -604,7 +642,7 @@ if (!name) continue; - action_info = g_slice_new0 (GUPnPServiceActionInfo); + action_info = g_rc_box_new0 (GUPnPServiceActionInfo); action_info->name = name; action_info->arguments = get_action_arguments (action_node); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-service-introspection.h new/gupnp-1.2.6/libgupnp/gupnp-service-introspection.h --- old/gupnp-1.2.4/libgupnp/gupnp-service-introspection.h 2020-08-09 23:13:20.456699100 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-service-introspection.h 2021-05-24 16:34:52.805355300 +0200 @@ -31,6 +31,10 @@ #define GUPNP_TYPE_SERVICE_INTROSPECTION \ (gupnp_service_introspection_get_type ()) +#define GUPNP_TYPE_SERVICE_ACTION_INFO (gupnp_service_action_info_get_type()) +#define GUPNP_TYPE_SERVICE_ACTION_ARG_INFO (gupnp_service_action_arg_info_get_type()) + + G_DECLARE_FINAL_TYPE (GUPnPServiceIntrospection, gupnp_service_introspection, GUPNP, @@ -66,6 +70,8 @@ char *related_state_variable; gboolean retval; } GUPnPServiceActionArgInfo; +GType +gupnp_service_action_arg_info_get_type (void); /** * GUPnPServiceActionInfo: @@ -80,6 +86,9 @@ GList *arguments; /* list of #GUPnPServiceActionArgInfo */ } GUPnPServiceActionInfo; +GType +gupnp_service_action_info_get_type (void); + /** * GUPnPServiceStateVariableInfo: * @name: The name of the state variable. @@ -112,6 +121,8 @@ GList *allowed_values; } GUPnPServiceStateVariableInfo; +GType +gupnp_service_state_variable_info_get_type (void); const GList * gupnp_service_introspection_list_action_names diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-service-proxy-action.c new/gupnp-1.2.6/libgupnp/gupnp-service-proxy-action.c --- old/gupnp-1.2.4/libgupnp/gupnp-service-proxy-action.c 2020-08-09 23:13:20.456699100 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-service-proxy-action.c 2021-05-24 16:34:52.806355500 +0200 @@ -61,6 +61,15 @@ xmlDoc *response; int code; + if (action->msg == NULL) { + g_set_error (error, + GUPNP_SERVER_ERROR, + GUPNP_SERVER_ERROR_INVALID_RESPONSE, + "No message, the action was not sent?"); + + return NULL; + } + /* Check for errors */ switch (action->msg->status_code) { case SOUP_STATUS_OK: @@ -221,6 +230,10 @@ g_clear_object (&action->cancellable); g_clear_error (&action->error); g_clear_object (&action->msg); + if (action->msg_str != NULL) { + g_string_free (action->msg_str, TRUE); + action->msg_str = NULL; + } g_free (action->name); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-service-proxy.c new/gupnp-1.2.6/libgupnp/gupnp-service-proxy.c --- old/gupnp-1.2.4/libgupnp/gupnp-service-proxy.c 2020-08-09 23:13:20.456699100 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-service-proxy.c 2021-05-24 16:34:52.806355500 +0200 @@ -481,7 +481,7 @@ } /** - * gupnp_service_proxy_send_action_list: (rename-to gupnp_service_proxy_send_action_list) + * gupnp_service_proxy_send_action_list: * @proxy: (transfer none) : A #GUPnPServiceProxy * @action: An action * @in_names: (element-type utf8) (transfer none): #GList of 'in' parameter @@ -724,6 +724,7 @@ ret->msg_str->len); g_string_free (ret->msg_str, FALSE); + ret->msg_str = NULL; } static void @@ -2065,7 +2066,7 @@ /** * gupnp_service_proxy_call_action_async: * @proxy: (transfer none): A #GUPnPServiceProxy - * @action: An action + * @action: (transfer none): A #GUPnPServiceProxyAction to call * @cancellable: (allow-none): A #GCancellable which can be used to cancel the * current action call * @callback: (scope async): A #GAsyncReadyCallback to call when the action is @@ -2114,7 +2115,7 @@ * Finish an asynchronous call initiated with * gupnp_service_proxy_call_action_async(). * - * Returns: %NULL, if the call had an error, the action otherwise. + * Returns: (nullable) (transfer none): %NULL, if the call had an error, the action otherwise. */ GUPnPServiceProxyAction * gupnp_service_proxy_call_action_finish (GUPnPServiceProxy *proxy, @@ -2129,14 +2130,14 @@ /** * gupnp_service_proxy_call_action: * @proxy: (transfer none): A #GUPnPServiceProxy - * @action: An action + * @action: (transfer none): An action * @cancellable: (allow-none): A #GCancellable which can be used to cancel the * current action call * @error: (allow-none): Return location for a #GError, or %NULL. * * Synchronously call the @action on the remote UPnP service. * - * Returns: %NULL on error, @action if successful. + * Returns: (nullable)(transfer none): %NULL on error, @action if successful. */ GUPnPServiceProxyAction * gupnp_service_proxy_call_action (GUPnPServiceProxy *proxy, @@ -2151,6 +2152,9 @@ prepare_action_msg (proxy, action, cancellable); + /* prepare_action_msg has queued the message, so remove it */ + gupnp_service_proxy_remove_action (proxy, action); + if (action->error != NULL) { g_propagate_error (error, g_error_copy (action->error)); @@ -2167,9 +2171,6 @@ soup_session_send_message (session, action->msg); } - /* prepare_action_msg has queued the message, so remove it */ - gupnp_service_proxy_remove_action (proxy, action); - if (action->msg->status_code == SOUP_STATUS_CANCELLED) { action->error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/gupnp-service.c new/gupnp-1.2.6/libgupnp/gupnp-service.c --- old/gupnp-1.2.4/libgupnp/gupnp-service.c 2020-08-09 23:13:20.456699100 +0200 +++ new/gupnp-1.2.6/libgupnp/gupnp-service.c 2021-05-24 16:34:52.807355400 +0200 @@ -954,6 +954,19 @@ context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (service)); + const char *host_header = + soup_message_headers_get_one (msg->request_headers, "Host"); + + if (!gupnp_context_validate_host_header (context, host_header)) { + g_warning ("Host header mismatch, expected %s:%d, got %s", + gssdp_client_get_host_ip (GSSDP_CLIENT (context)), + gupnp_context_get_port (context), + host_header); + + soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED); + return; + } + /* Get action name */ soap_action = soup_message_headers_get_one (msg->request_headers, "SOAPAction"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/libgupnp/meson.build new/gupnp-1.2.6/libgupnp/meson.build --- old/gupnp-1.2.4/libgupnp/meson.build 2020-08-09 23:13:20.460699000 +0200 +++ new/gupnp-1.2.6/libgupnp/meson.build 2021-05-24 16:34:52.810355400 +0200 @@ -117,16 +117,22 @@ ) pkg.generate( - libraries : libgupnp, + libgupnp, subdirs: 'gupnp-1.2', name : 'gupnp-1.2', - requires : dependencies, + requires : ['glib-2.0', 'gio-2.0', 'gssdp-1.2'], description : 'GObject-based UPnP library', version : meson.project_version(), filebase : 'gupnp-1.2' ) if get_option('introspection') + gir_includes = ['GObject-2.0', 'Gio-2.0', 'Soup-2.4', 'libxml2-2.0'] + if gssdp_dep.type_name() == 'internal' + gir_includes += subproject('gssdp-1.2').get_variable('gir').get(0) + else + gir_includes += 'GSSDP-1.2' + endif gir = gnome.generate_gir( libgupnp, sources : headers + sources + enums, @@ -136,7 +142,7 @@ symbol_prefix : 'gupnp', identifier_prefix : 'GUPnP', export_packages : 'gupnp-1.2', - includes : ['GObject-2.0', 'Gio-2.0', 'Soup-2.4', 'GSSDP-1.2', 'libxml2-2.0'], + includes : gir_includes, install : true, extra_args : '-DGOBJECT_INTROSPECTION_SKIP' ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/meson.build new/gupnp-1.2.6/meson.build --- old/gupnp-1.2.4/meson.build 2020-08-09 23:13:20.460699000 +0200 +++ new/gupnp-1.2.6/meson.build 2021-05-24 16:34:52.810355400 +0200 @@ -1,4 +1,4 @@ -project('gupnp', 'c', version : '1.2.4', meson_version : '>= 0.48.0') +project('gupnp', 'c', version : '1.2.6', meson_version : '>= 0.53.0') gnome = import('gnome') pkg = import('pkgconfig') @@ -14,17 +14,19 @@ conf.set('HAVE_LINUX_WIRELESS_H', cc.has_header('linux/wireless.h')) config_h = configure_file(output : 'config.h', configuration : conf) -add_global_arguments('-DHAVE_CONFIG_H=1', language : 'c') +add_project_arguments('-DHAVE_CONFIG_H=1', language : 'c') guul = subproject('guul', default_options : ['default_library=static']) +gssdp_dep = dependency('gssdp-1.2', version : '>= 1.2.3', default_options: ['sniffer=false']) + dependencies = [ dependency('glib-2.0', version : '>= 2.58'), dependency('gio-2.0', version : '>= 2.58'), dependency('gmodule-2.0', version : '>= 2.44'), dependency('gobject-2.0', version : '>= 2.44'), - dependency('gssdp-1.2', version : '>= 1.2.3'), dependency('libsoup-2.4', version : '>= 2.48.0'), + gssdp_dep, dependency('libxml-2.0') ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/subprojects/gssdp-1.2.wrap new/gupnp-1.2.6/subprojects/gssdp-1.2.wrap --- old/gupnp-1.2.4/subprojects/gssdp-1.2.wrap 1970-01-01 01:00:00.000000000 +0100 +++ new/gupnp-1.2.6/subprojects/gssdp-1.2.wrap 2021-05-24 16:34:52.810355400 +0200 @@ -0,0 +1,8 @@ +[wrap-git] +url = https://gitlab.gnome.org/GNOME/gssdp.git +revision = master +depth = 1 + +[provides] +dependency_name = gssdp-1.2 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/tests/gtest/test-bugs.c new/gupnp-1.2.6/tests/gtest/test-bugs.c --- old/gupnp-1.2.4/tests/gtest/test-bugs.c 2020-08-09 23:13:20.460699000 +0200 +++ new/gupnp-1.2.6/tests/gtest/test-bugs.c 2021-05-24 16:34:52.812355500 +0200 @@ -25,6 +25,7 @@ #include <libgupnp/gupnp.h> #include <libgupnp/gupnp-service-private.h> +#include <libgupnp/gupnp-context-private.h> static GUPnPContext * create_context (guint16 port, GError **error) { @@ -469,14 +470,81 @@ g_object_unref (context); } +static void +test_ggo_24 (void) +{ + // IPv4 + g_assert ( + validate_host_header ("127.0.0.1:4711", "127.0.0.1", 4711)); + + g_assert ( + validate_host_header ("127.0.0.1", "127.0.0.1", 80)); + + g_assert_false ( + validate_host_header ("example.com", "127.0.0.1", 4711)); + + g_assert_false ( + validate_host_header ("example.com:80", "127.0.0.1", 4711)); + + g_assert_false ( + validate_host_header ("example.com:4711", "127.0.0.1", 4711)); + + g_assert_false ( + validate_host_header ("192.168.1.2:4711", "127.0.0.1", 4711)); + + g_assert_false ( + validate_host_header ("[fe80::01]", "127.0.0.1", 4711)); + + // Link ids should not be parsed + g_assert_false ( + validate_host_header ("[fe80::01%1]", "127.0.0.1", 4711)); + + g_assert_false ( + validate_host_header ("[fe80::01%eth0]", "127.0.0.1", 4711)); + + // IPv6 + g_assert ( + validate_host_header ("[::1]:4711", "::1", 4711)); + + g_assert ( + validate_host_header ("[::1]", "::1", 80)); + + // Host header needs to be enclosed in [] even without port + g_assert_false ( + validate_host_header ("::1", "::1", 80)); + + g_assert_false ( + validate_host_header ("example.com", "::1", 4711)); + + g_assert_false ( + validate_host_header ("example.com:80", "::1", 4711)); + + g_assert_false ( + validate_host_header ("example.com:4711", "::1", 4711)); + + g_assert_false ( + validate_host_header ("192.168.1.2:4711", "::1", 4711)); + + g_assert_false ( + validate_host_header ("[fe80::01]", "::1", 4711)); + + // Link ids should not be parsed + g_assert_false ( + validate_host_header ("[fe80::01%1]", "fe80::acab", 4711)); + + g_assert_false ( + validate_host_header ("[fe80::01%eth0]", "fe80::acab", 4711)); +} + int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_add_func ("/bugs/696762", test_bgo_696762); - g_test_add_func ("/bugs/678701", test_bgo_678701); - g_test_add_func ("/bugs/690400", test_bgo_690400); - g_test_add_func ("/bugs/722696", test_bgo_722696); - g_test_add_func ("/bugs/743233", test_bgo_743233); + g_test_add_func ("/bugs/bgo/696762", test_bgo_696762); + g_test_add_func ("/bugs/bgo/678701", test_bgo_678701); + g_test_add_func ("/bugs/bgo/690400", test_bgo_690400); + g_test_add_func ("/bugs/bgo/722696", test_bgo_722696); + g_test_add_func ("/bugs/bgo/743233", test_bgo_743233); + g_test_add_func ("/bugs/ggo/24", test_ggo_24); return g_test_run (); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gupnp-1.2.4/vala/meson.build new/gupnp-1.2.6/vala/meson.build --- old/gupnp-1.2.4/vala/meson.build 2020-08-09 23:13:20.460699000 +0200 +++ new/gupnp-1.2.6/vala/meson.build 2021-05-24 16:34:52.813355400 +0200 @@ -1,5 +1,14 @@ +if gssdp_dep.type_name() == 'internal' + gssdp_vala_package = subproject('gssdp-1.2').get_variable('vapi') + gssdp_gir_dirs = subproject('gssdp-1.2').get_variable('gssdp_gir_dir') +else + gssdp_vala_package = 'gssdp-1.2' + gssdp_gir_dirs = [] +endif gnome.generate_vapi('gupnp-1.2', sources : [gir.get(0), 'gupnp-1.2-custom.vala'], - packages : ['gssdp-1.2', 'gio-2.0', 'libsoup-2.4', 'libxml-2.0'], - install : true) + packages : [gssdp_vala_package, 'gio-2.0', 'libsoup-2.4', 'libxml-2.0'], + gir_dirs : gssdp_gir_dirs, + install : true +)
