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

OpenBSD, web interface: authentication works, but not authorization #5166

Closed
ajacoutot opened this issue Nov 8, 2017 · 15 comments
Closed

OpenBSD, web interface: authentication works, but not authorization #5166

ajacoutot opened this issue Nov 8, 2017 · 15 comments
Assignees
Milestone

Comments

@ajacoutot
Copy link

Hi.

I am running CUPS 2.2.6 on OpenBSD/amd64.
As a member or the wheel group (which is included in SystemGroup), I cannot manage printers over the web interface. External clients (like using the GNOME print dialog) works fine.
Here's an hopefully relevant extract from the cups error_log in debug mode.
Authentication works fine but I am puzzled by this entry: cupsdIsAuthorized: username="" which may be the reason for Returning HTTP Unauthorized for CUPS-Get-Devices (no URI) from localhost.

D [08/Nov/2017:18:01:54 +0100] [Client 116] Read: status=200, state=6
D [08/Nov/2017:18:01:54 +0100] [Client 116] Authorized as "ajacoutot" using Basic.
D [08/Nov/2017:18:01:54 +0100] [CGI] argv[0] = "/usr/local/libexec/cups/cgi-bin/admin.cgi"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[0] = "CUPS_CACHEDIR=/var/cache/cups"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[1] = "CUPS_DATADIR=/usr/local/share/cups"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[2] = "CUPS_DOCROOT=/usr/local/share/doc/cups"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[3] = "CUPS_FONTPATH=/usr/local/share/cups/fonts"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[4] = "CUPS_REQUESTROOT=/var/spool/cups"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[5] = "CUPS_SERVERBIN=/usr/local/libexec/cups"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[6] = "CUPS_SERVERROOT=/etc/cups"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[7] = "CUPS_STATEDIR=/var/run/cups"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[8] = "HOME=/var/spool/cups/tmp"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[9] = "PATH=/usr/local/libexec/cups/filter:/usr/local/bin:/usr/local/sbin:/bin:/usr/bin"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[10] = "SERVER_ADMIN=[email protected]"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[11] = "SOFTWARE=CUPS/2.2.6"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[12] = "TMPDIR=/var/spool/cups/tmp"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[13] = "USER=root"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[14] = "CUPS_MAX_MESSAGE=2047"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[15] = "CUPS_SERVER=/var/run/cups/cups.sock"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[16] = "CUPS_ENCRYPTION=IfRequested"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[17] = "IPP_PORT=631"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[18] = "AUTH_TYPE=Basic"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[19] = "LANG=en_US.UTF8"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[20] = "REDIRECT_STATUS=1"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[21] = "GATEWAY_INTERFACE=CGI/1.1"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[22] = "SERVER_NAME=localhost"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[23] = "SERVER_PORT=631"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[24] = "REMOTE_ADDR=127.0.0.1"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[25] = "REMOTE_HOST=localhost"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[26] = "SCRIPT_NAME=/admin/"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[27] = "SCRIPT_FILENAME=/usr/local/share/doc/cups/admin/"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[28] = "REMOTE_USER=ajacoutot"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[29] = "SERVER_PROTOCOL=HTTP/1.1"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[30] = "HTTP_COOKIE=_ga=GA1.1.129303679.1495441594; org.cups.sid=f5d732a2ec61b2eaed7720c4d12c5b3f; cookieconsent_status=dismiss; _ga=GA1.1.129303679.1495441594"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[31] = "HTTP_USER_AGENT=Mozilla/5.0 (X11; OpenBSD amd64; rv:56.0) Gecko/20100101 Firefox/56.0"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[32] = "HTTP_REFERER=http:https://localhost:631/admin"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[33] = "REQUEST_METHOD=POST"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[34] = "CONTENT_LENGTH=60"
D [08/Nov/2017:18:01:54 +0100] [CGI] envp[35] = "CONTENT_TYPE=application/x-www-form-urlencoded"
D [08/Nov/2017:18:01:54 +0100] cupsdAddCert: Adding certificate for PID 89333
D [08/Nov/2017:18:01:54 +0100] [CGI] Started /usr/local/libexec/cups/cgi-bin/admin.cgi (PID 89333)
I [08/Nov/2017:18:01:54 +0100] [Client 116] Started "/usr/local/libexec/cups/cgi-bin/admin.cgi" (pid=89333, file=15)
D [08/Nov/2017:18:01:54 +0100] [Client 116] Waiting for CGI data.
D [08/Nov/2017:18:01:54 +0100] [CGI] admin.cgi started...
D [08/Nov/2017:18:01:54 +0100] cupsdSetBusyState: newbusy="Active clients and dirty files", busy="Active clients and dirty files"
D [08/Nov/2017:18:01:54 +0100] [Client 117] Server address is "/var/run/cups/cups.sock".
D [08/Nov/2017:18:01:54 +0100] [Client 117] Accepted from localhost (Domain)
D [08/Nov/2017:18:01:54 +0100] [Client 117] Waiting for request.
D [08/Nov/2017:18:01:54 +0100] [CGI] http=0x146728c9000
D [08/Nov/2017:18:01:54 +0100] [CGI] cgiSetVariable: SECTION="admin"
D [08/Nov/2017:18:01:54 +0100] [CGI] cgiSetVariable: REFRESH_PAGE=""
D [08/Nov/2017:18:01:54 +0100] [CGI] org.cups.sid cookie is "f5d732a2ec61b2eaed7720c4d12c5b3f"
D [08/Nov/2017:18:01:54 +0100] [CGI] cgiSetVariable: org.cups.sid="f5d732a2ec61b2eaed7720c4d12c5b3f"
D [08/Nov/2017:18:01:54 +0100] [CGI] cgiSetVariable: OP="add-printer"
D [08/Nov/2017:18:01:54 +0100] [CGI] op="add-printer"...
D [08/Nov/2017:18:01:54 +0100] [CGI] do_am_printer: DEVICE_URI="(null)"
D [08/Nov/2017:18:01:54 +0100] [CGI] Getting list of devices...
D [08/Nov/2017:18:01:54 +0100] [Client 117] POST / HTTP/1.1
D [08/Nov/2017:18:01:54 +0100] cupsdSetBusyState: newbusy="Active clients and dirty files", busy="Active clients and dirty files"
D [08/Nov/2017:18:01:54 +0100] [Client 117] Read: status=200, state=6
D [08/Nov/2017:18:01:54 +0100] [Client 117] No authentication data provided.
D [08/Nov/2017:18:01:54 +0100] [Client 117] Read: status=100, state=6
D [08/Nov/2017:18:01:54 +0100] [Client 117] Read: status=100, state=6
D [08/Nov/2017:18:01:54 +0100] [Client 117] Read: status=100, state=6
D [08/Nov/2017:18:01:54 +0100] [Client 117] Read: status=100, state=6
D [08/Nov/2017:18:01:54 +0100] [Client 117] 2.0 CUPS-Get-Devices 1
D [08/Nov/2017:18:01:54 +0100] CUPS-Get-Devices
D [08/Nov/2017:18:01:54 +0100] cupsdIsAuthorized: username=""
D [08/Nov/2017:18:01:54 +0100] [Client 117] Returning HTTP Unauthorized for CUPS-Get-Devices (no URI) from localhost
D [08/Nov/2017:18:01:54 +0100] [Client 117] cupsdSendHeader: code=401, type="text/html", auth_type=0
D [08/Nov/2017:18:01:54 +0100] [Client 117] WWW-Authenticate: Basic realm="CUPS", trc="y"
D [08/Nov/2017:18:01:54 +0100] [Client 117] HTTP_STATE_WAITING Closing for error 32 (Broken pipe)
D [08/Nov/2017:18:01:54 +0100] [Client 117] Closing connection.

@ajacoutot
Copy link
Author

I forgot to mention that it works fine as the root user.

@michaelrsweet
Copy link
Collaborator

Hmm, it should be getting the local authentication certificate from the certs directory - can you attach your /etc/cups/cups-files.conf file? I'm wondering if something is messed up with the directory used for passing credentials to the CGI programs?

@ajacoutot
Copy link
Author

Sure, here you go.

cups-files.conf.txt

@michaelrsweet
Copy link
Collaborator

OK, that looks pretty standard, so can you send me the output of:

ls -ld /var/run
ls -ld /var/run/cups
ls -ld /var/run/cups/certs

The certs directory is the one the CGI programs will need to be able to access...

@ajacoutot
Copy link
Author

Here you go:

# ls -ld /var/run/{,cups/{,certs}}
drwxr-xr-x  9 root   wheel  512 Nov  9 11:50 /var/run/
drwxr-xr-x  3 root   _cups  512 Nov  9 10:24 /var/run/cups/
dr-x--x--x  2 _cups  wheel  512 Nov  9 13:20 /var/run/cups/certs

@michaelrsweet
Copy link
Collaborator

OK, that should be enough for the CGIs to get the local certs... Alright, try enabling debug2 logging ("cupsctl LogLevel=debug2") and see what is coming from the CGI Get-Devices request...

@michaelrsweet michaelrsweet self-assigned this Nov 9, 2017
@ajacoutot
Copy link
Author

Here's the error log. I really don't understand what is going on :-/ ...
cups-debug2-log.txt

@michaelrsweet
Copy link
Collaborator

So the new log shows admin.cgi getting run and then the CUPS-Get-Devices operation being done over a domain socket which (correctly) gets the logged-in credentials from the cert cache, but then it thinks that ajacoutot is not a member of group wheel...

Can you verify that your user account is, in fact, listed in /etc/groups for the wheel account?

@ajacoutot
Copy link
Author

It is :-)

$ id
uid=1000(ajacoutot) gid=1000(ajacoutot) groups=1000(ajacoutot), 0(wheel), 9(wsrc), 10(users), 21(wobj)
$ grep wheel /etc/group                                        
wheel:*:0:root,ajacoutot

At least I have a better hint of where to look at in the code..

@michaelrsweet
Copy link
Collaborator

Well, the CUPS group lookup code is not seeing it - are you using LDAP or other network account stuff on this system? Something that might prevent /etc/group from being the first to get looked up?

@ajacoutot
Copy link
Author

Nope, only using flat files. No external authentication.
I'll start digging in the code in a few...

@ajacoutot
Copy link
Author

group->gr_gid looks corrupted somehow. If I print "group->gr_gid groups[i]", I have the following in the logs:

E [09/Nov/2017:18:41:33 +0100] 724 0
E [09/Nov/2017:18:41:33 +0100] 724 9
E [09/Nov/2017:18:41:33 +0100] 724 10
E [09/Nov/2017:18:41:33 +0100] 724 21

@ajacoutot
Copy link
Author

Ok I found the cullprit. Our getgrouplist(3) implementation has a documented bug:

BUGS
     The getgrouplist() function uses the routines based on getgrent(3).  If
     the invoking program uses any of these routines, the group structure will
     be overwritten in the call to getgrouplist().

So the solution would be to either:

  • only check for getgrouplist in configure if we are not OpenBSD (or force disable it)
  • call getgrnam(3) again on OpenBSD after the call to getgrouplist
    I just tested this patch and it works:
Index: scheduler/auth.c
--- scheduler/auth.c.orig
+++ scheduler/auth.c
@@ -1192,6 +1192,12 @@ cupsdCheckGroup(
 #  else
       getgrouplist(username, user->pw_gid, groups, &ngroups);
 #endif /* __APPLE__ */
+
+/* On OpenBSD, getgrouplist overwrites the group structure */
+#  ifdef __OpenBSD__
+      group = getgrnam(groupname);
+      endgrent();
+#  endif

       for (i = 0; i < ngroups; i ++)
         if ((int)group->gr_gid == (int)groups[i])

I'd rather not open a pull request until you advise me what you prefered solution would be.
Thank you @michaelrsweet

@michaelrsweet
Copy link
Collaborator

OK, just pushed some changes to auth.c that copy the gr_gid value so that we don't care that the group structure has been overwritten. Try this:

[master 3637469] Workaround getgrouplist group data overwrite bug on OpenBSD (Issue #5166)

@ajacoutot
Copy link
Author

Works like a charm \o/
Thanks again.

michaelrsweet added a commit that referenced this issue Mar 7, 2018
- Fixed a compile issue when PAM is not available (Issue #5253)
- Documentation fixes (Issue #5252)
- Star Micronics printers need the "unidir" USB quirk rule (Issue #5251)
- The scheduler now supports using temporary print queues for older IPP/1.1 print queues like those shared by CUPS 1.3 and earlier (Issue #5241)
- The `cupsRasterWritePixels` function did not correctly swap bytes for some formats (Issue #5225)
- Added a USB quirk rule for Canon MP280 series printers (Issue #5221)
- The `ppdInstallableConflict` tested too many constraints (Issue #5213)
- More fixes for printing to old CUPS servers (Issue #5211)
- The `cupsCopyDest` function now correctly copies the `is_default` value (Issue #5208)
- The scheduler did not work with older versions of uClibc (Issue #5188)
- The scheduler now substitutes default values for invalid job attributes when running in "relaxed conformance" mode (Issue #5186)
- Fixed PAM module detection and added support for the common PAM definitions (Issue #5185)
- Fixed a journald support bug in the scheduler (Issue #5181)
- The cups-driverd program incorrectly stopped scanning PPDs as soon as a loop was seen (Issue #5170)
- Fixed group validation on OpenBSD (Issue #5166)
- Fixed the `ippserver` sample code when threading is disabled or unavailable (Issue #5154)
- The `cupsEnumDests` function did not include options from the lpoptions files (Issue #5144)
- The `SSLOptions` directive now supports `MinTLS` and `MaxTLS` options to control the minimum and maximum TLS versions that will be allowed, respectively (Issue #5119)
- The scheduler did not write out dirty configuration and state files if there were open client connections (Issue #5118)
- The `lpadmin` command now provides a better error message when an unsupported System V interface script is used (Issue #5111)
- The `lp` and `lpr` commands now provide better error messages when the default printer cannot be found (Issue #5096)
- No longer support backslash, question mark, or quotes in printer names (Issue #4966)
- The CUPS library now supports the latest HTTP Digest authentication specification including support for SHA-256 (Issue #4862)
- The `lpstat` command now reports when new jobs are being held (Issue #4761)
- The `lpoptions` command incorrectly saved default options (Issue #4717)
- The `ppdLocalizeIPPReason` function incorrectly returned a localized version of "none" (rdar:https://36566269)
- TLS connections now properly timeout (rdar:https://34938533)
- The IPP backend did not properly detect failed PDF prints (rdar:https://34055474)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants