import gupnp-1.0.6-2.el8_4
This commit is contained in:
parent
239767b179
commit
9ce75f404d
180
SOURCES/0001-Tests-Add-test-for-host-header-validation.patch
Normal file
180
SOURCES/0001-Tests-Add-test-for-host-header-validation.patch
Normal 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
|
||||
|
63
SOURCES/0001-context-Use-SoupURI-instead-of-GUri.patch
Normal file
63
SOURCES/0001-context-Use-SoupURI-instead-of-GUri.patch
Normal 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
|
||||
|
118
SOURCES/0001-service-Validate-host-header.patch
Normal file
118
SOURCES/0001-service-Validate-host-header.patch
Normal 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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user