Cover V02, I04
Figure 1
Listing 1
Listing 2
Listing 3
Listing 4
Listing 5
Listing 6


Printer Encryption on AIX

Jeff Courington

I recently had to confront an unusual security issue: a report coming through our lp spooler contained sensitive information that could not be broadcast to the company at large. Since all of our programmers needed root access, permissions were not the answer. And, since the data actually resided on a remote system accessed via a Sun, tampering with the data was not an issue. What I had to do was make sure that while the document was on my system, it was never in a readable form. I also needed to make the process as transparent to the end user as possible.

The Scheme

The solution I came up with is an encode/decode scheme. The printout would come from the Sun in a encoded form and would sit in my spooler in this form until it was released to the printer. During the printing of the report, the backend process would decode the file and print it correctly. The scheme has two parts: one process must encode the report when it is submitted, and another process must decode the report when it is printed.

You can create your own encode/decode routines by using the sample code in cdr.c (Listing 1) and dcdr.c (Listing 2). The one thing to avoid is changing characters outside the printable range. The function isgraph() can tell whether a character is within the ASCII range of printable characters (isgraph() differs from the isprint() function in that it returns FALSE on the space character). This range is from hexadecimal 21 to hexadecimal 7E. If you do use characters outside the printable range, the coder and decoder programs will function correctly as filters, but the formatter for the printer will give strange results, since it actually modifies the nonprintable characters for printer control. If you do use the two sample programs to work out an encoding/decoding scheme for your system, be aware that this scheme has its limits. Try to keep the process as simple as possible. Do not, for example, count on the next 20 printable characters. If you need that complex an encryption/decryption system, you may need more than this scheme can offer.

The technique in the sample programs first changes the case of all of the characters. It then starts at the middle of the range of printable characters, which is hexadecimal 4F or character "O," and exchanges each with its corresponding member on the upper half. This encryption/decryption scheme will encode the string "Hello, World" as "7ZSSPs (PMS[q".

A major problem with this technique is that the text remains in the same form. Even though the characters are different, both strings have the same number of characters organized in two groups. A scheme that would encode the characters in groups of some arbitrary number with a character in between would make the encoding scheme much harder to break. Another feature that would add complexity to the encoded file would be to change the carriage return/line feed characters so that the lines run into each other.

The Implementation

I implement this encoding/decoding scheme in two parts. The first part, encoding, is simple, and is system independent. The printout has to be run through the encryption algorithm before it is sent to my system. Since the sending machine is another UNIX box, it was easy enough to use the cdr program as a filter during the submission of the report.

The second part, decoding, is somewhat trickier. The AIX backend process uses what IBM refers to as a "printer formatter" to translate the spooled output to a form that the printer can recognize. The formatters that IBM provides are in the directory /usr/lib/lpd/pio/fmtrs under AIX 3.2. The queue colon files, which resides in the directory /var/spool/lpd/pio/custom, define which of these printer formatters are to be used. The colon files define printer functionality that the formatter then passes to the printer device. For purposes of this article, only the references to the print formatter must be changed.

The Print Formatter

I used the sample formatter in C found in InfoExplorer as a template for the encoding formatter I present here (Listing 3, piostruct.h; Listing 4, piocrypt.imp; Listing 5, piocrypt.exp, and Listing 6, piocrypt.c).

The driver for the print formatter, pioformat, requires that the formatter contain five routines: initialize, lineout, passthru, restore, and setup.

The initialize routine uses the piocmdout subroutine to send the initialization string to the printer. This action should set the printer to the proper state for printing. The initialization string is kept in the colon file for the printer under the two-character code ci.

The lineout routine is invoked by the formatter driver to output horizontal lines on the page. The lineout routine should never output a printer command that causes a vertical movement of the page; instead, it should update the shared variables that keep track of page movement.

The passthru routine takes the input stream and passes it to the formatter driver unmodified.

The restore routine uses the piocmdout subroutine to send the restore string to the printer. The restore string is kept in the colon file for the printer under the two-character code cr.

A fifth routine, setup, reads the colon file for information about how the printer should behave. This routine is not required if the printer is to be used in passthru mode.

These routines provide all of the functionality for a simple printer formatter. They can be expanded to add more complex encoding and decoding as well as more functionality.

The header file piostruct.h (Listing 3) contains the definitions for the structures that the formatter must access.

The setup routine uses the attrparms structure to hold the data from the colon files. For each two-character variable from the colon file, an attrparms structure must be created. This array is passed to the piogetvals subroutine, which reads the information from the colon files.

The structure shar_vars (see Figure 1) is used to pass information between the print formatter and the formatter driver. The print formatter must initialize these variables if they are to be trusted. The format driver takes no responsibility for these values and only references them as necessary.

Compiling the Formatter

Use the following command to compile and link the print formatter.

cc -o piocrypt -bI:piocrypt.imp -bE:piocrypt.exp \

Place the resulting file in the /usr/lib/lpd/pio/fmtrs directory with bin as the owner and group. Set the permissions to 555.

Changing the Colon File

The colon files, which reside in the directory /var/spool/lpd/pio/custom on AIX 3.2, are named after the queue and the physical printer. In IBM terminology this constitutes a virtual printer.

The first step is to set up a virtual printer using the ASCII setting. This will give you a good base colon file to begin work with.

The five lines to be changed are the sh, st, ia, ip, and mf variables. The sh variable defines the pipeline for the header page; the -J flag tells the formatter to use the passthru routine. The st variable defines the trailer page and is also sent through the passthru routine. The ia and ip variables define the pipeline for the input data stream for the extended ASCII and passthru modes respectively. The mf command defines the pathname for the default formatter.

These lines, which contain the default formatter, piofasci, must be changed to contain the new formatter. To make the change, vi the colon file and use the command:


to replace the old formatter with the new one. Then compile the new file with the chvirprt command, as follows:

chvirprt  -d [physical device name] -q [queue name]

The new formatter should now be in place.


Keeping sensitive data private can be a very complicated task for a system administrator, and the spooler is a particularly vulnerable device, since the report is simply sitting there waiting to be printed. This encode/decode scheme is a very nice means of protecting sensitive information from curious eyes.

About the Author

Jeff Courington has worked on various forms of UNIX over the past 8 years, including AIX, SCO, HP/UX, and SVR3 variants from Silicon Valley Software and Versyss Corporation. He presently has a network of 11 IBM RS/6000s and various HP/UX machines connected over the wide area with TCP/IP through the use of Cisco routers. Jeff graduated from Virginia Polytechnical Institute and State University with a BS in Computer Science. He is currently working on his MS in Computer Science at Virginia Commonwealth University and can be reached from the Internet at!aix!jeff.