Bug 1825749

Summary: Cannot get admin privileges in web console with non-lowercase domain users
Product: Red Hat Enterprise Linux 8 Reporter: Martin Pitt <mpitt>
Component: cockpitAssignee: Martin Pitt <mpitt>
Status: CLOSED ERRATA QA Contact: Jan Ščotka <jscotka>
Severity: high Docs Contact:
Priority: high    
Version: 8.2CC: mmarusak, mvollmer
Target Milestone: rc   
Target Release: 8.3   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-11-04 01:53:29 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Martin Pitt 2020-04-20 06:40:31 UTC
Description of problem: When joining an Active Directory (AD) domain with realmd or cockpit, and then logging in as AD admin, sudo works on the command line, but not in Cockpit -- all administrative actions are grayed out with a tooltip that says "User ... is not privileged".

This works fine with FreeIPA (although this uses a different method of configuring sudo).

It's sufficient to test that against a Samba AD server, which is very easy to set up with docker.


Version-Release number of selected component (if applicable):

cockpit 211.3


How reproducible: Always


Steps to Reproduce:
1. "realm join", give Administrator password

2. Allow local sudo to the domain admins:

# cat /etc/sudoers.d/domain-admins
"%domain\ admins ALL=(ALL) ALL

3. Log into Cockpit as Administrator (you can also disable qualified names in realmd or sssd, same effect)

4. Try to shut down machine, change a service, edit time, etc. 

Actual results: No administrative actions possible


Expected results: Administrative actions work. Going to "Terminal" and trying "sudo whoami" works.


Additional info: Journal says

sudo[9690]: pam_sss(sudo:auth): authentication failure; logname= uid=1576800500 euid=0 tty= ruser=administrator rhost= user=administrator
sudo[9690]: pam_sss(sudo:auth): received for user administrator: 7 (Authentication failure)
audit[9690]: USER_AUTH pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="administrator" exe="/usr/bin/sudo" hostname=? addr=? terminal=? res=failed'
kernel: audit: type=1100 audit(1587364514.133:406): pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="administrator" exe="/usr/bin/sudo" hostname=? addr=? terminal=? res=failed'
cockpit-bridge[9656]: Sorry, try again.
sudo[9690]: pam_sss(sudo:auth): authentication failure; logname= uid=1576800500 euid=0 tty= ruser=administrator rhost= user=administrator
sudo[9690]: pam_sss(sudo:auth): received for user administrator: 7 (Authentication failure)
audit[9690]: USER_AUTH pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="administrator" exe="/usr/bin/sudo" hostname=? addr=? terminal=? res=failed'
kernel: audit: type=1100 audit(1587364515.986:407): pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="administrator" exe="/usr/bin/sudo" hostname=? addr=? terminal=? res=failed'
cockpit-bridge[9656]: Sorry, try again.
sudo[9690]: pam_sss(sudo:auth): authentication failure; logname= uid=1576800500 euid=0 tty= ruser=administrator rhost= user=administrator
sudo[9690]: pam_sss(sudo:auth): received for user administrator: 7 (Authentication failure)
kernel: audit: type=1100 audit(1587364518.310:408): pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="administrator" exe="/usr/bin/sudo" hostname=? addr=? terminal=? res=failed'
audit[9690]: USER_AUTH pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="administrator" exe="/usr/bin/sudo" hostname=? addr=? terminal=? res=failed'
sudo[9690]: administrator : 3 incorrect password attempts ; TTY=unknown ; PWD=/run/user/1576800500 ; USER=root ; COMMAND=/usr/bin/cockpit-bridge --privileged
cockpit-bridge[9656]: sudo: 3 incorrect password attempts
audit[9690]: USER_CMD pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='cwd="/run/user/1576800500" cmd=636F636B7069742D627269646765202D2D70726976696C65676564 exe="/usr/bin/sudo" terminal=? res=failed'
kernel: audit: type=1123 audit(1587364519.699:409): pid=9690 uid=1576800500 auid=1576800500 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='cwd="/run/user/1576800500" cmd=636F636B7069742D627269646765202D2D70726976696C65676564 exe="/usr/bin/sudo" terminal=? res=failed'

Comment 1 Martin Pitt 2020-04-20 17:33:48 UTC
First I disabled the polkit bridge, so that local land AD user both run through the sudo bridge path, and can be compared:

With a local user, cockpit-askpass does see the password:

cockpit-session[36117]: pam_unix(cockpit:session): session opened for user admin by (uid=0)
[...]
cockpit-bridge[36171]: We trust you have received the usual lecture from the local System
cockpit-bridge[36171]: Administrator. It usually boils down to these three things:
cockpit-bridge[36171]:     #1) Respect the privacy of others.
cockpit-bridge[36171]:     #2) Think before you type.
cockpit-bridge[36171]:     #3) With great power comes great responsibility.
cockpit-askpass[36182]: XXX write_control_message writing {"command":"authorize","challenge":"plain1:61646d696e:","cookie":"askpass361821587398369"}
cockpit-askpass[36182]: XXX read_control_message: {"command":"authorize","cookie":"askpass361821587398369","response":"foobar"}
cockpit-askpass[36182]: XXX askpass wrote 6 bytes
cockpit-askpass[36182]: XXX askpass wrote 1 bytes

while with the AD user, it does not:

cockpit-session[36267]: pam_systemd(cockpit:session): Failed to get user record: No such process
cockpit-session[36267]: pam_unix(cockpit:session): session opened for user Administrator by (uid=0)
[...]
cockpit-askpass[36311]: XXX write_control_message writing {"command":"authorize","challenge":"plain1:61646d696e6973747261746f72:","cookie":"askpass363111587398584"}
cockpit-askpass[36311]: XXX read_control_message: {"command":"authorize","cookie":"askpass363111587398584","response":""}
cockpit-askpass[36311]: XXX askpass wrote 0 bytes
cockpit-askpass[36311]: XXX askpass wrote 1 bytes
sudo[36302]: pam_sss(sudo:auth): authentication failure; logname= uid=208200500 euid=0 tty= ruser=administrator rhost= user=administrator
sudo[36302]: pam_sss(sudo:auth): received for user administrator: 7 (Authentication failure)


It's better with https://github.com/cockpit-project/cockpit/pull/13482 -- the initial sudo auth fails in the same way, but elevating privileges within the session works. Need to talk to Marius tomorrow about that.

Comment 2 Martin Pitt 2020-04-21 07:50:06 UTC
Here's the problem:

 * I'm trying to log in as "Administrator"; that's generally supposed to work, and sssd/AD forward-resolve it to a user ID just fine. But the canonical name from Linux' POV is "administrator", that's what you get when you "getent passwd <uid>".
 * cockpit-askpass sends the authorize challenge from `$USER`, which is "administrator" regardless of which capitalization you used on the login screen.
 * OTOH, src/ws/cockpitwebservice.c authorize_check_user() uses the original value from cockpit_creds(), which retains the case that was used on the login screen; It only replies with the password if they are exactly equal:

    authorize_check_user: creds user Administrator, challenge subject 61646d696e6973747261746f7240636f636b7069742e6c616e == administrator

 * Logging in as literally "administrator" works fine, and cockpit gets sudo permissions.

My first instinct is to let go of user names here, and instead use UIDs. However, it's not guaranteed that cockpit-ws and cockpit-bridge are the same version (even though on the same host they usually are), so that would be a protocol compatibility break. Also, possibly these user names are not directly Linux users (getpwnam()), but may also be abstract OAUth account names or similar?

A less intrusive, but also less clean approach maybe to accept either the original or the tolower() form of cockpit_creds_get_user() in authorize_check_user(), so that we accept the cases where user names are case insensitive. That avoids a protocol compatibility break and works with AD and other user names that include domain names (which are usually case insensitive). However, classic Unix users are case *sensitive* -- you can totally create two different users "testy" and "Testy".

So to dial this down even further, we could do a comparison with tolower(cockpit_creds_get_user) *only* if the user name contains a @. This feels like the most hackish approach, but also the safest both in terms of compatibility and robustness.

Comment 3 Martin Pitt 2020-04-21 09:33:48 UTC
I tested this with IPA; even though "Admin@" is refused, the same problem is still happening with non-lowercase domains. I. e. logging in as "admin" fails the same way. Retitling accordingly.

I sent a fix (including integration tests for AD and IPA) to https://github.com/cockpit-project/cockpit/pull/13934

Comment 11 errata-xmlrpc 2020-11-04 01:53:29 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (cockpit bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2020:4511