One Solution To Kerberized Printing with CUPS under MacOS X 10.2 Only
Note: This software will not work with 10.3! The command line klprng may still work.
March 2003
Updated October 2003

Get the parts from
See details on the CUPS backend script at

 1) This solution will only work for users logged in at the console (iHook has to run and it is a GUI app). Terminal users can use /usr/bin/klprng -P instead of the cups lpr.
2) Printing will fail with no good error message if the user does not have kerberos tickets before they print.
3) The lprng print servers seem to reject print request with no error message if the local username requesting the print does not match the kerberos principal name.  This means you can't just kinit from any local user id and then print.  We do not intend to fix this as we use a kerberized login and don't care.  If anyone wants to work on the project we will share everything we know with them and help test as best we can.
4) This software has only been tested on 10.2.3 and 10.2.4 and WILL NOT WORK on 10.1.x because CUPS is required. It will not work with 10.3 because the security hole used to run iHook is closed.
5) If this does not work for you we are sorry. We might make some suggestions but we did not write most of the software and do not have the resources to fix your problems.  I wish we did.
6) We did not write lprng, Patrick Powell did.  See
7) We did not kerberize lprng for the new kerberos model in MacOS X, Sam Hartman wrote the lprng.diff.  It was a one shot deal based on a lprng snap shot around May 2002(v3.8.12) so don't bother him about it.  We have the patch available with this distribution (lprng.diff).
7) We did not write CUPS, Michael Sweet did most of it. See
8) The perl script for our  lpr backend is based loosely on the pap script at and we are not sure who wrote it.

The Parts:
1) klprng - This is the lpr client tool from the LPRNG distribution version 3.8.12 with a patch to make it compile with kerberos under MacOS X 10.2. We put this in /usr/bin because that is were kinit is stored on a default MacOS X install.
2) lpd.conf - the configuration file that lprng uses to get info about printers and their configuration.  We have the most simple case where all printers are kerberized and there is one server.  Most sites will need to change this to reflect their information. We put it in /usr/local/etc to avoid conflicts any other lpr/lpd software.
3) klpr - the cups backend script written in perl that makes everything work.  If you want to change the application you use to print (klprng) or launch ( make sure to change these two lines at the top of this file:
my $cmd = "/usr/bin/klprng";
my $ihook = "/Applications/";
See a commented version of the perl klpr backend here.
4) iHook - the software we choose to act as our script launcher.  If you have not already, get it from  Great job by the UMich team!  Runs any script you give it.
5) open - the command line tool Apple provides to run applications or files by their paths.

How we got here:

We needed to print to kerberized lprng servers from MacOS X 10.2 as I suspect you do if you are reading this file.  We spent a lot of time talking to a lot of developers on kerberos and at Apple about the problems associated with kerberos, cups and lprng.  We tested lots of theories about ticket caches, cups configuration, lprng configuration and other things.  Several folks have kerberized command line printing tools on MacOS X (CMU, Reed, etc)  but no one to our knowledge has worked out printing with Print Center and GUI apps on MacOS X 10.2+. Really the issues all boil down to two things a) kerberos in MacOS X is cached in memory only and b) the CUPS printing system is running as root.  Since root is not the user that is requesting to print and has no kerberos tickets then a simple script CUPS backend that calls a kerberized lpr does not work.  Getting to the tickets in memory won't work because of the way the MacOS partitions off users from each other (MachO chain issues).  Apple suggested and we looked at doing something like what Cornel's Side Car does with 2 daemons one root and one that starts on user login that pass tickets to each other. On our way to testing the suggestions from all the folks we talked to we found a simple solution.

So a rough analogy of what happens when a user prints is that the print job is thrown over a fence from the user to cupsd running as root.  Many folks thought we should throw the user's kerberos creds over the fence as well but we found a way to throw the processed print job back over the fence to klprng running as the user.  It seems that any GUI bundle application which is started using Apple's "open" tool will run as the current console user regardless of who calls it.
Knowing how the open tool worked made the difference.  So now we wrote a CUPS lpr backend in perl which spools the processed print file in tmp, writes a shell script into tmp to run klprng, uses open to run that shell script with iHook, and cleans up both the spool file and the temp script at finish.  Get all that? Ok so it just works for us.

These are some things we think should be done or tried but really do not have time to work on.

a) Maybe recompile CUPS so that the RunAsUser directive would take $USER from the user that asked to print and run at least the backend in that users space.  Still not sure this would solve the MachO Chain problems.

b) It would be nice if users using Print Center could not delete every printer on the box.  We thought about building Xpp for MacOS X, making it Aqua and then adding authorization api checks for creating and destroying printers but no time.

c) klprng should really be built from the latest versions and have some checks to match calling user names and kerberos principals.

d) Would be really cool to add new directives to iHook like %GETKRBCRED and %DESTROYKRBCRED so we would not have the problem with print jobs not going thru due to lack of kinit before printing.
So Apple did close the open -a path we were using to get back into the user space and at the ticket cache. We are now working on a Printing Plug-in that will use a Printer Dialog Extension to get a service granting ticket for lprng and file cache it in /private/tmp on a per user per job basis (this is as secure as we can get). The new backend will pick up the tickets, destroy the file cache and print the job. No date has been set for release.