import gupnp-1.0.6-2.el8_4

This commit is contained in:
CentOS Sources 2021-06-09 08:55:21 -04:00 committed by Andrew Lukoshko
parent 239767b179
commit 9ce75f404d
4 changed files with 375 additions and 1 deletions

View File

@ -0,0 +1,180 @@
From 125e957092083ea37cf8ac712fa62587e3817242 Mon Sep 17 00:00:00 2001
From: Jens Georg <mail@jensge.org>
Date: Mon, 10 May 2021 11:45:57 +0200
Subject: [PATCH] Tests: Add test for host header validation
---
libgupnp/gupnp-context-private.h | 5 ++
libgupnp/gupnp-context.c | 25 ++++++++--
tests/gtest/test-bugs.c | 78 ++++++++++++++++++++++++++++++--
3 files changed, 99 insertions(+), 9 deletions(-)
diff --git a/libgupnp/gupnp-context-private.h b/libgupnp/gupnp-context-private.h
index 5848d02..a8b4a75 100644
--- a/libgupnp/gupnp-context-private.h
+++ b/libgupnp/gupnp-context-private.h
@@ -42,6 +42,11 @@ 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 --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index 0381474..ec88b93 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -1585,9 +1585,11 @@ out:
}
gboolean
-gupnp_context_validate_host_header (GUPnPContext *context,
- const char *host_header)
+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.
@@ -1610,8 +1612,11 @@ gupnp_context_validate_host_header (GUPnPContext *context,
goto out;
}
- const char *host_ip = gssdp_client_get_host_ip (GSSDP_CLIENT (context));
- gint context_port = gupnp_context_get_port (context);
+ // -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, "
@@ -1631,6 +1636,18 @@ gupnp_context_validate_host_header (GUPnPContext *context,
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 --git a/tests/gtest/test-bugs.c b/tests/gtest/test-bugs.c
index 0ffac76..24ec4ba 100644
--- a/tests/gtest/test-bugs.c
+++ b/tests/gtest/test-bugs.c
@@ -24,6 +24,7 @@
#endif
#include <libgupnp/gupnp.h>
+#include <libgupnp/gupnp-context-private.h>
struct _GUPnPServiceAction {
@@ -468,14 +469,81 @@ test_bgo_743233 (void)
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 ();
}
--
2.31.1

View File

@ -0,0 +1,63 @@
From 8ed9a525a97091c2a416c82f05e8311837cc7600 Mon Sep 17 00:00:00 2001
From: Jens Georg <mail@jensge.org>
Date: Wed, 2 Jun 2021 12:43:45 +0200
Subject: [PATCH] context: Use SoupURI instead of GUri
Do not bump the implicit requirement to GLib 2.66 for this version
---
libgupnp/gupnp-context.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index ec88b93..dda565e 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -1595,26 +1595,22 @@ validate_host_header (const char *host_header,
// [] from v6 addresses, splitting of the port etc.
char *uri_from_host = g_strconcat ("http://", host_header, NULL);
- char *host = NULL;
+ const 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);
+ SoupURI *uri = soup_uri_new (uri_from_host);
+ if (uri == NULL) {
+ g_debug ("Failed to parse HOST header %s from request",
+ host_header);
goto out;
}
+ host = soup_uri_get_host (uri);
+ port = soup_uri_get_port (uri);
+
// -1 means there was no :port; according to UDA this is allowed and
// defaults to 80, the HTTP port then
- if (port == -1) {
+ if (soup_uri_uses_default_port (uri)) {
port = 80;
}
@@ -1635,8 +1631,7 @@ validate_host_header (const char *host_header,
retval = g_str_equal (host, host_ip) && port == context_port;
out:
- g_clear_error (&error);
- g_free (host);
+ g_clear_pointer (&uri, soup_uri_free);
g_free (uri_from_host);
return retval;
--
2.31.1

View File

@ -0,0 +1,118 @@
From 05e964d48322ff23a65c6026d656e4494ace6ff9 Mon Sep 17 00:00:00 2001
From: Jens Georg <mail@jensge.org>
Date: Mon, 10 May 2021 10:34:36 +0200
Subject: [PATCH] service: Validate host header
Make sure that the host header matches the ip:port of the context.
This is in line with UDA (Host header is required and must match the
location url) and DLNA 7.2.24.1 (All communication has to use ip
addresses and not names)
Prevents DNS rebinding attacs against agains UPnP services
---
libgupnp/gupnp-context-private.h | 3 ++
libgupnp/gupnp-context.c | 51 ++++++++++++++++++++++++++++++++
libgupnp/gupnp-service.c | 13 ++++++++
3 files changed, 67 insertions(+)
diff --git a/libgupnp/gupnp-context-private.h b/libgupnp/gupnp-context-private.h
index 801d679..5848d02 100644
--- a/libgupnp/gupnp-context-private.h
+++ b/libgupnp/gupnp-context-private.h
@@ -39,6 +39,9 @@ _gupnp_context_add_server_handler_with_data (GUPnPContext *context,
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);
+
G_END_DECLS
#endif /* __GUPNP_CONTEXT_PRIVATE_H__ */
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index 1732bf4..0381474 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -1583,3 +1583,54 @@ out:
return retval;
}
+
+gboolean
+gupnp_context_validate_host_header (GUPnPContext *context,
+ const char *host_header)
+{
+ 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;
+ }
+
+ const char *host_ip = gssdp_client_get_host_ip (GSSDP_CLIENT (context));
+ gint context_port = gupnp_context_get_port (context);
+
+ 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 (uri_from_host);
+ return retval;
+}
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index 4235cab..50765f0 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -949,6 +949,19 @@ control_server_handler (SoupServer *server,
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");
--
2.31.1

View File

@ -1,6 +1,6 @@
Name: gupnp
Version: 1.0.6
Release: 1%{?dist}
Release: 2%{?dist}
Summary: A framework for creating UPnP devices & control points
License: LGPLv2+
@ -17,6 +17,11 @@ BuildRequires: vala
Requires: dbus
# https://gitlab.gnome.org/GNOME/gupnp/-/issues/24
Patch0: 0001-service-Validate-host-header.patch
Patch1: 0001-Tests-Add-test-for-host-header-validation.patch
Patch2: 0001-context-Use-SoupURI-instead-of-GUri.patch
%description
GUPnP is an object-oriented open source framework for creating UPnP
devices and control points, written in C using GObject and libsoup.
@ -39,6 +44,9 @@ This package contains developer documentation for %{name}.
%prep
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
# Use Python 3
sed -i '1s|^#! /usr/bin/env python$|#!/usr/bin/python3|' tools/gupnp-binding-tool
@ -79,6 +87,11 @@ find %{buildroot} -name '*.la' -delete
%doc %{_datadir}/gtk-doc/html/%{name}
%changelog
* Wed Jun 02 2021 Bastien Nocera <bnocera@redhat.com> - 1.0.6-2
+ gupnp-1.0.6-2
- Fix DNS rebind issue
- Resolves: #1964710
* Wed Sep 30 2020 Bastien Nocera <bnocera@redhat.com> - 1.0.6-1
+ gupnp-1.0.6-1
- Update to 1.0.6