NNRPD External Authentication Support

Table of Contents

  1. nnrpd External Authentication Support
  2. Reading Information from nnrpd
  3. Returning Information to nnrpd
  4. Error Messages
  5. HISTORY

nnrpd External Authentication Support

A fundamental part of the readers.conf(5)-based authorization mechanism is the interface to external authenticator and resolver programs. This interface is documented below.

INN ships with a number of such programs (all written in C, although any language can be used). Code for them can be found in authprogs/ of the source tree; the authenticators are installed to pathbin/auth/passwd, and the resolvers are installed to pathbin/auth/resolv.

Reading Information from nnrpd

When nnrpd spawns an external auth program, it passes information on standard input as a sequence of key: value lines. Each line ends with CRLF, and a line consisting of only a dot followed by CRLF (.\r\n) indicates the end of the input. The order of the fields is not significant. Additional fields not mentioned below may be included; this should not be cause for alarm.

(For robustness as well as ease of debugging, it is probably wise to accept line endings consisting only of LF, and to treat EOF as indicating the end of the input even if .\r\n has not been received.)

Code which reads information in the format discussed below and parses it into convenient structures is available authenticators and resolvers written in C; see libinnauth(3) for details. Use of the libinnauth library will make these programs substantially easier to write and more robust.

For Authenticators

When nnrpd calls an authenticator, the lines it passes are

    ClientAuthname: user\r\n
    ClientPassword: pass\r\n
    .\r\n

where user and pass are the username and password provided by the client (e.g. using AUTHINFO). In addition, nnrpd also passes, if available, the fields mentioned as intended for resolvers; in rare instances, this data may be useful for authenticators.

For Resolvers

When nnrpd calls a resolver, the lines it passes are

    ClientHost: hostname\r\n
    ClientIP: IP-address\r\n
    ClientPort: port\r\n
    LocalIP: IP-address\r\n
    LocalPort: port\r\n
    .\r\n

where hostname indicates a string representing the hostname if available, IP-address is a numeric IP address (dotted-quad for IPv4, equivalent for IPv6 if appropriate), and port is a numeric port number. (The LocalIP and LocalPort parameters may be useful for determining which interface was used for the incoming connection.)

If information is not available, nnrpd will omit the corresponding fields. In particular, this applies to the unusual situation of nnrpd not being connected to a socket; TCP-related information is not available for standard input.

Returning Information to nnrpd

Exit Status and Signals

The external auth program must exit with a status of 0 to indicate success; any other exit status indicates failure. (The non-zero exit value will be logged.)

If the program dies due to catching a signal (for example, a segmentation fault occurs), this will be logged and treated as a failure.

Returning a Username and Domain

If the program succeeds, it must return a username string (optionally with a domain appended) by writing to standard output. The line it should write is exactly

    User:username\r\n

where username is the string that nnrpd should use in matching readers.conf access blocks. The User parameter is case-insensitive.

There should be no extra spaces in lines sent from the hook to nnrpd; User:aidan is read by nnrpd as a different username than User: aidan. If a domain is provided, it would for instance be User:aidan@domain.

Note that nnrpd implements a five-second timeout for the receipt of this line.

Error Messages

As mentioned above, errors can be indicated by a non-zero exit value, or termination due to an unhandled signal; both cases are logged by nnrpd. However, external auth programs may wish to log error messages separately.

Although nnrpd will syslog() anything an external auth program writes to standard error, it is generally better to use the messages.h functions, such as warn() and die().

Please use the ckpasswd.c program as an example for any authenticators you write, and ident.c as an example for any resolvers.

HISTORY

Written by Aidan Cully for InterNetNews. This documentation was rewritten in POD by Jeffrey M. Vinocur <jeff@litech.org>.

Last modified and spun 2023-12-26