Skip to content

Commit

Permalink
ws: Accept upper-case login names for ssh/polkit agent challenges
Browse files Browse the repository at this point in the history
Identity management domain users are usually case insensitive, in
particular the domain part. E. g. with FreeIPA, "user@domain" and
"user@DOMAIN" mean exactly the same. With AD, even the user name is case
insensitive, and in fact the canonical name starts with an upper case
("Administrator@DOMAIN").

Linux' canonical form (reverse resolution of uids, or `$USER`) is
lower-case, though. This led to a failed "original vs. challenge
subject" string comparison in authorize_check_user(), resulting in
sessions not getting root privileges.

To fix this, if a direct comparison fails, compare again against the
lower-case form of the credential's user name. This avoids having to
decode the subject's hex string and thus introducing more protocol
assumptions.

Note that native Linux user names are case sensitive, i. e. "user" and
"User" are both legitimate and different. This comparison is just a
plausibility check for not accidentally logging into a remote machine
that has a different user name and spilling the password. It's
acceptable to introduce the corner case for auto-logging into remote
machines if the remote user name only differs in case.

Revert the workaround for this bug from commit c5ee044, and explicitly
test a variation in case.

https://bugzilla.redhat.com/show_bug.cgi?id=1825749

Closes #13934
  • Loading branch information
martinpitt committed Apr 24, 2020
1 parent 313ee7a commit 713ab82
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
16 changes: 13 additions & 3 deletions src/ws/cockpitwebservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,6 @@ authorize_check_user (CockpitCreds *creds,
{
char *subject = NULL;
gboolean ret = FALSE;
gchar *encoded = NULL;
const gchar *user;

if (!cockpit_authorize_subject (challenge, &subject))
Expand All @@ -511,13 +510,24 @@ authorize_check_user (CockpitCreds *creds,
}
else
{
encoded = cockpit_hex_encode (user, -1);
gchar *encoded = cockpit_hex_encode (user, -1);
ret = g_str_equal (encoded, subject);
g_free (encoded);

/* domain users are often case insensitive, while NSS/Linux converts them to the canonical lower-case form;
* accept the lower-case form of the creds user as well */
if (!ret)
{
gchar *user_lower = g_ascii_strdown (user, -1);
encoded = cockpit_hex_encode (user_lower, -1);
g_free (user_lower);
ret = g_str_equal (encoded, subject);
g_free (encoded);
}
}
}

out:
g_free (encoded);
free (subject);
return ret;
}
Expand Down
20 changes: 18 additions & 2 deletions test/verify/check-realms
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ class CommonTests:
b.wait_in_text("#statuses", "Not running")
b.logout()

# should also work with capitalized domain and lower-case user (fixed in PR #13934)
if m.image not in ["rhel-8-2-distropkg"]:
# need to change URL to actually reload the page
b.login_and_go('/system', user='%s@COCKPIT.LAN' % self.admin_user.lower(), password=self.admin_password)
b.go('/system/services#/systemd-tmpfiles-clean.timer')
b.enter_page('/system/services')
b.wait_in_text("#statuses", "Not running")
b.click(".service-top-panel .dropdown-kebab-pf button")
b.click(".service-top-panel .dropdown-menu a:contains('Start')")
b.wait_in_text("#statuses", "Running")
b.logout()

self.checkBackendSpecifics()

# change home directory ownership back to local user
Expand Down Expand Up @@ -260,6 +272,11 @@ class CommonTests:
self.login_and_go("/system", user=self.admin_user)
b.wait_in_text(self.domain_sel, "cockpit.lan")

if m.image in ["rhel-8-2-distropkg"]:
# admin operations were fixed in PR #13934; on older version this causes sudo failure
self.allow_authorize_journal_messages()
return

# Show domain information
b.click(self.domain_sel)
b.wait_popup("realms-op")
Expand Down Expand Up @@ -632,8 +649,7 @@ class TestAD(TestRealms, CommonTests):

# allow sudo access to domain admins; FIXME: Is there a server-side setting for this,
# similar to "ipa-advise enable-admins-sudo"?
# HACK: https://bugzilla.redhat.com/show_bug.cgi?id=1825749: sudo with password is broken under Cockpit
self.machine.write("/etc/sudoers.d/domain-admins", r"%domain\ admins@COCKPIT.LAN ALL=(ALL) NOPASSWD:ALL")
self.machine.write("/etc/sudoers.d/domain-admins", r"%domain\ admins@COCKPIT.LAN ALL=(ALL) ALL")

def checkBackendSpecifics(self):
'''Check domain backend specific integration'''
Expand Down

0 comments on commit 713ab82

Please sign in to comment.