diff --git a/src/ws/cockpitchannelresponse.c b/src/ws/cockpitchannelresponse.c index bf01dba30233..fe30e207d264 100644 --- a/src/ws/cockpitchannelresponse.c +++ b/src/ws/cockpitchannelresponse.c @@ -601,6 +601,7 @@ cockpit_channel_response_serve (CockpitWebService *service, gchar *channel = NULL; gpointer key; gpointer value; + gboolean allow_multihost; g_return_if_fail (COCKPIT_IS_WEB_SERVICE (service)); g_return_if_fail (in_headers != NULL); @@ -614,6 +615,14 @@ cockpit_channel_response_serve (CockpitWebService *service, goto out; } + allow_multihost = cockpit_conf_bool ("WebService", "AllowMultiHost", ALLOW_MULTIHOST_DEFAULT); + if (!allow_multihost && g_strcmp0 (host, "localhost") != 0) + { + cockpit_web_response_error (response, 403, NULL, NULL); + handled = TRUE; + goto out; + } + if (quoted_etag) { cache_type = COCKPIT_WEB_RESPONSE_CACHE; diff --git a/test/verify/check-shell-multi-machine b/test/verify/check-shell-multi-machine index 9b49b1ee610a..cd4268ef0409 100755 --- a/test/verify/check-shell-multi-machine +++ b/test/verify/check-shell-multi-machine @@ -18,6 +18,7 @@ # along with Cockpit; If not, see . import re +import subprocess import time import testlib @@ -372,6 +373,36 @@ class TestMultiMachine(testlib.MachineCase): self.allow_hostkey_messages() self.allow_journal_messages(".* Failed to resolve hostname bad .*") + # Check whether AllowMultiHost blocks access already in cockpit-ws. + + self.enable_multihost(m) + self.setup_ssh_auth() + + # login into cockpit on machine1 + self.login_and_go("/system") + cookie = b.cookie("cockpit") + + def http_code(url): + return int(subprocess.check_output(["curl", + "--silent", + "-b", f"cockpit={cookie['value']}", + "-o", "/dev/null", "-w", "%{http_code" + "}", + f"http://{b.address}:{b.port}{url}"])) + + # Now we can get resources from machine1 and machine2 + self.assertEqual(200, http_code("/cockpit/@localhost/manifests.json")) + self.assertEqual(200, http_code("/cockpit/@10.111.113.2/manifests.json")) + + # But not when AllowMultiHost is false + m.write("/etc/cockpit/cockpit.conf", + '[WebService]\nAllowMultiHost=no\n') + m.restart_cockpit() + b.relogin("/system") + cookie = b.cookie("cockpit") + + self.assertEqual(200, http_code("/cockpit/@localhost/manifests.json")) + self.assertEqual(403, http_code("/cockpit/@10.111.113.2/manifests.json")) + def testDirectLogin(self): self.machine.start_cockpit() self.checkDirectLogin('/')