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 \
piocrypt.c
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:
:1,$s/piofasci/piocrypt/g
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.
Conclusion
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 attmail.com!aix!jeff.
|