LPRng-HOWTO: 15 Oct 2001 (For LPRng-3.7.9)
Prev | Chapter 17. Permissions and Authentication | Next

# 17.17. Adding Authentication Support

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 encrypt 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.

## 17.17.1. Printcap Support

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.

## 17.17.2. Code Support

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.

name

  The authentication name. The `auth=XXX` printcap or configuration value will cause the `name` fields to be searched using a glob match.

config_tag

  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.

connect

  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.

send

  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.

## 17.17.3. Connection and Transfer Authentication

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.

Prev | Home | Next
Using MD5 for Authentication | Up | Accounting