The contents of the /etc/lpd.perms file
are used to control access to the lpd server facilities.
The model used for permission granting is similar to packet filters.
An incoming request is tested against a list of rules,
and the first match found determines the action to be taken.
The action is either ACCEPT or the request is granted,
or REJECT and the request is denied.
You can also establish a default action.
The following is a sample lpd.perms file.
# allow root on server to control jobs
ACCEPT SERVICE=C SERVER REMOTEUSER=root
REJECT SERVICE=C
#
# allow same user on originating host to remove a job
ACCEPT SERVICE=M SAMEHOST SAMEUSER
# allow root on server to remove a job
ACCEPT SERVICE=M SERVER REMOTEUSER=root
REJECT SERVICE=M
# all other operations allowed
DEFAULT ACCEPT
Each line of the permissions file is a rule. A rule will ACCEPT or REJECT a request if all of the patterns specified in the rule match. If there is a match failure, the next rule in sequence will be applied. If all of the rules are exhausted, then the last specified default authorization will be used.
The sense of a pattern match can be inverted using the NOT keyword.
For example,
the rules with
ACCEPT NOT REMOTEUSER=john,bill
succeeds only if the REMOTEUSER value is defined and
is not john or bill.
Each entry in a rule is a keyword which has is assigned a value or list of values followed by an optional set of patterns that are matched against these values. The following table is a summary of the available keywords.
|
Keyword | Match |
DEFAULT | default result |
SERVICE | Checking lpC, lpR, lprM, lpQ, and Printing |
USER | P (logname) field name in print job control file. |
REMOTEUSER | user name in request from remote host. |
HOST | DNS and IP address information for the H (host) field name in print job control file |
REMOTEHOST | DNS and IP address information for the connection from the remote host making the request |
IP | Alias for HOST |
REMOTEIP | Alias for REMOTEHOST |
REMOTEPORT | Originating TCP/IP port for the connection from the remote host making the request |
SAMEUSER | USER and REMOTEUSER matches |
SAMEHOST | HOST and REMOTEHOST matches |
SERVER | request originates on lpd server |
FORWARD | destination of job is not host |
REMOTEGROUP | REMOTEUSER is in the specified group or netgroup in the lpd server group database. |
GROUP | USER is in the specified group or netgroup in the lpd server group database. |
LPC | LPC command in the LPC request. |
CONTROLLINE | match a line in control file |
AUTH | authentication type |
AUTHUSER | authenticated user |
AUTHFROM | authenticated forwarder |
AUTHJOB | authenticated job in queue |
The lpd server uses the following algorithm to do
permission checks.
null value.lpd server,
REMOTEHOST
and
REMOTEPORT
are set to the the IP addresses and hostnames, and the TCP/IP port
of the host originating the IP address respectively.
REMOTEIP and IFHP are aliases for REMOTEPORT
and PORT is an alias for REMOTEPORT. Thes
are provided for backwards compatibility with older versions of LPRng.
For example,
a request originating from 10.0.0.2, port 1011 would set
REMOTEIP to 10.0.0.2 and PORT to 1011.h2.private and patrick.private,
and the only IP address assigned to it was 10.0.0.2.
The REMOTEHOST value would then be the list
h2.private,patrick.private,10.0.0.2.X
and then the permissions database is scanned for a matching entry.
The result is the permission value of the first matching line or the default
permission.
If the result is REJECT then the connection is closed.R,
Q,
M,
and
C,
for a
lpR,
lpQ,
lprM,
and
lpc
request respectively and PRINTER to the print queue name.lpc operation,
the LPC value is set to the name of the operation.
For example,
and
lpc lpd
operationlpd server as determined by
the connection arriving from the localhost address or an
address assigned to one of the network interfaces for this host
then the SERVER value is set to true (or matches).lpq command,
and most of the lpc commands control queue operations.P line.
The value of the H line in the control file is used to perform a
DNS lookup,
and the HOST value is set to the results of this lookup.
IP is an alias for HOST,
and is retained for backwards compatibility.These checks are applied on the arrival of a job from an external connection. Unfortunately, there are a set of print spooler implementations that do not handle job rejection due to lack of permissions. These printers will continually and repeatedly attempt to send a job for which there is no printing permission until the job is removed by administrative action. To accommodate these printers, we must accept jobs for printing and then dispose of them. This is done by using the SERVICE=P (printing) checks.
USER and HOST
values as discussed in the previous sections.
It will also set the AUTH,
AUTHUSER,
and AUTHJOB
values as well,
if the job was spooled by using an authenticated method.While this model is very simple it can handle a wide range of situations. However, it is really based on the simple trust that users will not impersonate other users or hosts. If this is not the case, then more elaborate proceedures based on encryption and authentication are called for.
There is a problem with permissions checking for lpq (SERVICE=Q)
requests.
Since the user name is not passed as part of the request,
it is impossible to use the REMOTEUSER clause to restrict lpq
operations.
The SERVICE=R and SERVICE=P
facilities are provided to handle problems with print spoolers that
do not recognize a lack of permission error code,
and will indefinately retry sending a job to the lpd server.
If this is the case,
then the SERVICE=R clause can be used to accept jobs,
and then the SERVICE=P clause will cause the lpd
server to remove of the job when it is scheduled for printing.
[not] key assigned value
[not] key=pattern substring match
[not] key=pattern1,pattern2,pattern3,... glob and exact
[not] key=IP1/mask1,IP2/mask2,... IP address
Each of the indicated values is matched against a list of patterns. The following types of matches are used:
[L-H]
specifies a range of characters from
L to H,
in ASCII order.nn.nn.nn.nn format.
The mask must be either an integer number
corresponding to the number of significant bits,
or in the standard nn.nn.nn.nn format.
Addresses are compared by doing
( IPaddr XOR IP ) AND mask
If the result is 0, then a match results. Note that there may be one or more addresses being checked for; this can occur when a host may have multiple IP addresses assigned to it.
low-high,
where low and high are integer numbers.
The match succeeds if the value is in the specified range.
DEFAULT ACCEPT
DEFAULT REJECT
The DEFAULT rule specifies the default if no rule matches. Normally, there is one DEFAULT entry in a permissions file.
Example:
DEFAULT ACCEPT
Match type: substring
The SERVICE key is based on the type of request.
|
Key | Request |
C | LPC Control Request |
M | LPRM Removal Request |
P | Printing |
Q | LPQ Status Request |
R | LPR Job Transfer |
X | Connection Request |
Each of the above codes corresponds either directly to the user command, or a set of subcommands.
If you have an LPC request,
you can add an LPC=xxx clause to refine the
permissions checking to allow or disallow
lpc commands such as lpc status, printcap, active, .
Example:
# control only from root on server
ACCEPT SERVICE=C SERVER USER=root
REJECT SERVICE=C
# accept all others
ACCEPT SERVICE=*
Match type: GLOB
The USER information is taken from the P (person or logname)
information in the print job control file.
Example:
# we allow jobs to be spooled
ACCEPT SERVICE=R
# now we do the checking at print time
ACCEPT SERVICE=P USER=root
REJECT SERVICE=P
Match type: GLOB
The REMOTEUSER information is taken from the user information sent with a service request.
Note that one of the flaws of RFC1179 is that an LPQ (print status) request does not provide a REMOTEUSER name.
Example:
ACCEPT SERVICE=C REMOTEUSER=root,papowell,admin SERVER
ACCEPT SERVICE=C LPC=status,lpd REMOTEUSER=admin
REJECT SERVICE=C
Match type: GLOB
The H (host) information in the print job control file
is used to do a DNS lookup,
and the resulting list of names and addresses is used for matching purposes.
Example:
# we allow jobs to be spooled
ACCEPT SERVICE=R
# now we do the checking at print time
# allow from our private subnet
ACCEPT SERVICE=P HOST=10.0.0.0/8,*.othernet.com
REJECT SERVICE=P
Match type: GLOB
The REMOTEHOST information is obtained by doing a reverse IP name lookup on the remote host IP address and the resulting list of names and addresses is used for matching purposes. If there is no FQDN available, then the IP address in text form will be used.
Example:
# allow from our private subnet
ACCEPT SERVICE=R REMOTEHOST=10.0.0.0/8,*.othernet.com
REJECT SERVICE=R
Match type: integer range
The REMOTEPORT value is the originating port of the TCP/IP connection. The match succeeds if it is in the specified range.
Example:
# require connections to originate from priviledged port
ACCEPT SERVICE=X REMOTEPORT=1-1023
REJECT SERVICE=X
Alias for REMOTEPORT.
Alias for HOST.
Alias for REMOTEHOST.
Match type: GLOB
The requested lpc command.
This allows the following permissions line to be used:
Example:
#allow remoteuser admin on server to use LPC topq and hold
ACCEPT SERVICE=C SERVER REMOTEUSER=root
ACCEPT LPC=topq,hold SERVER REMOTEUSER=papowell
REJECT SERVICE=C
Match type: exact string match
Both the REMOTEUSER and USER information must be present and identical.
Example:
# LPC users can do anything
ACCEPT SERVICE=C SERVER REMOTEUSER=root
REJECT SERVICE=C
# allow users who sent jobs from the same host to remove them
ACCEPT SERVICE=M SAMEUSER SAMEHOST
REJECT SERVICE=M
Match type: Same IP Address
The REMOTEHOST and HOST address lists are checked; if there is a common value the match succeeds.
Example:
# allow root on the same host as user
# to remove files
ACCEPT SERVICE=M SAMEHOST REMOTEUSER=root
REJECT SERVICE=M
Match type: Matching IP Address
One of the REMOTEHOST addresses
must be the same as one of the addresses of the lpd server host,
or must be one of the addresses found by looking up the localhost
name using gethostbyname().
Example:
# allow root on the server full LPC permissions
ACCEPT SERVICE=C SERVER REMOTEUSER=root
REJECT SERVICE=C
Match type: Address Match
The list of REMOTEHOST and HOST addresses must not have a common entry.
This is usually the case when a remote lpd server is forwarding
jobs to the lpd server.
Example:
# do not accept forwarded jobs or requests
REJECT SERVICE=* FORWARD
Match type: modified GLOB
The USER must be present in
one of the groups in /etc/group or whatever permissions mechanism is used
to determine group ownership
which matches the GLOB pattern.
If the pattern has the form @name,
then a check to see if the user is in the named netgroup is done.
Example:
ACCEPT SERVICE=P GROUP=admin,@netgroup
REJECT SERVICE=P
The same rules as for GROUP, but using the REMOTEUSER value.
Example:
ACCEPT SERVICE=R REMOTEGROUP=admin,@netgroup
REJECT SERVICE=R
Match type: GLOB
A CONTROLLINE pattern has the form
X=pattern1,pattern2,...
X is a single upper case letter. The corresponding line must be present in a control file, and the pattern is applied to the line contents.
This pattern can be used to select only files with specific control file information for printing.
Match type: value
If the current transfer or the transfer used to send a job was authenticated, then AUTH is true or matches.
Example:
# reject all non-authenticated transfers
REJECT NOT AUTH
Match type: glob
If the current transfer or the transfer used to send a job was authenticated, then AUTHTYPE is set to the name of the authentication method.
Example:
# require kerberos, pgp, or md5 authentication
REJECT NOT AUTHTYPE=kerberos*,pgp,md5
Match type: GLOB
The AUTHUSER rule will check to see if the authenticated user identification matches the pattern.
Example:
ACCEPT SERVICE=C AUTHTYPE=kerberos* AUTHUSER=admin@ASTART.COM
Match type: IPmatch, but for IPV6 as well as IPV4
There is a subtle problem with names and IP addresses which are obtained for 'multi-homed hosts', i.e. - those with multiple ethernet interfaces, and for IPV6 (IP Version 6), in which a host can have multiple addresses, and for the normal host which can have both a short name and a fully qualified domain name.
The IFIP (interface IP) field can be used to check the IP address of the interface that accepted the network connection, as reported by the information returned by the accept() system call. Note that this information may be IPV4 or IPV6 information, depending on the origination of the system. This information is used by gethostbyaddr() to obtain the originating host fully qualified domain name (FQDN) and set of IP addresses. Note that this FQDN will be for the originating interface, and may not be the canonical host name. Some systems which use the Domain Name Server (DNS) system may add the canonical system name as an alias.
This entry is deprecated and may not be supported in future releases.
Options used:
perms_path= directory path listThe perms_path= configuration variable specifies the
location of the default permissions file.
The default value is:
perms_path=/etc/lpd.perms:/usr/etc/lpd.perms
The lpd.perms file can be obtained by running a program,
in a similar manner to the /etc/printcap file.
See
Filters for details on how
the program would be invoked.
For example, assume the configuration information specified:
perms_path=|/usr/local/libexec/get_perms
The lpd server will write either a blank line
for connection (SERVICE=X) and global lpc permissions
(SERVICE=C and LPC=reread,lpd,default)
or the name of the spool queue to the get_perms
STDIN,
and expects to read permission information from its STDOUT.
If the filter method is used,
it should always return the complete set of connection (X)
and control (C service values.
# allow root on server to control jobs
ACCEPT SERVICE=C SERVER REMOTEUSER=root
ACCEPT SERVICE=C LPC=lpd
REJECT SERVICE=C
#
# allow same user on originating host to remove a job
ACCEPT SERVICE=M SAMEHOST SAMEUSER
# allow root on server to remove a job
ACCEPT SERVICE=M SERVER REMOTEUSER=root
REJECT SERVICE=M
# all other operations allowed
DEFAULT ACCEPT
In the above sample, we first specify that
lpC
commands from user root on the lpd server will be accepted.
This is traditionally the way that most lpc commands operate.
We also allow anybody to use the lpc lpd command.
We reject any other lpc requests.
We accept
lprM
requests from the host and user that submitted the job,
as well as from root on the server,
and reject any others.
Finally, all other types of commands (lpq, lpr) are allowed by default.
One of the more useful types of permission checking is to restrict access to your printers from users outside your networks. The IP pattern can specify a list of IP addresses and netmasks to apply to them.
For example
IP=10.3.4.0/24 would match all hosts with the IP
addresses
IP=10.3.4.0 to
IP=10.3.4.255.
Similarly, the HOST pattern can specify a set of hostnames or patterns to match against based on the GLOB notation.
For example
REMOTEHOST=*.astart.com
would match all hosts with a DNS entry which ended with
astart.com.
The NOT keyword reverses the match sense. For example
REJECT NOT REMOTEHOST=*.astart.com,*.murphy.com
would reject all requests from hosts which did not have a DNS entry
ending in
astart.com
or
murphy.com.
The following is a more complex lpd.perms file.
# All operations allowed except those specifically forbidden
DEFAULT ACCEPT
#Reject connections which do not originate from hosts with an
# address on 130.191.0.0 or from localhost,
# or name is not assigned to Engineering pc's
REJECT SERVICE=X NOT IFIP=130.191.0.0/16,127.0.0.1/32
REJECT SERVICE=X NOT REMOTEHOST=engpc*
#Do not allow anybody but root or papowell on
#astart1.astart.com or the server to use control
#facilities.
ACCEPT SERVICE=C SERVER REMOTEUSER=root
ACCEPT SERVICE=C REMOTEHOST=astart1.astart.com REMOTEUSER=papowell
#Allow root on talker.astart.com to control printer hpjet
ACCEPT SERVICE=C HOST=talker.astart.com PRINTER=hpjet REMOTEUSER=root
#Reject all others
REJECT SERVICE=C
#Do not allow forwarded jobs or requests
REJECT SERVICE=R,C,M FORWARD
# allow same user on originating host to remove a job
ACCEPT SERVICE=M SAMEHOST SAMEUSER
# allow root on server to remove a job
ACCEPT SERVICE=M SERVER REMOTEUSER=root
One of the major problems in a print spooler system is providing privacy and authentication services for users. One method is to construct a specific set of protocols which will be used for providing the privacy or authentication; another is to provide a simple interface to a set of tools that will do the authentication and/or encryption.
LPRng provides native support for the MIT Kerberos 4 extensions and Kerberos 5 authentication.
LPRng has native support for the PGP (Pretty Good Privacy) program and can sign and optionally encrypt command and responses between servers and clients. Due to legal restrictions, an external PGP program must be used for this purpose.
A simple MD5 hash based authentication scheme is also provided as an example to illustrate how new or different authentication methods can be adddd.
Finally, LPRng provide a general purpose interface allowing users to insert their own authentication methods, either at the program level or at the code level.
A careful study of the authentication problem shows that it should be done during reception of commands and/or jobs from a remote user and/or spooler. At this time the following must be done:
When a user logs into a system, they are assigned a user name and a corresponding UserID. This user name is used by the LPRng software when transferring jobs to identify the user.
When we look into the problem of authentication, we will possibly have a more global user identification to deal with, the authentication identifier (AuthID). One way to deal with this problem is to give LPRng intimate knowledge of the UserID and AuthID relationship. While this is possible it is difficult to deal with in a simple and extensible manner. An alternate solution is to provide a mapping service, where the authentication procedure provides a map between the UserID and AuthID.
The RFC1179 protocol specifies that a LPD server command sent on a connection has the form:
\nnn[additional fields]\n
\nnn is a one octet (byte) value with the following meaning:
REQ_START 1 start printer
REQ_RECV 2 transfer a printer job
REQ_DSHORT 3 print short form of queue status
REQ_DLONG 4 print long form of queue status
REQ_REMOVE 5 remove jobs
The LPRng system extends the protocol with the following additional types:
REQ_CONTROL 6 do control operation
REQ_BLOCK 7 transfer a block format print job
REQ_SECURE 8 do operation with authentication
The REQ_CONTROL allows a remote user to send LPC commands to the server. The REQ_BLOCK provides an alternate method to transfer a job. Rather than transferring the control and data files individually, this format transfers one file. The REQ_AUTH provides a mechanism for providing an authentication mechanism and is described in this document.
Options used:
auth=client to server authentication typeauth_forward=server to server authentication typeXX_id=server identificationXX_forward_id=Server identificationA client (lpr, lpc, etc to lpd server authenticated transfer
proceeds as follows.
If an authenticated transfer is specified by the
auth=protocol entry in the printcap or configuration information,
the client sends a request for an authenticated transfer
to the server.
Part of the authentication request is the authentication type.
If authentication type XX is requested
the server will examine the information in the printcap and configuration
entries for an XX_id value.
If this value is present then the server supports authentication of this type.
Further permission checks are carried out and finally the
server will accept or reject the authentication request.
If the request is accepted the server returns a postive
acknowlegement (single 0 byte) to the requester,
otherwise it returns a nonzero value and an error message.
If the request is accepted then an authentication specific protocol exchange is carried out between client and server. The commands and/or data files are encrypted and/or signed and transferred to the server. The protocol specific software on the server will then decrypt and/or check signatures, perform the requested actions, and in turn generate a status information. The status information is encrypted and/or signed by the server and sent to the client, where the client decrypts and/or checked for correct signature.
A lpd server to lpd server authenticated transfer
proceeds as follows.
If an authenticated transfer is specified by the
auth_forward=protocol entry in the printcap or configuration information,
the originating server sends a request for an authenticated transfer
to the destination server.
The originating server plays the part of the client
and performs the same set of actions.
The following printcap or user level information needs to be provided for an authenticated exchange.
auth option specifies the authentication type to be used
for client to server transfers.
For example,
auth=kerberos or
auth=kerberos5 or
would specify Kerberos 5 authentication,
auth=kerberos4 would specify Kerberos 4 authentication,
auth=pgp would specify PGP authentication,
auth=md5 would specify MD5 authentication,
etc.
The special form auth@ specifies no authentication.auth_forward option specifies the authentication type to be used
for server to server transfers.
For example,
auth_forward=kerberos5 would specify Kerberos 5 authentication,
etc.
The special form auth@ specifies no authentication.
\008printer C user_id authtype \n - for commands (lpq, lpc, etc.)
\008printer C user_id authtype size\n - for print jobs (lpr)
\008printer F server_id authtype \n - forwarded commands (lpq, lpc, etc.)
\008printer F server_id authtype size\n - forwarded print jobs (lpr)
The single character with the \008 value signals that this
is an authentication request
the printer is the name of a print queue,
and the C (client) or F indicates that the request is from
a client program or is a forwarded request from a server.
The user_id or server_id field is an identifier supplied by
the originator and is dicussed below.
If the size value is present then the request
is for a job transfer and this value represents the job size.
It is used to determine if there is sufficient space in the spool queue
for the job.
user_id or server_id fields in the authentication
request are obtained as follows.
If the request originates from a client,
then the user_id is the user name of the originator obtained from
password information.
If the request originates from a server,
then the server_id is the printcap or configuration
xx_id=server_id value,
where xx is the value of the auth_forward=xx entry.AUTHFROM and AUTHUSER
strings will be supplied
to the lpd server for purposes of permission checking.When an authenticated transfer has been performed, the following permission information will be provided.
true or match if an authenticated request
was received.authtype field in the authentication
request.AUTHUSER information provided by the authentication
protocol,
and is usually the originating user's identification.AUTHUSER information provided by the authentication
protocol,
and is usually the originating system (user or lpd server) identification.AUTHUSER information from the request is compared to the
AUTHUSER information from the request that created a job.
If they are identical, the match succeeds.For example, to reject non-authenticated operations, the following line could be put in the permissions file.
REJECT NOT AUTH
If a remote server has id information FFEDBEEFDEAF, then the following will accept only forwarded jobs from this server.
ACCEPT AUTH AUTHFROM=FFEDBEEFDEAF
REJECT AUTH
REJECT NOT AUTH
To allow only authenticated users to remove jobs you can use:
ACCEPT AUTH SERVICE=R,M,L,P AUTHSAMEUSER
REJECT AUTH
REJECT NOT AUTH
PGP is a well known encryption and authentication program. For more details see the web site http://www.pgp.net or the ftp site ftp://ftp.pgp.net.
LPRng has greatly simplified the use of PGP for authentication by building in support as follows.
user and group configuration entry (defaults
daemon and daemon respectively) specify the user and group id
used by the lpd server for file and program execution.
PGP uses the current user id of the PGP process to determine the locations
of various configuration files and information.
In this discussion we will assume that lpd runs as uid daemon.$HOME/.pgp/ directory
to be readable only by the user.
In order to set up PGP authentication,
make sure that the daemon account has a home directory.
Then use the su daemon command to change effective UID to daemon
and run the
pgp -kg
(generate key)
command as daemon.
The daemon user should not have a password.lpd key be lpr@hostname,
where hostname is the fully qualified domain name of the server.
A public and a private key file will be created.daemon
user in
~daemon/.pgp/serverkey,
and make sure it has owner daemon
and 600 permissions (read/write only by daemon).
This is extremely important.
If other users can read this file then security will be severely compromised.lpr@hostname public key to all users of the
LPRng server.
This is usually done by placing the public key in a well known file location
or making it available to users by some form of Public Key Distribution system
(PKD).
The key can be extracted and put into a text file using the following commands:
pgp -kxa userid destfile keyfile
Example:
> pgp -kxa lpr@astart /tmp/lprkey ~daemon/.pgp/pubring.pgp
Key for user ID: lpr@astart
512-bit key, key ID BB261B89, created 1999/01/01
Transport armor file: /tmp/lprkey.asc
Key extracted to file '/tmp/lprkey.asc'.
daemon public key ring.
This can be done using:
pgp -ka /tmp/lprkey.asc
daemon users public key ring. This can most easily be done by
copying all the keys (in ASCII text form) to a single file
(/tmp/keyfile)and using:
su daemon
pgp -ka /tmp/keyfile ~daemon/.pgp/pubring.pgp
lpd server is using PGP to forward jobs or requests,
the destination server's public key must be put in the originating
servers public keyring. For example:
su daemon
pgp -ka /tmp/lpd.keyfile ~daemon/.pgp/pubring.pgp
Options used:
pgp_path=path to PGP programpgp_id=destination server key used by clientspgp_forward_id=destination server used by serverpgp_server_key=path to server passphrase fileExample printcap entry:
pr:
:lp=pr@wayoff
:auth=pgp
:pgp_id=lpr@wayoff.com
:pgp_path=/usr/local/bin/pgp
pr:server
:lp=pr@faroff
:auth_forward=pgp
:pgp_id=lpr@wayoff.com
:pgp_path=/usr/bin/pgp
:pgp_forward_id=lpr@faroff.com
The pgp_path value is the path to the PGP program.
The progam must be executable by all users.
The pgp_id value is the id used by PGP to look extract keys from
key rings.
When doing a client to server transfer this will be supplied as the id
to be used for the destination,
and the user's public keyring will be checked for a key corresponding to
this id.
When a request arrives at the server,
the server will use this value as the id of a key in its private key ring.
Finally,
when a server is forwarding a request to a remote server,
it will use this value
as the id of the key in its private key ring to be used to sign
or encode the destination information.
The pgp_forward_id value is used by the lpd server as the id
to use to find a key for the destination.
The pgp_server_key is the path to the file containing the server passphrase.
This file will be read by lpd to get the passphrase to unlock the server's
keyring.
Options used:
PGPPASSFILE=File to read PGP passphrase fromPGPPASSFD=File descriptor to read PGP passphrase fromPGPPASS=PGP passphraseOne problem with using PGP is the need to have users input their passphrases. The following methods can be used.
$(HOME)/.pgp/.hidden,
and set the PGPPASSFILE environment variable to the file name.
This file will be opened and read by PGP to get the passphrase.
This file should be owned by the user and have 0600 or read/write
only by user permissions.PGPPASSFD environment variable
facility.
This causes PGP to read the passphrase from a file descriptor.
If the user puts his passphrase in a file, say
$(HOME)/.pgp/.hidden,
then the following shell script can be used:
#!/bin/sh
# /usr/local/bin/pgplpr script - passphrase in $(HOME)/.pgp/.hidden
#
PGPASSFD=3 3<$(HOME)/.pgp/.hidden lpr "$@"
PGPPASS environment variable.
Since the ps command can be used to list the environment variables
of processes,
this is highly undesireable and should not be used under any circumstances.LPRng Kerberos 5 authentication is
based on the
Kerberos5-1.1.1 release as of December 28, 1999. This was obtained
from MIT from the
http://web.mit.edu/kerberos/www/
Website.
The following sections briefly describes how to set up and test the Kerberos software and then how to configure LPRng to use Kerberos.
By default,
LPRng will search for the krb5.h file and the krb5 libraries.
If it finds these,
then Kerberos authentication will be included.
If it also finds the krb.h file then MIT Kerberos 4 compatibility will
also be enabled.
/etc/krb5.conf and
/usr/local/var/krb5kdc/kdc.conf,
files using templates from the files in the
Kerberos distribution's
src/config-files directory.
See the Installation notes and the System Administrators Guide for
details.rc.local
or equivalent system startup files:
if [ -f /etc/krb5.conf -a -f /usr/local/var/krb5kdc/kdc.conf ]; then
echo -n ' krb5kdc '; /usr/local/sbin/krb5kdc;
echo -n ' kadmind '; /usr/local/sbin/kadmind;
fi
lpd servers. I have been using
lpr/hostname.REALM
as a template-
i.e.
lpr/astart1.astart.com@ASTART.COM
for an example.
You should use fully qualified domain names for the principals.
Since it will never be used by an individual,
you do not have to give it a password.
Example:
kadmin ...
addprinc -randkey lpr/wayoff.astart.com@ASTART.COM
kadmin ...
ktadd -k keytab lpr/hostname.REALM
Example:
ktadd -k /tmp/lpr.wayoff.astart.com lpr/wayoff.astart.com@ASTART.COM
keytab file contains the keytab information, which is the
equivalent information for the server.keytab file to the
appropriate server (you might want to encrypt
or use a secure transfer for this).
Put it in the /etc/lpd.keytab file on the server.
This file should have 0400 permissions and owned by
daemon or the user that lpd will run as.
#> ls -l /etc/lpd.keytab
-rw------- 1 daemon wheel 128 Jan 16 11:06 /etc/lpd.keytab
servertabs
instead of Kerberos 5 keytabs.
Assuming that you have put the Kerberos 5 keytab in /etc/lpd.keytab,
then you extract the Kerberos 4 srvtab version of the Kerberos 5 keytab using
the following commands.
You must put the key in the /etc/srvtab file
in order to be compatible with the Kerberos 4 support.
%> su
#> ktuil
rkt /etc/lpd.keytab
wst /etc/srvtab
The LPRng software needs to be configured so that it can find the
Kerberos libraries and include files.
By default,
the include files are installed in
/usr/local/include
and the libraries in
/usr/local/lib.
Use the following steps to configure LPRng so that it uses these
directories during configuration and installation:
cd .../LPRng
rm -f config.cache
CPPFLAGS="-I/usr/local/include -I/usr/include/kerberosIV" \
LDFLAGS="-L/usr/local/lib -L/usr/lib/kerberosIV" \
./configure
make clean all
su
make install
Options used:
auth=kerberos5=use Kerberos5 authenticationkerberos_id=destination server key used by clientskerberos_server_principal=alias for kerberos_idkerberos_forward_id=destination server used by serverkerberos_forward_principal=alias for kerberos_forward_idkerberos_keytab=location of the lpd server keytab filekerberos_service=service to be usedkerberos_life=lpd server ticket lifetimekerberos_renew=lpd server ticket renewExample printcap entry:
pr:
:lp=pr@wayoff
:auth=kerberos5
:kerberos_id=lpr/wayoff.astart.com@ASTART.COM
pr:server
:lp=pr@faroff.private
:auth_forward=kerberos5
:kerberos_id=lpr@wayoff.astart.com@ASTART.COM
:kerberos_forward_id=lpr/faroff.astart.com@ASTART.COM
OR If you want to use Kerberos 4 authentication to the server
pr:
:lp=pr@wayoff
:auth=kerberos4
:kerberos_id=lpr/wayoff.astart.com@ASTART.COM
# support both Kerberos 4 and 5 on server
pr:server
:lp=pr@faroff.private
:auth_forward=kerberos5
:kerberos_id=lpr@wayoff.astart.com@ASTART.COM
:kerberos_forward_id=lpr/faroff.astart.com@ASTART.COM
:kerberos_keytab=/etc/lpd.keytab
The printcap configuration for Kerberos authentication is very simple.
The kerberos_id is the principal name of the lpd server
that clients will connect to.
For backwards compatibility,
kerberos_server_principal can also be used.
This values is used to obtain a ticket for the lpd server,
and is the only entry required for client to server authentication.
The other entries are used by the lpd server.
kerberos_keytab
entry is the location of the keytab file to be used by the server.
This contains the passphrase used by the server to authenticate itself
and get a ticket from the ticket server.
The kerberos_id value is also used by the server during the
authentication process to make sure that the correct principal name
was used by the request originator.
This check has saved many hours of pain in trying to determine why
authentication is failing.
The
kerberos_life and kerberos_renew
set the lifetime and renewability
of the lpd server Kerberos tickets.
These values should not be modified unless you are familiar with the
Kerberos system.
There are extensive notes in the LPRng source code concerning these values.
The kerberos_service value supplies the name of the service
to be used when generating a ticket.
It is stronly recommended that the kerberos_id entry
be used instead.
In order to use kerberos authentication,
the user will need to obtain a ticket from the Kerberos ticket server.
This is done using kinit.
No other actions are required by the user.
LPRng has built-in support for the Project Athena extensions to the RFC1179 protocol. These provide an extremely simple authentication protocol using an initial credential exchange. After the initial exchange the usual RFC1179 protocol is used.
During configuration,
if the krb.h (Kerberos 4) include file is found,
then this is enabled by default.
Options used:
auth=kerberos4use Kerberos4 authenticationkerberos_id=destination server key used by clientskerberos_server_principal=alias for kerberos_idExample printcap entry:
pr:
:lp=pr@wayoff
:auth=kerberos4
:kerberos_id=lpr/wayoff.astart.com@ASTART.COM
The configuration information for Kerberos4 and Kerberos5 is identical and differ only in the authentication type. Note that only client to server authentication is supported.
LPRng has built-in support for using MD5 digests as an authentication method. The implementation is provided as an example of how to add user level authentication into the LPRng system.
The method used to do authentication is very simple. Each user has a file containing a set of keys that are used to salt an md5 hash. The information being transferred has its md5 checksum calculated using this salt, and is then transferred to the destination, along with the md5 hash result. At the destination the server will get the user id, obtain the salt value from a key file, and then calculate the md5 hash value. If the two are in agreement, authentication is successful.
The keyfile used for md5 authentication contains an id followed by a text string whose binary value is used as a hash key:
id1=key
id2=key
Example:
lpr@h2=tadf79asd%^1asdf
lpr@h1=fdfa%$^&^%$
Options used:
auth=md5use MD5 authenticationauth_forward=md5forward using MD5 authenticationmd5_id=id for servermd5_forward_id=id for servermd5_server_keyfile=server keyfileExample printcap entry:
pr:
:lp=pr@wayoff
:auth=md5
:md5_id=lpr@wayoff.com
pr:server
:auth_forward=md5
:md5_id=lpr@wayoff.com
:md5_server_keyfile
:md5_forward_id=lpr@faroff.com
The md5_id value is used by the client to obtain
a hash key that is used to salt the md5 calculation for client to server
transfers.
The md5_forward_id value is used by the server to obtain
a hash key that is used to salt the md5 calculation for server to server transfers.
The md5_server_keyfile contains the keys of users;
the id sent as the connection information is used to obtain the key from the file.
To set up md5 authentication, all that is needed is the following.
user1@host1=asdfasdfadf
user2@host2=a8789087asddasdf
pr:
:lp=pr@wayoff
:auth=md5
:md5_id=lpr@wayoff.com
lpr@wayoff = user1@host1 asdfasdfadf
The first entry corresponds to the md5_id value in the printcap.
The second field is the AUTHUSER value supplied to the server
and which will be used to look up the key in the servers key file.
Finally,
the last field is the salt value for the md5 calculation.Options used:
MD5KEYFILE=5location of user keyfileThe MD5KEYFILE environment variable contains the path to the
user keytab file.
Additional types of authentication support can be added very easily to LPRng by using the following conventions and guidelines.
First, the authentication method can be connection based or transfer based. Connection based authentication involves the LPRng client or server opening a connection to the remote server, having the authentication protocol provide authentication information, and then having no further interaction with the system. This is the easiest to implement and understand method. Code needs to be provided to do a simple authentication exchange between the two ends of the connection, after which no other action needs to be taken.
Transfer based authentication is more complex, but allows encrypted transfers of information between the two systems. A connection is established between client and server (or server and server), and an initial protocol exchange is performed. Then the authentication module transfers the command or job information to the destination, where is it unpacked and/or decrypted. The internal LPD server facilities are then invoked by the authentication module, which also provides a destination for any error message or information destined for the client. The authentication module will encrpt or encode this information and then send it to the client program. This type of authentication is more complex, but provides a higher degree of security and reliability than the simple connection based system.
By convention,
printcap entries
auth=XXX
and
auth_forward=XXX
specifies that authentication protocol XXX
is to be used for client to server
and for server to server transfers respectively.
Similarly,
the server receiving an authentication request must have a
XXX_id=name entry in the printcap or configuration information.
This allows several different authentication protocols to be accepted
by a server.
By convention,
printcap and configuration entries of the form
XXX_key
contain configuration information for the XXX authentication protocol.
As part of the authentication support process the XXX_key values
are extracted from the printcap and configuration files
and placed in a simple database for the authentication support module.
If you are using a routing filter,
then you can also place
XXX_key
information in the routing entry for each file,
and this will be used for sending the job to the specified destination.
The LPRng/src/common/sendauth.c
file has the following entries at the end.
#define SENDING
#include "user_auth.stub"
struct security SendSecuritySupported[] = {
/* name, config_tag, connect, send, receive */
{ "kerberos4", "kerberos", Send_krb4_auth, 0, 0 },
{ "kerberos*", "kerberos", 0, Krb5_send },
{ "pgp", "pgp", 0, Pgp_send },
#if defined(USER_SEND)
USER_SEND
#endif
{0}
};
This is an example of how to add user level authentication support.
The user_auth.stub
file contains the source code for the various modules authentication
modules.
You can replace this file with your own version
if desired.
The following fields are used.
The authentication name.
The auth=XXX printcap or configuration value will cause the
name fields to be searched using a
glob match.
When a match is found,
the config_tag value is used to search
the printcap and configuration entries for information.
If the config_tag field has value XXX,
then entries with keys XXX_key will be extracted for use
by the authentication code.
Routine to call to support connection
level authentication.
This routine is responsible for connection establishment and
protocol handshake.
If the value is 0,
then the send field value will be used.
Routine to call to support transfer
level authentication.
The send
routine is provided a file and a connection to the remote server,
and is responsible for the transferring files.
The
LPRng/src/common/lpd_secure.c
file has the following information at the end:
#define RECEIVE 1
#include "user_auth.stub"
struct security ReceiveSecuritySupported[] = {
/* name, config_tag, connect, send, receive */
#if defined(HAVE_KRB_H) && defined(MIT_KERBEROS4)
{ "kerberos4", "kerberos", 0, 0, 0 },
#endif
#if defined(HAVE_KRB5_H)
{ "kerberos*", "kerberos", 0, 0, Krb5_receive },
#endif
{ "pgp", "pgp", 0, 0, Pgp_receive, },
#if defined(USER_RECEIVE)
/* this should have the form of the entries above */
USER_RECEIVE
#endif
{0}
};
This information matches the same information in the sendauth.c
file.
When the authentication request arrives at the server,
the name field values are searched for a match,
and then the config_tag value is used to get extract configuration
information from the database for the protocol.
The receive
routine is then called and is expected to handle the remaining
steps of the authentication protocol.
If the routine exits with a 0 value then the lpd server expects
connection level authentication has been done and proceeds to
simply transfer information using the standard RFC1179 protocol steps.
A non-zero return value indicates an error and an error is reported
to the other end of the connection.
If the receive module is to perform transfer level authentication,
then the module carries out the necessary steps to transfer the command and/or
job information.
It then calls the necessary internal LPRng routine to implement the desired
services.
After finishing the requested work,
these routines return to the calling authentication module,
which then will transfer data, close the connection to the
remote system,
and return to the calling system.
The combination of 0 return value and closed connection
indicates successful transfer level authentication to the server.
The user_auth.stub file contains the following code that sets the
USER_SEND variable:
#if defined(SENDING)
extern int md5_send();
# define USER_SEND \
{ "md5", "md5", md5_send, 0, md5_receive },
#endif
If the SENDING value has been defined,
this causes the prototype for md5_send() to be place in the file
and the USER_SEND value to be defined.
This will cause the md5 authentication information to be placed in the
correct table.
Rather than go into a detailed description of the code,
the user_auth.stub file contains extremely detailed examples
as well as several working versions of authentication information.
It is recommended that the user start with one of these and then
modify it to suit themselves.