Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webinterface GSSAPI auth broken in cups >= 2.2 #5596

Closed
kenshin33 opened this issue Jun 13, 2019 · 12 comments
Closed

webinterface GSSAPI auth broken in cups >= 2.2 #5596

kenshin33 opened this issue Jun 13, 2019 · 12 comments

Comments

@kenshin33
Copy link
Contributor

As the tite states, the web interface does no longer work if authentication is required and Negotiate is set.

For example after the last step in modifying a printer the interface hangs. Tcpdump shows no reply after the post (except for the keepalive packets).
cupsd and admin.cgi cpu usage on the server goes up.
Debuggin shows an infinit loop in admin.cgi, precisly the while (response == NULL) in cupsDoIORequest (cups/request.c)

Basic auth works fine
OS :debian stretch
Cups: 2.2.10 (source for buster rebuilt with debuging enabled)

@michaelrsweet michaelrsweet self-assigned this Jun 13, 2019
@michaelrsweet michaelrsweet added the investigating Investigating the issue label Jun 13, 2019
@michaelrsweet
Copy link
Collaborator

@kenshin33 We'll need debug logs from the system in question. (cupsctl --debug-logging)

@kenshin33
Copy link
Contributor Author

tryin to modify the default options of a printer
error_log.old.gz

@michaelrsweet
Copy link
Collaborator

@kenshin33 OK, I'll need to see your cupsd.conf file as well - the admin.cgi program is using Peer Credentials for some reason, instead of Negotiate.

@kenshin33
Copy link
Contributor Author

kenshin33 commented Jul 16, 2019

Here it is (removed identifying information):
cupsd.conf.gz

TO be noted it is the safe file used by the older version of cups (2.2.1).
I noticed that while running cups in gdb. It keeps looping without asking for anything.
If I change to basic Auth it works fine.

@michaelrsweet
Copy link
Collaborator

Also now have reports of this on macOS, investigating...

@michaelrsweet michaelrsweet added priority-medium and removed investigating Investigating the issue labels Aug 1, 2019
@michaelrsweet michaelrsweet added this to the CUPS 2.2.x Updates milestone Aug 1, 2019
@frazhome
Copy link

frazhome commented Sep 5, 2019

at SUSE SLES 15 sp1 it is also broken.

Is there anything I could do to help you?

@DemiMarie
Copy link

admin.cgi seems to be trying to get a Kerberos ticket, but there is no way for it to do so: it doesn’t have permissions to access the host keytab, and since it runs as a system user it wasn’t granted a ticket during login. Instead, it should connect over AF_UNIX, and cupsd should admin.cgi to be authenticated by virtue of running as the lp user.

@DemiMarie
Copy link

Debug logging reveals that cupsd is sending a WWW-Authenticate: PeerCred header, which probably should not happen. This suggests that cupsd isn’t honoring PeerCred authentication when DefaultAuth is set to Negotiate. It could also mean that the CGI programs are not sending an SCM_CREDENTIALS control message.

@michaelrsweet does that help?

@DemiMarie
Copy link

Problem seems to be that CGI programs

  • Refuse to try PeerCred authentication:

    cups/cups/auth.c

    Lines 1047 to 1069 in ec8beb8

    if (http->hostaddr->addr.sa_family == AF_LOCAL &&
    !getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */
    cups_auth_find(www_auth, "PeerCred"))
    {
    /*
    * Verify that the current cupsUser() matches the current UID...
    */
    struct passwd *pwd; /* Password information */
    const char *username; /* Current username */
    username = cupsUser();
    if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid())
    {
    httpSetAuthString(http, "PeerCred", username);
    DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
    http->authstring));
    return (0);
    }
    }

    Even if they tried, they would fail, as the lp user does not have enough privileges.
  • Do not have Basic auth credentials they can use.
  • Cannot obtain a Kerberos ticket.

There are two solutions:

  1. Run the CGI programs with enough privileges that they can administer CUPS themselves.
  2. Run them as a separate user, such as cupscgi. Use sandboxing (pledge on OpenBSD, seccomp on Linux, seatbelt on macOS, etc) to prevent them from using ptrace or otherwise interfering with each other. And link each CGI process to the request that made it. This can be done using its PID, which is race-free so long as cupsd does a wait with WNOWAIT, then removes the child PID from its internal database, and finally actually reaps the child.

@DemiMarie
Copy link

DemiMarie commented Feb 24, 2020

One fix is to use S4U2Self when Kerberos is in use. That said, running the CGI programs as a separate user is still a good idea.

S4U2Self allows a service (CUPS in this case) to get a service ticket for itself that it can give to another program (here the CGI program) so that it can authenticate to the service using Kerberos. It is mostly meant for cases where the initial authentication is not via Kerberos, but it should work here too.

scabrero added a commit to scabrero/cups that referenced this issue Oct 27, 2020
SetAuthorizationString with NULL argument sets an empty string.

Related: apple#5596

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
scabrero added a commit to scabrero/cups that referenced this issue Oct 27, 2020
Related: apple#5596

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
scabrero added a commit to scabrero/cups that referenced this issue Oct 27, 2020
If connecting to localhost then proceed to ask the client for the
authorization using cupsGetPassword2. The get password callback will
return 401 to the client with WWW-Authenticate: Negotiate.

Fixes: apple#5596

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
scabrero added a commit to scabrero/cups that referenced this issue Oct 27, 2020
PeerCred is also possible if address family is AF_LOCAL. This will allow
the CGI programs to generate the authorization from the local
certificates based on PID also when Negotiate is used for local
connections:

Client                       CGI
Browser <- Remote conn -> admin.cgi <--- Localhost conn --->  Scheduler
  |                           |                                    |
  + --- HTTP/POST /admin/ --> |                                    |
  |                           + --- CUPS-Get-Devices ------------> |
  |                           |                                    |
  |                           | <-- 401 Unauthorized --------------+
  |                           |     WWW-Authenticate:              |
  |                           |       Negotiate, (PeerCred,) Local |
  |                           |                                    |
  | <-- 401 Unauthorized -----+                                    |
  |     WWW-Authenticate:     |                                    |
  |       Negotiate           |                                    |
  |                           |                                    |
  | --- HTTP/POST /admin/ --> |                                    |
  |     Authorization:        + --- IPP CUPS-GetDevices ---------> |
  |       Negotiate           |     Authorization: Local <cert>    |
  |                           |                                    |

Fixes: apple#5596

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
@michaelrsweet
Copy link
Collaborator

Fixed in OpenPrinting CUPS.

@kenshin33
Copy link
Contributor Author

can confirm. Built 2.3.3 with the patch from the pull request, it seems to work !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants