sandboxd for CUPS backends in Mac OS X Yosemite

While this doesn't answer the question, I stumbled across this - http://www.papercut.com/kb/Main/MacOS1010YosemiteKnownIssues - when trying to get Tea4CUPS working in OS X 10.10 (I was not able to achieve this):

To get PaperCut working with Mac OS 10.10 in the interim, you’ll need to disable sandboxing. Edit the file /etc/cups/cups-files.conf to include the new line ‘Sandboxing Relaxed’. Then restart CUPS for this to take effect.

sudo sh -c 'echo "Sandboxing Relaxed" >> /etc/cups/cups-files.conf'
sudo launchctl stop org.cups.cupsd

After a long debugging session, I have finally solved this problem. In case other people run into the same difficulties, here is what I learned about CUPS backends under Mac OS X Yosemite:

  • Backends are executable files (in my case, a shell script) in the /usr/libexec/cups/backend/ directory. Information about the print job is passed into these programs via command line arguments ($1=job-id, $2=user, $3=title, $4=copies, $5=options, $6=file) and environment variables (e.g. $DEVICE_URI).

  • Backends are executed as user _lp, group _lp, with permissions further restricted by sandboxd. The current directory when the backend is started is the root directory /, but the backend does not have permission to read this directory. Directories which can be read include /usr/libexec/cups/backend/, /etc/ and subdirectories thereof. Only very restricted (or none at all?) access to the home directory of user _lp (in /var/spool/cups) is permitted.

  • My backend requires use of ssh. For this to work, ssh needs to be able to access the private key required to log into the remote server, and a known_hosts file which identifies the remote server. The required key can be placed in /usr/libexec/cups/backend/ or a subdirectory, it must be only readable by the user _lp. It seems that ssh, when started from the CUPS backend, has no permission to access /var/spool/cups/.ssh/, even if this directory exists; thus the known_hosts file must be stored in /etc/, as /etc/ssh_known_hosts. (Note that the ssh manual page incorrectly claims that this should be /etc/ssh/ssh_known_hosts.)

    Edit: On MacOS X 10.11 (El Capitan), ssh now seems to use the documented location /etc/ssh/ssh_known_hosts for the known hosts file. I had to move my file into /etc/ssh/ to make the printer filter work after the OS upgrade.

  • To debug issues like this, using cupsctl --debug-logging is invaluable: After this command is issued, everything written to stderr in the CUPS backend appears in /var/log/cups/error_log. Logging can be switched off again using cupsctl --no-debug-logging. In addition, whenever sandboxd denies an attempted file access, a message like sandboxd[426] ([15998]): sh(15998) deny file-read-data / can be found in /var/log/system.log.