- C 97.5%
- Makefile 2%
- Shell 0.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .gitignore | ||
| auth.sh | ||
| Makefile | ||
| pam_termux_fingerprint.c | ||
| pam_termux_fingerprint_parallel.c | ||
| README.md | ||
| ssh_auth.c | ||
| ssh_auth.h | ||
pam-termux-fingerprint
A small, intentionally simple PAM module that authenticates users by executing a command over SSH and using its exit status as the authentication result.
Despite the original name, the module is not tied to fingerprints, Termux, Android, or any particular authentication mechanism. The remote command can perform whatever authentication logic you want, as long as it communicates the result through its exit code:
0→ authentication succeeds- non-zero → authentication fails
The included auth.sh demonstrates using this mechanism with the Termux API's fingerprint authentication.
How it works
┌─────────┐ SSH ┌──────────────────┐
│ PAM │ ──────────────> │ Remote SSH host │
│ module │ │ │
└─────────┘ │ authentication │
│ │ command │
│ └────────┬─────────┘
│ │
│ exit status │
│ <─────────────────────────────┘
│
├── 0 → PAM_SUCCESS
└── != 0 → PAM_AUTH_ERR
The module:
- Receives an SSH host, port, username, and command from PAM configuration.
- Connects using
/usr/bin/ssh. - Executes the configured remote command.
- Waits for it to finish.
- Uses the command's exit status as the authentication result.
The module does not need to understand what the remote command actually does.
Configuration
The module takes its configuration as a single pipe-separated argument:
IP|PORT|USER|COMMAND
The command supports these placeholders: %h for the local hostname, %s
for the PAM service, %u for the PAM username, %t for the TTY, %r for
the remote user, and %R for the remote host. Colons in the command are
converted to spaces, so sh:-c:check:%u is sent to SSH as sh -c check %u
after placeholder expansion.
An optional v argument enables verbose logging.
Example:
auth sufficient pam_termux_fingerprint.so 100.115.238.73|2222|u0_a407|fprint v
This tells PAM to execute:
ssh -p 2222 u0_a407@100.115.238.73 fprint
and interpret the result as:
exit 0 → authentication succeeded
exit != 0 → authentication failed
Example: Termux fingerprint authentication
The repository includes auth.sh as an example of a remote authentication helper:
#!/data/data/com.termux/files/usr/bin/bash
# minimal executable to bridge termux api logic to exit codes
[ "$(termux-fingerprint | jq -r '.auth_result')" = "AUTH_RESULT_SUCCESS" ]
The script converts the Termux fingerprint API result into a normal Unix exit status.
A successful fingerprint authentication causes the test expression to return 0.
A failed authentication causes it to return a non-zero status.
The PAM module therefore does not need to know anything about Termux or fingerprint JSON.
PAM example
A complete PAM configuration might look like:
#%PAM-1.0
auth sufficient pam_termux_fingerprint.so 100.115.238.73|2222|u0_a407|fprint v
auth sufficient pam_fprintd_grosshack.so
auth include system-auth
account include system-auth
session include system-auth
The exact PAM stack depends on what you are trying to authenticate and how your system is configured.
Building
Dependencies:
gccmake- PAM development headers
Build:
make
Install:
sudo make install
This installs the module to:
/usr/lib/security/pam_termux_fingerprint.so
SSH requirements
The PAM module invokes the system SSH client rather than implementing SSH itself.
The configured SSH connection therefore needs to work non-interactively.
In particular, the SSH connection must not require a password or interactive prompt, since PAM cannot wait for arbitrary SSH interaction.
The module uses:
BatchMode=yes
StrictHostKeyChecking=yes
and has connection/command timeouts to prevent an unavailable remote host from hanging authentication indefinitely.
Make sure the SSH host key is trusted before using the module.
Test the exact connection manually first:
ssh \
-p 2222 \
-o BatchMode=yes \
-o StrictHostKeyChecking=yes \
user@host \
command
Then check the exit status:
echo $?
Logging
Verbose logging can be enabled by adding v after the module configuration:
auth sufficient pam_termux_fingerprint.so 100.115.238.73|2222|u0_a407|fprint v
Logs are written to:
/var/log/pam_termux_fingerprint.log
For example:
sudo tail -f /var/log/pam_termux_fingerprint.log
With verbose logging enabled, the log records the PAM context, expanded SSH command, SSH target, child-process failures, SSH output, timeout details, and the final exit status. This is useful when a polkit authentication request fails before the remote helper appears to run. The command and SSH output may contain usernames or other context from the PAM request.
Designing your own authentication helper
The important part of this project is the exit-code interface.
Your remote helper can perform any authentication logic you want:
#!/bin/sh
if authentication_succeeded; then
exit 0
else
exit 1
fi
The PAM module does not care whether the command uses:
- a fingerprint sensor
- a hardware token
- a phone
- a custom API
- a challenge-response system
- some completely cursed shell script
As long as the command returns the appropriate exit status.
Security considerations
This module is intentionally minimal, but SSH-backed authentication introduces several security considerations.
SSH authentication
The SSH connection itself must be authenticated securely. Avoid configurations that disable host-key verification or otherwise allow a malicious host to impersonate the authentication server.
Non-interactive authentication
The SSH credentials used by the PAM process should be carefully restricted. Ideally, the remote SSH account should only be capable of running the intended authentication helper.
Remote command
Treat the configured remote command as trusted code. A compromise of the remote account or authentication helper could directly affect authentication.
Availability
Authentication now depends on the SSH connection and remote device being available. Network failures, an unavailable phone, or an unresponsive authentication helper will cause authentication to fail.
Timeouts
The module places a limit on how long the remote command can run, preventing a stuck SSH connection from blocking PAM indefinitely.
Why exit codes?
Using exit codes keeps the PAM module deliberately dumb.
Instead of implementing every possible authentication protocol inside the module:
PAM module
↓
SSH
↓
arbitrary authentication program
↓
exit 0 / exit non-zero
The remote program owns the authentication logic, while the PAM module only provides the bridge between SSH and PAM.
Status
This is a small experimental PAM module rather than a polished general-purpose authentication framework.
Use it with care, especially in PAM configurations that could affect your ability to log into the system.