Home / Alt manpages / pam_echo(8)

  • pam_echo(8)
  • Admin command
  • linux

Show a Useful PAM Login Message with pam_echo

By the end of this guide, a PAM stack can display a small text message such as the system name, the service being used and the account name. pam_echo is a PAM module, not a command you run at a shell prompt: a PAM-aware service loads its shared object while processing its configuration.

This guide uses the installed libpam-modules package, version 1.5.3-5ubuntu5.7 on this machine. Allow about 10 minutes. You need an ordinary shell for the checks and root access only if you change a system PAM file or place a message under a protected directory.

Checkpoint 1: understand what will change

pam_echo prints a file as a PAM text-information message. It provides all four PAM module types: auth, account, password and session. The module does not authenticate a user, change a password or grant access. The PAM application's conversation function decides whether and how that informational message reaches the user.

The configuration line has this shape:

type control pam_echo.so file=/path/to/message

type is the point in the PAM transaction, control is the stack rule and file= names the message file. The file contents are passed through PAM as PAM_TEXT_INFO. Keep the message short enough for the client to display clearly.

Checkpoint 2: create and inspect a message

First make a disposable message in /tmp. This step is unprivileged and does not alter PAM configuration:

message_file=$(mktemp /tmp/pam-echo.XXXXXX)
chmod 0644 "$message_file"
cat >"$message_file" <<'EOF'
Welcome to %h. Service: %s. Account: %u.
EOF
printf 'Message file: %s\n' "$message_file"
sed -n '1,3p' "$message_file"

Expected output is the temporary pathname followed by the line containing the literal placeholders. Do not expand those values in the shell. pam_echo expands them when PAM reads the message:

  • %H is the remote host, while %h is the local host.
  • %s is the PAM service name and %t is the controlling terminal.
  • %U is the remote user and %u is the local user.

Any other sequence beginning with % becomes the character after the percent sign. That fallback is easy to overlook: a literal percent sign in the message must therefore be written as %%.

Checkpoint 3: add the module to a PAM stack

Choose the service deliberately. PAM configuration is service-specific, so a line in /etc/pam.d/sshd affects SSH authentication, while a line in another file affects a different client. Inspect the target file before editing:

sudo sed -n '1,160p' /etc/pam.d/sshd

This is a privileged read. If the message file is still under /tmp, replace its pathname with the exact value printed in the previous step. A representative informational line is:

auth optional pam_echo.so file=/tmp/pam-echo.REPLACE

Place it at the point where the message makes sense. For example, an auth line is processed during authentication. The optional control flag means this module's result is not, by itself, required for the stack to succeed; it does not guarantee that a client will display the text.

Do not paste this example into a production PAM file without a recovery plan. A malformed PAM edit can prevent logins, and a message file in /tmp is not a durable deployment location. Use a root-owned path with suitable permissions for a real configuration, and keep an already-open root session while testing. The exact file edit is service-specific, so copy the line into a temporary review buffer first rather than using an automatic replacement command.

Checkpoint 4: verify the common failure paths

Check that the module exists and that the configured file is readable before testing a login:

test -r /usr/lib/x86_64-linux-gnu/security/pam_echo.so && echo 'module exists'
test -r "$message_file" && echo 'message is readable'

The module's documented return values explain several confusing results. A successful message returns PAM_SUCCESS. If the file does not exist, or the PAM transaction has the PAM_SILENT flag, the module returns PAM_IGNORE and prints nothing. A memory allocation failure returns PAM_BUF_ERR. A blank terminal therefore does not prove that the line was skipped by the stack: check the path, the service file and whether the client suppresses informational messages.

Test through the actual PAM-aware service rather than invoking the shared object. For SSH, make a new connection from a separate terminal and keep the existing session open. For a graphical display manager or another service, use that service's own safe test path. Do not repeatedly test a password stack with guesses, and do not use an account lockout policy as an experiment.

Undo and cleanup

After testing, remove the exact pam_echo.so line from the service file using the same privileged editing method you used to add it. Confirm the line is gone:

sudo grep -nF 'pam_echo.so' /etc/pam.d/sshd || echo 'pam_echo line removed'

Then remove the disposable message. This deletes only the pathname held in the shell variable:

rm -- "$message_file"

If the shell was closed, locate the specific temporary file with find /tmp -maxdepth 1 -type f -name 'pam-echo.*' -user "$(id -un)" -print and remove only the file you recognise. For a permanent setup, replace the temporary path with a reviewed root-owned file and document which PAM service owns the line.

Done means

  • The message file contains the text you intend to show and is readable by the PAM service.
  • The module line names the correct service, module type, control flag and file path.
  • Placeholders are left for PAM to expand, and literal percent signs are doubled.
  • A real PAM client was tested with a separate recovery session available.
  • The temporary configuration and message have been removed, or the permanent change is recorded and reviewable.