Next Previous Contents

## 9. The /etc/lpd.perms Permissions File

This file is used to specify the restrictions on the use of the LPRng software, printers, and other facilities. The following is an example of a `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

The structure of the lpd.perms file was inspired by network packet filter configuration files. When the LPD server gets a request from a remote client program, it performs the checks specified by the rules in the `lpd.perms` to decide whether to accept or reject the request.

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 USER=john,bill` succeeds only if USER is defined and the USER value is not `john` or `bill`.

The following patterns and matching are applied.

Keyword | Match
`DEFAULT` | default result
`SERVICE` | lpC Status and User, lpR, lprM, lpQ request
`USER` | user name in print job
`REMOTEUSER` | user making request
`HOST` | host name in print job
`REMOTEHOST` | host making request
`IP` | IP address and mask of host in print job
`REMOTEIP` | IP address and mask of host making request
`PORT` | TCP/IP port of host making request
`SAMEUSER` | USER and REMOTEUSER same
`SAMEHOST` | HOST and REMOTEHOST same
`SERVER` | request originates on lpd server
`FORWARD` | destination of job is not host
`GROUP` | USER is in the particular group
`REMOTEGROUP` | REMOTEUSER is in the particular group
`CONTROLLINE` | match a line in control file
`AUTH` | authentication type
`AUTHUSER` | authenticated user
`FWDUSER` | authenticated forwarder

Most of the patterns can be lists of alternative values to match, and can even contain wild cards. The full details of the rules and keywords are detailed in the `lpd.conf(5)` man page.

## 9.1 Information for matching

In order to do matching, the `lpd` server obtains and sets up the following information:

1. If the request is coming over a network connection, then the IP address (REMOTEIP) port (PORT) of the source of the connection and FQDN of the remote host (REMOTEHOST) are obtained and the indicated values are set. To be specific, the IP address of the remote host is obtained using `getpeername()`. The `gethostbyaddr()` is used to look up the host's fully qualified domain name, which is then assigned to the REMOTEHOST value. The REMOTEIP value is the set or list of IP addresses that could be used by this host. This is possible in the IPV6 environment.
2. If the request contains the name of the user, then REMOTEUSER is assigned the name.
3. If the request contains the name of the printer, then PRINTER is assigned the name.
4. If a print job is being printed, then the USER, HOST, IP, and PRINTER are set to the user name, host, and printer information in the control file for the print job. To be specific, the HOST entry in the control file is used by `gethostbyname()` to get the fully qualified domain name of the host. The IP value is assigned a set or list of IP addresses that could be used by this host.
5. If one of the optional authentication methods is being used, (see Authentication and Encryption), then AUTH is set to NONE, USER, or FWD, depending on the type of operation and authentication present. AUTHUSER to the authenticated originating user of the request and FWDUSER is set to the forwarding servers authentication information (if any).

## 9.2 Permission Checks

When a connection is made to the `lpd` server, the originating site's IP address and hostname are determined, and a check with `SERVICE=X` is made. The REMOTEHOST, REMOTEIP, and PORT will be defined for the purposes of this check.

If the result is to accept the connection, then the request is then read from the connection, and the SERVICE, REMOTEUSER and PRINTER will be defined. A further check is performed to determine if the service request would be accepted.

When performing a service activity and a particular job is to be acted on, the USER, HOST, and other control file information will be available, and a further check can be performed.

If a rule is specified and the particular value is not defined, then a rule will fail to match.

## 9.3 Match Procedure

    key=pattern                         substring match
    key=pattern1,pattern2,pattern3,...  glob and exact
    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:

1. substring match. The indicated entry is present as a substring in the pattern.
2. GLOB matches. The pattern is interpreted as a GLOB style pattern, where * matches 0 or more characters, and ? matches a single character.
3. Exact string match. There is no glob matching performed and the strings must match exactly.
4. IP address match. The address must be specified in the standard `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.

5. integer range match. The pattern has the form `low-high`, where low and high are integer numbers. The match succeeds if the value is in the specified range.
6. Same IP Address Match. This compares two lists of IP addresses; a match is found when there is one or more common addresses.

### DEFAULT

    DEFAULT ACCEPT
    DEFAULT REJECT

The DEFAULT rule specifies the default if no rule matches. Normally, there is one DEFAULT entry in a permissions file.

### SERVICE

Options used:

- `user_lpc=`allow set of lpc actions on user files

Match type: substring

The SERVICE key is based on the type of request.

Key | Request
`C` | LPC Control Request
`M` | LPRM Removal Request
`P` | Job Printing
`Q` | LPQ Status Request
`R` | LPR Job Transfer
`S` | LPC Status Request
`U` | LPC User File Request
`X` | Connection Request

Each of the above codes corresponds either directly to the user command, or a set of subcommands.

All the LPC subcommands are SERVICE=C; status commands such as `lpc status, printcap, active,` or `lpd` are SERVICE=S commands as well.

The `user_lpc` configuration option can be used to specify a set of control commands that can be applied to individual user files in a spool queue. These commands include `user_lpc=` `hold`, `release`, `move`, `topq`, `kill`, and `abort`. When the `user_lpc` specifies one of these commands, the `lpd` program will delay rejecting a request until the individual files in a queue are checked for permission. This allows the following permissions line to be used:

    #allow root on server all permissions
    ACCEPT SERVICE=C SERVER REMOTEUSER=root
    #allow all status commands
    ACCEPT SERVICE=S
    #allow same user on same host to use user_lpc commands
    ACCEPT SERVICE=U SAMEUSER SAMEHOST
    #note that this has effect for U only when file checks are performed
    REJECT SERVICE=UCS

The above permissions entry will allow users to perform the actions specified by `user_lpc` on their files.

### USER

Match type: GLOB

The USER information is taken from the `P` (person or logname) information in the print job control file.

### REMOTEUSER

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.

### HOST

Match type: GLOB

The HOST information is taken from the `H` (host) information in the print job control file.

### REMOTEHOST

Match type: GLOB

The REMOTEHOST information is obtained by doing a reverse IP name lookup on the remote host address. If there is no FQDN available, then the IP address in text form will be used.

### PORT

Match type: integer range

The PORT value is obtained from the originating port of the TCP/IP connection. The match succeeds if it is in the specified range.

### IP

Match type: IPaddr

The IP information is obtained by doing a DNS lookup on the H (host) information in the control file. If there is no host information, the IP address is undefined. Note that for a single host name there may be multiple IP addresses; address matches are performed against the list of addresses and succeeds if there is one or more individual address matches.

### REMOTEIP

Match type: IPaddr

The REMOTEIP information is the IP address of the host making the service request. Note that the REMOTEIP value is obtained by using the `gethostbyaddr` lookup to obtain the DNS information for the remote host. This information may include multiple IP addresses; address matches are performed against the list of addresses and succeeds if there is one or more individual address matches.

### SAMEUSER

Match type: exact string match

Both the REMOTEUSER and USER information must be present and identical.

### SAMEHOST

Match type: Same IP Address

The REMOTEHOST and HOST address lists are checked; if there is a common value the match succeeds.

### SERVER

Match type: Same 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()`.

### FORWARD

Match type: Address Match

The list of REMOTEHOST and HOST addresses must not have a common entry. This is identical to NOT SAMEHOST. This is usually the case when a remote `lpd` server is forwarding jobs to the `lpd` server.

### GROUP

Match type: modified GLOB

If the pattern does not start with a `@` character, then the USER information must be present and 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 starts with a `@` character, then the USER information must be present and the user must be in the specified `netgroup`. This match will be performed only if the `netgroup` mechanism is supported on the system and the specified netgroup exists. No wildcard match will be done for netgroups.

### REMOTEGROUP

The same rules as for GROUP, but using the REMOTEUSER value.

### CONTROLLINE

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.

### AUTH

Match type: GLOB

The AUTH value can be NONE, indicating that no authentication was done. If authentication was done, then AUTH=USER checks to see if there was user information, and AUTH=FWD checks to see if there was forwarding system identification.

### AUTHUSER

Match type: GLOB

If AUTH=USER check succeeds, the AUTHUSER rule will check to see if the user identification matches the pattern.

### FWDUSER

Match type: GLOB

If AUTH=FWD check succeeds, the FWDUSER rule will check to see if the forwarding system identification matches the pattern.

### IFIP

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 origination of the request, 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 cannonical host name. Some systems which use the Domain Name Server (DNS) system may add the cannonical system name as an alias.

## 9.4 Permission File Location

Options used:

- `perms_path=` directory path list
- `xu=` additional permission file pathname

The `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

In addition, the `xu` (extra permissions file) specifies an additional per-printer permissions file to be used when checking permissions for a particular printer.

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

Then the `get_perms` program would be invoked with STDIN attached to `/dev/null` and the complete set of permission information would be read from its STDOUT.

## 9.5 Example Permission 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

In the above sample, we first specify that lp`C` commands from user `root` on the lpd server will be accepted. This is traditionally the way that most lpc commands operate.

Next, we reject any other lpc requests.

We accept lpr`M` 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.

## 9.6 Complex Permission Checking

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 reverse the match sense. For example `REJECT NOT REMOTEHOST=*.astart.com,*.murpy.com` would reject all requests from hosts which did not have a DNS entry ending in `astart.com` or `murphy.com` as one of the host name components.

## 9.7 More Examples

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

Next Previous Contents