Skip to content

Commit

Permalink
ws: Conditionally block channel requests to remote hosts
Browse files Browse the repository at this point in the history
When AllowMultiHost is false, cockpit-ws will reject all GET requests
that would load from a non-localhost bridge.
  • Loading branch information
mvollmer authored and martinpitt committed Sep 24, 2024
1 parent 5a73281 commit 5d7508a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/ws/cockpitchannelresponse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
34 changes: 34 additions & 0 deletions test/verify/check-shell-multi-machine
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with Cockpit; If not, see <https://www.gnu.org/licenses/>.

import re
import subprocess
import time

import testlib
Expand Down Expand Up @@ -376,6 +377,39 @@ class TestMultiMachine(testlib.MachineCase):
self.machine.start_cockpit()
self.checkDirectLogin('/')

# Also check whether AllowMultiHost blocks access already in cockpit-ws.

b = self.browser
m = self.machine

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"))

@testlib.todoPybridgeRHEL8()
def testUrlRoot(self):
b = self.browser
Expand Down

0 comments on commit 5d7508a

Please sign in to comment.