Troubleshooting
===============

Don't panic!

Log Analysis
------------

Most pam_usb tools log to syslog, but not all:

| Tool | Logs to syslog | Facility / tag |
|------|:-:|---|
| `pam_usb.so` | Yes | AUTH — usually `/var/log/auth.log` |
| `pamusb-agent` | Yes | AUTH — usually `/var/log/auth.log` |
| `pamusb-keyring-unlock-gnome` | Yes | LOCAL0 — tag `pamusb-keyring-unlock-gnome` |
| `pinentry-pamusb` | Yes | AUTH — tag `pinentry-pamusb` |

This can be useful for GUI-driven applications (for instance GDM) where you
don't get to see console output.
AUTH messages are usually written to `/var/log/auth.log` but may vary
depending on the operating system you're using.

    # tail -f /var/log/auth.log
    pamusb-agent[25429]: Device "sandisk" has been inserted. Performing
    verification...
    pamusb-agent[25429]: Executing "/usr/bin/pamusb-check --quiet
    --config=/etc/pamusb.conf --service=pamusb-agent scox"
    pam_usb[25485]: Authentication request for user "scox" (pamusb-agent)
    pam_usb[25485]: Device "sandisk" is connected (good).
    pam_usb[25485]: Access granted.
    pamusb-agent[25429]: Authentication succeeded. Unlocking user "scox"...
    pamusb-agent[25429]: Unlocked.

On systems using systemd without a traditional syslog daemon, `/var/log/auth.log` may not exist. Use journalctl instead:

    # journalctl -f -t pam_usb -t pamusb-agent -t pamusb-keyring-unlock-gnome -t pinentry-pamusb

**Troubleshooting pinentry-pamusb:** Authentication results, passphrase delivery, and fallback events are logged to syslog (AUTH facility, tag `pinentry-pamusb`). Check the log with:

    journalctl -t pinentry-pamusb

For deeper gpg-agent protocol issues, enable gpg-agent debug logging (`--debug-all` in `~/.gnupg/gpg-agent.conf`).

For `pamusb-check` you can also use the `--debug` argument, but that is only temporary and wont help you with i.e login manager issues.

Enabling debug
--------------

Enabling debug messages may help you find out what's wrong.

To enable them, edit `/etc/security/pam_usb.conf` and set the following option:

```xml
<defaults>
  <option name="debug">true</option>
</defaults>
```
You can also enable debug messages only for a specific user, device or service.

```xml
<services>
  <service id="sudo">
    <option name="debug">true</option>
  </service>
</services>
```

Device not detected at all
--------------

If pam_usb reports no device is connected even though the USB stick is plugged in, work through these steps:

**1. Verify pam_usb can see your device at all:**

    pamusb-conf --list-devices

This lists every removable device UDisks2 currently sees. If your device appears here but authentication still fails, the serial/vendor/model in `/etc/security/pam_usb.conf` does not match the device.

If your device does not appear here, continue below.

**2. Check that UDisks2 is running:**

    systemctl status udisks2

pam_usb talks to UDisks2 over D-Bus to enumerate devices. If UDisks2 is stopped or crashed you will see `"Unable to check for device, could not get UDisksClient!"` in the log and no device will ever be found. Start and enable it:

    sudo systemctl start udisks2
    sudo systemctl enable udisks2

**3. Device detected but authentication still fails — check for config mismatch:**

Run `pamusb-check --debug <username>` with the device plugged in and look for lines like:

    Serial "XXXX" doesn't match "YYYY"

This means the serial number in your config does not match the physical device. Re-run `pamusb-conf --add-device` to pick up the correct values.

**4. Device takes too long to be detected:**

pam_usb waits up to `probe_timeout` seconds (default `10s`) for the device volume to appear. On slower USB sticks or busy systems this can expire before the device is ready, producing a "not connected" denial even though the device is physically present.

Increase the timeout in `/etc/security/pam_usb.conf` — either globally or for the specific device:

```xml
<device id="MyDevice">
  <option name="probe_timeout">20s</option>
</device>
```

Getting 'Access denied' on graphical terminals / when using agent
--------------

Most times this is caused by pamusb not being able to determine your login/session tty. This shouldn't happen with current builds since we support multiple ways to determine it by now.

If it does happen, enable debug and look for this specific line in the log:

    Couldn't confirm login tty to be neither local or remote - denying.

If you see that line, pam_usb exhausted all TTY detection methods without being able to confirm the session is local. Please create an issue which should contain the output of `w` and `pamusb-check --debug <yourusername>`. Please also specify your distribution, login manager and desktop environment used. The default issue template will assist you with this.


Getting 'Pad checking failed!' when trying to authenticate
--------------

This error means that either the machine/host specific pad file on the device, or - more likely - the user specific pad file in your homedir is not in sync anymore. It can also be caused if you use the same device on two computers and both share the same username (guess why I know :facepalm:).

It can happen if you remove the authentication device without unmounting it before, manually mess with the pad files (like copying from a previous device) or your system crashed before file buffers were written to the media and similar.

Or, worst case scenario - someone tried to tamper with your system. In example someone could deep-clone (not only FS but also HW Ids) your authentication device and use it to login or sudo (if you use pamusb as the only factor), pads will then be updated on system and the attacking device but not on your original device since it wasn't connected at the time of your login. On next authentication request with your original device you will then get "Pad checking failed!". Of course for most persons this is an unlikely scenario. Also this would only work if the attacker uses his device before you use yours the next time. Else your authentication would invalidate his pads. But if your system and/or device is accessible to other persons, keep it in mind.

**Related pad errors you may see in the debug log:**

- `"Device pad is incomplete"` / `"System pad is incomplete"` — the pad file exists but is shorter than expected (1024 bytes). Usually caused by a filesystem write interrupted by an unclean unmount or system crash.
- `"System pad missing but device pad exists"` — the pad file was deleted from your home directory (or never written) but the device-side pad still exists. This can indicate an interrupted first authentication, a manual deletion, or — in the tamper scenario — that someone authenticated from your device on another machine.

All of these have the same resolution: reset the pads so they are regenerated cleanly on the next successful authentication.

To resolve this you can use `pamusb-conf --reset-pads=<USERNAME>`, which will remove the pad files for the given user and its configured device so they will be regenerated on next authentication.

Agent configuration / commands don't work like expected
--------------

You have restarted the agent service after your config changes, right? RIIIIIIGHT? Seriously, you need to restart it for changes to be picked up.

The agent will log all executed commands, as well as their exitcode; stdout and stderr (since v0.8.3). You can view this log either via systemd, or by `tail`'ing `/var/log/auth.log` — or on systems without a traditional syslog daemon:

    # journalctl -f -t pamusb-agent

You can use this to a) verify your config is picked up like expected and b) configured commands do what you want. For some programs, esp. ones expecting to be run within a graphical environment, you will have to provide environment values via `<env>` tags in the agent configuration. Usually the log will provide you with some good clues. But feel free to open a support issue if you need help.

**Environment variables silently rejected:**

The agent blocks a set of dangerous environment variables to prevent privilege escalation. If you set any of the following in an `<env>` tag they will be ignored and a warning logged — the command will run without them:

    LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, LD_DEBUG, GLIBC_TUNABLES,
    PYTHONPATH, PERL5LIB, RUBYLIB, IFS, CDPATH, ENV, BASH_ENV, PATH

Look for `Rejecting dangerous env var` in the agent log if a command behaves unexpectedly. If you need to set `PATH` for a command, wrap it in a small shell script that sets the path internally, and call the script from `<cmd>` instead.


pam_usb not working in login manager when the device wasn't plugged before login manager started / always asked for password
--------------

Are you using `lightdm` by any chance?

Some login managers auto-select the first user they have in their list. This starts the pam chain and pam_usb will see "device is not plugged" and deny the request. At that point then pam_unix (or whatever your next module is) kicks in and asks for the password. This is intended behavior in pam_usb - the actual issue here is the login manager assuming which user wants to login.

Even if you now plug the device, from pam_usb POV the request is failed/finished and it wont care anymore. You will have to press [ESC] to abort the current authentication request and click/select the user again (if not auto-selected).

You can reduce how often this happens by configuring a service-specific `probe_timeout` for lightdm. This gives pam_usb a longer window to detect the device after the chain starts — if you plug in the USB stick within that window, authentication succeeds without needing to press ESC:

```xml
<services>
  <service id="lightdm">
    <option name="probe_timeout">30s</option>
  </service>
</services>
```

My screen wont lock when using pam_usb
--------------

Are you using KDE / `klockscreen` by any chance? And is your device still plugged?

Some lockscreens start the PAM chain already at time of lock. If you use only a password, that's fine. But if you use pam_usb, it will see "hey, the device is there and valid - I'll allow this". It's basically the inverted version of the topic in the paragraph above (see https://github.com/mcdope/pam_usb/wiki/Troubleshooting#pam_usb-not-working-in-login-manager-when-the-device-wasnt-plugged-before-login-manager-started--always-asked-for-password)

If you are not using KDE, please create an issue.

SELinux and pam_usb
--------------

If you have SELinux enabled you will likely get errors with pam_usb. At least on Fedora 40 you need to allow some things that are by default denied.

There is now a profile available for Fedora 40 that you can install to allow pam_usb to work like intended. To install it download both files from `selinux/<yourDistribution>` to some directory, open a shell in that directory and then run `semodule login.pp`. Replace "login" with the actual profile you want to install, but so far there is only one for login. It may work on other distributions or releases, too but this is untested.

In case it doesn't work for you, see the discussion at https://github.com/mcdope/pam_usb/discussions/241 to find out how to create your own profile.

PolicyKit 127 and pam_usb
--------------

PolicyKit starting from 127 and pam_usb are incompatible in the default configuration. This is caused by the [introduction of a socket based polkit-agent-helper](https://github.com/polkit-org/polkit/commit/c007940054392b67b84b6044dda8a215040d8eb5). You will have to a) disable the socket service b) re-enable suid and c) redo that on every polkit upgrade until they fix their agent (not only pam_usb is influenced by this).

Details:

#### 1. Disable the Systemd Socket
Stop and disable the socket so systemd stops intercepting the authentication requests. Open your terminal and run:
```bash
sudo systemctl disable --now polkit-agent-helper.socket
```

#### 2. Restore the SUID Bit on the Helper Binary
Because you disabled the socket, polkit will fall back to executing the agent helper directly. For this to work, the binary **must** have the SUID (Set Owner User ID) bit set. Since your distribution's package manager likely stripped this bit in the v127 update, you will need to restore it manually.

First, locate your `polkit-agent-helper-1` binary. It is typically found at one of these two paths, depending on your distribution:
* `/usr/lib/polkit-1/polkit-agent-helper-1` (Debian, Ubuntu, Fedora, openSUSE)
* `/usr/libexec/polkit-1/polkit-agent-helper-1` (Arch Linux)

Once you confirm the path, restore the SUID bit and set root ownership:
```bash
sudo chown root:root /usr/lib/polkit-1/polkit-agent-helper-1
sudo chmod u+s /usr/lib/polkit-1/polkit-agent-helper-1
```
*(Remember to replace the path if your system uses the `/usr/libexec/` directory).*

#### A Quick Warning on Package Updates
Because you are modifying the permissions of a package-managed file manually, a future update to the `polkit` package might overwrite your changes and strip the SUID bit again. Many distributions are currently working on patches or have temporarily downgraded polkit to `126` in their repositories, so keeping your system up-to-date should eventually resolve the underlying bug natively.

#### Alternative way, without messing with polkit
Create a copy of your common-auth pam config (or whatever file it is on your distribution) and name it polkit-1. Remove pam_usb from it.


Remote Desktop / Remote Access Detection
--------------

pam_usb can block authentication when it detects an active remote desktop session. This page covers how the check works, why it might fire unexpectedly, and how to handle it.

#### How it works

When `deny_remote` and `remote_desktop_check` are both enabled (the defaults), pam_usb checks for remote access via two layers before accepting a USB token:

1. **Remote service detection** — checks for known remote desktop software
2. **Virtual input device detection** — checks for `BUS_VIRTUAL` evdev devices (commonly created by remote desktop tools)

Both must clear for authentication to proceed.

#### Detected services and their trigger conditions

| Service | What triggers a deny |
|---|---|
| **AnyDesk** | Process `anydesk` is running (any connection state) |
| **VNC** (gnome-remote-desktop, x11vnc, Xvnc) | External ESTABLISHED connection on local TCP port 5900 **and** a matching VNC server process |
| **RDP** (gnome-remote-desktop) | External ESTABLISHED connection on local TCP port 3389 **and** `gnome-remote-de` process running |
| **TeamViewer** | Outbound ESTABLISHED connection to remote TCP port 5938 **and** `TeamViewer_Desk` or `teamviewerd` process running |

All checks use `/proc/net/tcp` (IPv4) and `/proc/net/tcp6` (IPv6). Loopback connections (`127.x.x.x`, `::1`) are never counted as external.

"External" means: ESTABLISHED state + non-loopback remote address.

---

#### Common false positives

##### AnyDesk installed but not in a session

AnyDesk is detected by process presence alone — if the daemon is running in the background (which it does by default on many installs), pam_usb will deny even without an active connection.

**Fix:** Disable the AnyDesk background service when not needed:

```sh
systemctl disable --now anydesk
```

Or stop it temporarily before authenticating:

```sh
sudo systemctl stop anydesk
```

##### Accessibility tools / input remappers

Software that creates virtual input devices (e.g. key remappers, on-screen keyboards, tablet drivers, disability assistance tools) may register a `BUS_VIRTUAL` evdev node. pam_usb treats this as a signal that a remote desktop tool could be injecting input.

Affected tools include (non-exhaustive):

- Screen readers / on-screen keyboards that synthesise input
- Drawing tablet drivers that register virtual devices (some Wacom, Huion setups)
- Key remappers (e.g. `keyd`, `xremap`, `input-remapper`)
- Accessibility software like `xdotool` daemons

**Workaround:** Disable `remote_desktop_check` in `pam_usb.conf` if you rely on such devices and cannot remove them:

```xml
<option name="remote_desktop_check">false</option>
```

Or disable the virtual device service before authenticating, then re-enable it.

##### VNC/RDP port in use by an unrelated app

Any process that listens on port 5900 (VNC) or 3389 (RDP) with an external ESTABLISHED connection will trigger the port check. The matching process name must also be present — but if it is, authentication is denied.

If you run a non-standard VNC or RDP server on these ports, pam_usb will catch it. Move the service to a non-standard port or disable `remote_desktop_check`.

##### TeamViewer installed but idle

TeamViewer will **not** trigger a deny unless it has an active outbound connection to a relay server (port 5938). Simply having TeamViewer installed or the daemon running without an active session is fine.

If it is denying unexpectedly, check:

```sh
grep ' 1742 ' /proc/net/tcp   # hex 1742 = port 5938
grep ' 1742 ' /proc/net/tcp6
```

If you see `01` in the state column, TeamViewer has an active relay connection.

#### Diagnosing a deny

Enable debug logging in `pam_usb.conf`:

```xml
<option name="debug">true</option>
```

Then attempt authentication and read the output. Relevant log lines:

```
Checking for active remote desktop services...
  Checking for known remote desktop processes...
    Found remote service process: anydesk
Active remote desktop service with connection detected, denying.
```

```
Virtual input device detected (possible remote desktop tool), denying.
```

```
XRDP session detected, denying.
```

The debug output will name the exact check that fired.


#### Disabling the check entirely

To skip remote desktop detection while keeping all other pam_usb protection:

```xml
<option name="remote_desktop_check">false</option>
```

To disable all remote/local discrimination (not recommended):

```xml
<option name="deny_remote">false</option>
```

Both options can be scoped to a specific user or service in the config hierarchy.

#### Configuration reference

| Option | Default | Effect |
|---|---|---|
| `deny_remote` | `true` | Master switch — if false, no remote checks run at all |
| `remote_desktop_check` | `true` | Enables process + port + virtual-device checks described on this page |