# General note about security

`pam_usb` is intended as an "user comfort" utility. While it can enhance security, if used as a second factor, it can also reduce it.

Make sure you are aware of how it works and what you combine it with (see other warnings).

Also I want to point it that this isn't audited. I've tried to raise funds for it but there was literally no interest in it seemingly...

# Warning about XDMCP

You should under no circumstances enable pamusb and XDMCP at the same time. Most graphical login managers are whitelisted and will not be checked for "remoteness" since issue #51 was fixed. This means if you enable XDMCP and have a usb device for an already configured user attached anyone connecting to your X-Server could login as that user!

I repeat, UNDER NO CIRCUMSTANCES ENABLE PAMUSB AND XDMCP AT THE SAME TIME! Don't say you haven't be warned if someone "hacks" your system because of this.

Note: you shouldn't use XDMCP these days anyway...

# Warning about remote desktop tools

Since v0.8.8, pam_usb ships built-in remote desktop detection controlled by the `remote_desktop_check` option (default: `true`). When enabled, authentication is denied if a known remote desktop service is detected as active.

## What is detected

| Tool | Detection method |
|------|-----------------|
| **AnyDesk** | Process presence alone — denied even if no remote session is active |
| **VNC** (x11vnc, Xvnc, GNOME Remote Desktop/VNC) | Process running **and** external established connection on port 5900 |
| **RDP** (GNOME Remote Desktop/RDP) | Process running **and** external established connection on port 3389 |
| **TeamViewer** | Process running **and** outbound connection to TeamViewer relay servers (port 5938) |
| **Virtual input devices** | Any tool that injects synthetic input via a `BUS_VIRTUAL` evdev device with no physical path |

All checks exclude loopback connections — a VNC or RDP session over localhost is not treated as remote.

## What is still NOT reliably detected

- TeamViewer in idle state (daemon running but no active remote session)
- x11vnc / Xvnc with no client currently connected
- VNC or RDP servers listening on non-standard ports
- GNOME desktop sharing over WebRTC (newer GNOME Remote Desktop protocol)
- Parsec, Rustdesk, Chrome Remote Desktop, NoMachine, and other tools not listed above

There will likely always be some remote access software that can circumvent the check. If this is a concern, use pam_usb as a second factor (`required` instead of `sufficient` in your PAM stack) so a password is still required even when pam_usb grants access.

## Known false positives

The virtual input device check (`BUS_VIRTUAL` evdev devices) can produce false positives for locally-running tools that happen to create synthetic input devices:

- Screen readers and on-screen keyboards
- Drawing tablet drivers (Wacom, Huion)
- Key remappers (keyd, xremap, input-remapper)
- Accessibility software

If pam_usb unexpectedly denies access and you do not use any remote desktop tools, set `remote_desktop_check=false` in the relevant section of `/etc/security/pam_usb.conf` to disable the check.

# Warning about remote access (SSH etc)

In the past there have been ways to circumvent the local check (see issue [#51](https://github.com/mcdope/pam_usb/issues/51) and also the "[cup of tee](https://github.com/mcdope/pam_usb/issues/39)"). I'm confident that all known ways are fixed now.

But I need to underline "known"... I'm no security expert and it's very well possible that there are still ways to circumvent the checks.

Kudos to [@Fuseteam](https://github.com/Fuseteam) for extensive testing, breaking and reporting.

# Warning about the ability to unlock the GNOME keyring

If you use the ability to auto-unlock your keyring while using pam_usb you are exposing your keyring password to everyone being able to access the file containing it.

This means at least root (and users able to use sudo) can read your keyring password in cleartext. If you use the SAMBA feature to share your home directory you will also expose it to everyone allowed to access that share.

For most users this isn't an issue. But if you're sharing your machine with other users, or use it in a network, you should for sure keep it in mind.

# Require a specific device for superuser access

In case you want to use multiple devices, and enable only one (or some) of them for superuser grants (su, sudo, polkit) you can do so with some manual configuration. You need to be sure about covering every mechanism/pam service used in your system though, in example if you enable it for sudo only but the user is able to run pkexec it will obviously fail to take effect.

Available from v0.8.7.

This feature allows you to designate specific USB devices as **superuser-capable** — valid for privilege-escalation services such as `sudo`, `su`, and `polkit-1` — while other registered devices remain valid only for non-privileged services (login, screensaver unlock, etc.).

A single `superuser="true"` attribute on a `<device>` element covers all services you mark as requiring it. No per-service device entries are needed.

**Use case:** In a shared-account environment (e.g. school lab), students and teachers use the same Unix account. Students carry a StudentUSB that lets them log in; teachers carry a TeacherUSB that additionally grants `sudo` access. The configuration enforces this without creating separate accounts.

---

### How it works

Two things must be configured for the restriction to take effect:

1. **Mark the device** as superuser-capable in the `<user>` block, using the `superuser="true"` attribute on the `<device>` element.
2. **Mark the service** as requiring a superuser device, by setting `<option name="superuser">true</option>` inside the corresponding `<service>` block.

When a user authenticates against a service marked with `superuser=true`, any device in their list that does **not** carry the `superuser="true"` attribute is silently excluded for that authentication attempt. If no superuser-capable device is present, authentication is denied.

Services **not** marked with `superuser=true` are unaffected — all registered devices for the user remain valid (fully backward-compatible).

---

### Option reference

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `superuser` | Boolean | `false` | When set on a `<service>`, only devices with `superuser="true"` in the user's device list are accepted for that service. No effect when set on `<defaults>`, `<devices>`, or `<users>`. |

---

### User configuration

The `<device>` element under `<user>` accepts an optional `superuser` XML attribute:

| Name | Type | Description | Example |
|------|------|-------------|---------|
| `superuser` | Attribute (optional) | Marks this device as valid for superuser services. Devices without this attribute are excluded when the service requires superuser. | `superuser="true"` |

```xml
<user id="alex">
    <!-- Works for login and all non-superuser services -->
    <device>StudentUSB</device>

    <!-- Works for all services including sudo, su, polkit-1 -->
    <device superuser="true">TeacherUSB</device>
</user>
```

A device with `superuser="true"` is **not** restricted to superuser services — it works for every service, including login. The attribute only adds eligibility for superuser-marked services.

---

### Service configuration

Mark any service as requiring a superuser-capable device by adding the `superuser` option:

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

<service id="su">
    <option name="superuser">true</option>
</service>

<!-- polkit-1 is also whitelisted for deny_remote by default -->
<service id="polkit-1">
    <option name="superuser">true</option>
    <option name="deny_remote">false</option>
</service>
```

You can apply the `superuser` option to any service name that appears in your PAM configuration — it is not limited to `sudo`, `su`, and `polkit-1`.

---

### Complete example

**Scenario:** A shared account `labuser` has two USB keys. The StudentUSB grants login only; the TeacherUSB grants login and sudo/pkexec.

```xml
<configuration>
    <devices>
        <device id="StudentUSB">
            <vendor>SanDisk Corp.</vendor>
            <model>Cruzer Blade</model>
            <serial>SNDKXXXXXXXXXXXXXXXX</serial>
            <volume_uuid>AAAA-1111</volume_uuid>
        </device>

        <device id="TeacherUSB">
            <vendor>Kingston</vendor>
            <model>DataTraveler</model>
            <serial>KNGXXXXXXXXXXXXXXXXX</serial>
            <volume_uuid>BBBB-2222</volume_uuid>
        </device>
    </devices>

    <users>
        <user id="labuser">
            <device>StudentUSB</device>
            <device superuser="true">TeacherUSB</device>
        </user>
    </users>

    <services>
        <service id="sudo">
            <option name="superuser">true</option>
        </service>
        <service id="su">
            <option name="superuser">true</option>
        </service>
        <service id="polkit-1">
            <option name="superuser">true</option>
            <option name="deny_remote">false</option>
        </service>
    </services>
</configuration>
```

**Result:**

| Device | Service | Outcome |
|--------|---------|---------|
| StudentUSB | login, gdm, screensaver | Allowed |
| StudentUSB | sudo, su, polkit-1 | **Denied** - no `superuser` attribute |
| TeacherUSB | login, gdm, screensaver | Allowed |
| TeacherUSB | sudo, su, polkit-1 | Allowed |

---

### Debug output

With `<option name="debug">true</option>`, the filtering is logged:

```
Service "sudo" requires superuser device. Filtering device list.
Device "StudentUSB" excluded for service "sudo" (no superuser attribute).
```

---

### Notes

- The restriction is configured entirely in `/etc/security/pam_usb.conf` — no PAM stack changes are needed.
- Adding more superuser-granted services requires only a new `<service>` entry; no change to the device or user configuration is needed.
- If a user has no device with `superuser="true"` and authenticates against a superuser-marked service, pam_usb denies the request. The fallback PAM module (e.g. `pam_unix`) still runs if configured as `sufficient` rather than `required`.
- `pamusb-conf` does not yet have a CLI flag for the `superuser` attribute — add it manually to the `<device>` element in the config file after running `pamusb-conf --add-user`. Tracked in [issue #337](https://github.com/mcdope/pam_usb/issues/337).