OpenPrinting / cups

OpenPrinting CUPS Sources
https://openprinting.github.io/cups
Apache License 2.0
958 stars 175 forks source link

CUPS in domain #1001

Open alexpevzner opened 3 days ago

alexpevzner commented 3 days ago

We are trying to use CUPS on Linux machine connected to the MS AD domain.

When user logs into the system, it receives uid=1136733317 or similar and this UID is properly resolved by the sss plugin to /etc/nsswitch.conf as testovmt@example.com with all appropriate groups membership, including the lpadmin group.

However, when user attempts to do some administrative tasks with printing system, the attempt is rejected as unauthorized and we see the following lines in log.

[04/Jul/2024:09:55:03 +0300] [Client 9] con->uri="/admin/", con->best=0x5580a2c09430(/admin)
D [04/Jul/2024:09:55:03 +0300] [Client 9] Authorized as testovmt@example.com using PeerCred.
d [04/Jul/2024:09:55:03 +0300] cupsdIsAuthorized: con->uri="/admin/", con->best=0x5580a2c09430(/admin)
d [04/Jul/2024:09:55:03 +0300] cupsdIsAuthorized: level=CUPSD_AUTH_USER, type=Basic, satisfy=CUPSD_AUTH_SATISFY_ALL, num_names=1
d [04/Jul/2024:09:55:03 +0300] cupsdIsAuthorized: auth=CUPSD_AUTH_ALLOW...
D [04/Jul/2024:09:55:03 +0300] cupsdIsAuthorized: username="testovmt@example.com"
d [04/Jul/2024:09:55:03 +0300] cupsdIsAuthorized: Checking user membership...
d [04/Jul/2024:09:55:03 +0300] cupsdCheckGroup(username="testovmt", user=(nil), groupname="lpadmin")
d [04/Jul/2024:09:55:03 +0300] cupsdCheckGroup(username="testovmt", user=(nil), groupname="root")
d [04/Jul/2024:09:55:03 +0300] cupsdCheckGroup(username="testovmt", user=(nil), groupname="wheel")
d [04/Jul/2024:09:55:03 +0300] [Client 9] cupsdSendError code=403, auth_type=0
D [04/Jul/2024:09:55:03 +0300] [Client 9] cupsdSendHeader: code=403, type="text/html", auth_type=0
D [04/Jul/2024:09:55:03 +0300] [Client 9] Closing connection.

Looking to the scheduler/auth.c source file, at around line 2205, I see the following code fragment:

 /*
  * Strip any @domain or @KDC from the username and owner...
  */

  if ((ptr = strchr(username, '@')) != NULL)
    *ptr = '\0';

  if (owner)
  {   
    strlcpy(ownername, owner, sizeof(ownername));

    if ((ptr = strchr(ownername, '@')) != NULL)
      *ptr = '\0';                      
  }   
  else
    ownername[0] = '\0';

So after successfully verifying that the supplied information via HTTP PeerCred corresponds to the SO_PEERCRED UID, CUPS proceeds to strip the domain part of the user name. Subsequently, only the local part of the user name is checked for group membership, mirroring the behavior observed in the logs.

This process leads to two significant issues:

  1. Domain users may not be granted permissions that they actually possess, which is currently being experienced.
  2. In cases where the local part of a domain user's name coincides with a local user's name, there is a risk of unintended permission escalation, posing a security vulnerability.

I suspect that there is a valid reason behind the decision to strip the domain part of the user name before group membership checks. Despite my efforts to trace this logic through the git history, it appears to originate from Apple's old SVN, which is inaccessible to the public.

Therefore, the key question is whether we should eliminate the domain name stripping process. If not, what would be the appropriate logic to implement in its place?

P.S.

There is a similar issue at the Red Hat Customer portal: https://access.redhat.com/discussions/6678951

temaps commented 3 days ago

I tried deleting these lines and recompiling. Everything immediately started working in the domain.

mikhailnov commented 3 days ago

I am not sure that removing this stripping will not break kerberos-related stuff, but I did not investigate.

michaelrsweet commented 3 days ago

I happen to still have a copy of the SVN repository; this is where the stripping originated:

------------------------------------------------------------------------
r6714 | mike | 2007-07-24 18:27:57 +0000 (Tue, 24 Jul 2007) | 4 lines

Fix Kerberos authentication - comment out the client SPNEGO code and strip
the @KDC portion of the Kerberos username since we can't really do group
lookups with it.

------------------------------------------------------------------------

More than likely the Kerberos PAM support code back then didn't properly handle domain accounts. I'm thinking maybe we just add a configuration directive for this ("StripUserDomain yes/no" or something like that). But longer term you'll need to transition to OAuth (supported in recent Windows Server/Azure AD), which will be supported in CUPS 2.5 and later (Kerberos won't be supported beyond CUPS 2.5.x...)

mikhailnov commented 3 days ago

NSS modules should return a correct username that does not require stripping or other changes, I think. "StripUserDomain yes/no" sounds like a good idea, maybe someone with something not common nowadays like pam_krb5 may need it, but the default should be "no", I think.

What about kerberos depreceation, there are no good and maintainable free, open source OAuth servers, at least I do not know such. Keycloack is Java, it is not maintainable as a distro package. FreeIPA is kerberos.

temaps commented 3 days ago

My colleagues and I checked the work with kerberos patched cups, where the domain cut-off code was deleted. Everything is working normally.

temaps commented 3 days ago

but the default should be "no", I think.

I support that the default should be the full name without cutting it off.

mikhailnov commented 3 days ago

but the default should be "no", I think.

I support that the default should be the full name without cutting it off.

I also meant that

michaelrsweet commented 3 days ago

@mikhailnov WRT free and open source OAuth servers, there is my mOAuth project at least, which I am updating now to full OpenID conformance. And of course Microsoft is all-in on OAuth/OpenID which is the 99% requirement for SSO on Linux desktops.

alexpevzner commented 3 days ago

Introducing an option to disable domain name stripping appears to be a viable solution to address our current challenges. Especially if stripping is disabled by default, so it will streamline the process for our administrators, eliminating the need for widespread configuration file modifications.

Nevertheless, the security implications stemming from the current stripping mechanism remain some concern for me. If domain name occasionalлy clashes with some privileged local name, it opens interesting possibilities...

mikhailnov commented 19 hours ago

@michaelrsweet Thanks for pointing to mOAuth. What do you think about removing or disabling this stripping of username, will it break anything?

michaelrsweet commented 17 hours ago

@mikhailnov Like I said earlier, I have no problems adding a configuration directive to control the stripping, with the default setting of "do not strip".

mikhailnov commented 17 hours ago

Ok, thanks!