Radiator Server Documentation — v10.33.3

pap

PAP action for plaintext password authentication

Table of Contents
  • pap
  • Basic Syntax
  • Modes
  • Parameters
  • secret
  • range
  • Result
  • Backend Mapping
  • Related Actions

pap

Validates passwords using the Password Authentication Protocol (PAP). PAP transmits passwords in cleartext over the authentication protocol (though the protocol itself may be encrypted, such as RADIUS over TLS).

Can be combined with other authentication methods like totp or hotp for two-factor authentication.

Basic Syntax

@execute {
    backend {
        name "USERS";
        query "FIND_USER";
    }

    # Validate password
    pap;
}

Modes

The pap action has two modes that control whether it actually validates the PAP response or only stages it on the shared authentication state for later actions to consume.

FormModeDescription
pap; or pap authentication;AuthenticateRead the current PAP response from the protocol context and validate it against user.password. Records the authentication outcome on the AAA context.
pap response;Extract responseRead the current PAP response from the protocol context and store it on the shared authentication state as the canonical PAP response. Does not call the backend, does not compare credentials, and does not by itself decide accept or reject.
pap { ... }Block formSame as pap; by default. Add response; inside the block to switch to extract-only mode, or authentication; to be explicit. Combine with secret and/or range to override where the response comes from and which substring is used.

pap response; is useful when a later action should consume a shared, explicitly staged PAP response. Use it when you want to store the current PAP response on the shared authentication state without authenticating it.

Parameters

secret

Override the source of the PAP response with a context expression. The value of that expression is used as the PAP response bytes instead of the protocol's default credential location. Combine it with the filter pipeline to derive the value to authenticate from any context attribute.

Two-factor example using the substring() filter to strip a 6-digit OTP suffix off the PAP field before validating the static password portion:

pap {
    secret radius.request.password | substring(0, -6);
}

A simple TACACS+ continue-message example:

pap {
    secret tacacsplus.request.message;
}

When you use pap in a TACACS+ handler, restrict that handler to the TACACS+ request variants that actually carry a PAP-style password. Do not match only tacacsplus.authentication == true; and then run pap; for every TACACS+ authentication request.

For combined <password><otp> fields where the OTP is a Yubico OTP, see the yubikey() filter.

secret is only valid inside the block form pap { ... } and can be combined with either authentication; (validate the supplied value against user.password) or response; (only stage the supplied value).

range

Slices the PAP response by character offsets before validation. Prefer secret together with the filter pipeline (for example substring() or yubikey()) for new configurations; range remains supported mainly for backward compatibility and is limited to a single contiguous slice.

Syntax: range <start> <end> [exclusive]

  • <start> - Starting index (negative values count from end)
  • <end> - Ending index (negative values count from end)
  • exclusive - Optional keyword to invert the range (extract everything except the specified range)
  • Indices are 0-based
# Extract all but the last 6 characters (typical password portion in 2FA)
pap {
    range -6 0 exclusive;
}

Result

The pap action produces the following pipeline results:

  • Accept: The supplied password matches the stored password. Execution continues to the next action.
  • Reject: Authentication failed. This occurs when:
    • The user was not found (reason: "No such user"). Ensure the preceding backend action populates user.password.
    • The password does not match (reason: "Incorrect password").
  • Ignore: The request does not contain PAP credentials. This allows combining pap with other authentication actions such as chap or mschapv2 in the same pipeline - the non-matching action is skipped.

Backend Mapping

The backend must populate the user password:

backends {
    sqlite "USERS" {
        filename "users.db";
        query "FIND_USER" {
            statement "SELECT username, password FROM users WHERE username = ?";
            bindings {
                aaa.identity;
            }
            mapping {
                user.username = username;
                user.password = password;  # Required for PAP
            }
        }
    }
}

Required context variables:

  • user.password - User's password for comparison
  • http-basic-auth - HTTP Basic Authentication for HTTP server handlers
  • totp - Time-based OTP for 2FA
  • hotp - Counter-based OTP for 2FA
  • chap - Challenge-response authentication
  • mschapv2 - Microsoft CHAP v2 authentication
Navigation
  • accept

  • append

  • assert

  • backend

  • challenge

  • chap

  • conditions

  • copy

  • count

  • debug

  • discard

  • EAP

  • error

  • filter

  • hotp

  • http-basic-auth

  • if

  • ignore

  • invoke

  • log

  • map

  • message

  • modify

  • mschap

  • mschapv2

  • must

  • pap

  • reason

  • reject

  • reject_errors

  • replace

  • reply

  • rewrite

  • set

  • sleep

  • sometimes

  • stop

  • totp

  • trace

  • try

  • until

  • yubikey

Related
  • http-basic-auth
  • totp
  • hotp
  • chap
  • mschapv2