VYPR
High severity8.2NVD Advisory· Published May 27, 2026

CVE-2026-44712

CVE-2026-44712

Description

pam_usb provides hardware authentication for Linux using ordinary removable media. Prior to 0.8.7, a crafted UUID such as $(id>/tmp/rce) in the config causes root RCE when pamusb-conf --reset-pads is run. A USB device with a crafted filesystem UUID (some controllers allow this) can inject the payload at --add-device time. Also, userName from the XML config is passed to os.system() in pamusb-agent, which invokes a shell. This vulnerability is fixed in 0.8.7.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Shell injection vulnerabilities in pam_usb ≤0.8.6 allow root RCE via crafted USB UUID or username in config.

Vulnerability

pam_usb versions 0.8.6 and earlier contain two shell injection vulnerabilities. In pamusb-conf, the device UUID read from the XML config is interpolated into a shell command with shell=True, allowing a crafted UUID like $(id>/tmp/rce) to execute arbitrary commands when pamusb-conf --reset-pads is run. In pamusb-agent, the userName from the XML config is passed to os.system(), which invokes a shell, enabling root RCE via shell metacharacters in the username [1].

Exploitation

For the UUID injection, an attacker with physical access can craft a USB device with a malicious filesystem UUID (some controllers allow this) and plug it into the target system, then trigger pamusb-conf --add-device followed by --reset-pads. For the username injection, an attacker who can modify the pam_usb XML config (e.g., through a compromised system or misconfiguration) can set a username containing shell metacharacters, leading to command execution when pamusb-agent runs [1].

Impact

Successful exploitation results in root-level remote code execution, granting the attacker full control over the affected system. The CIA impact is total compromise, with the attacker able to execute arbitrary commands with root privileges [1].

Mitigation

The vulnerabilities are fixed in version 0.8.7. The fix commits (d9acb56) validate UUIDs against a whitelist of hexadecimal characters and replace os.system() with subprocess.run() using an argument array, avoiding shell interpolation. Users should upgrade to 0.8.7 immediately [1]. No workaround is available for unpatched versions.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Mcdope/Pam Usbinferred2 versions
    <0.8.7+ 1 more
    • (no CPE)range: <0.8.7
    • (no CPE)range: <0.8.7

Patches

3
014042451850

[Security] Fix multiple advisories of various crititicallity - UPDATE ASAP!

https://github.com/mcdope/pam_usbMcDopeMay 4, 2026Fixed in 0.8.7via llm-release-walk
8 files changed · +170 39
  • src/conf.c+1 1 modified
    @@ -216,7 +216,7 @@ int pusb_conf_parse(
     			continue;
     		}
     
    -		strcpy(opts->device_list[currentDevice].name, device_list[currentDevice]);
    +		snprintf(opts->device_list[currentDevice].name, sizeof(opts->device_list[currentDevice].name), "%s", device_list[currentDevice]);
     		pusb_conf_parse_device(opts, doc, currentDevice, device_list[currentDevice]);
     	}
     
    
  • src/device.c+15 3 modified
    @@ -50,16 +50,28 @@ static int pusb_device_connected(t_pusb_options *opts, UDisksClient *udisks)
     			if (udisks_object_peek_drive(object))
     			{
     				drive = udisks_object_get_drive(object);
    -				retval = strcmp(udisks_drive_get_serial(drive), opts->device_list[currentDevice].serial) == 0;
    +
    +				const gchar *serial = udisks_drive_get_serial(drive);
    +				if (!serial)
    +				{
    +					log_debug("Drive has no serial number, skipping.\n");
    +					g_object_unref(drive);
    +					continue;
    +				}
    +				retval = strcmp(serial, opts->device_list[currentDevice].serial) == 0;
     
     				if (strcmp(opts->device_list[currentDevice].vendor, "Generic") != 0)
     				{
    -					retval = retval && strcmp(udisks_drive_get_vendor(drive), opts->device_list[currentDevice].vendor) == 0;
    +					const gchar *vendor = udisks_drive_get_vendor(drive);
    +					retval = retval && vendor != NULL &&
    +					         strcmp(vendor, opts->device_list[currentDevice].vendor) == 0;
     				}
     
     				if (strcmp(opts->device_list[currentDevice].model, "Generic") != 0)
     				{
    -					retval = retval && strcmp(udisks_drive_get_model(drive), opts->device_list[currentDevice].model) == 0;
    +					const gchar *model = udisks_drive_get_model(drive);
    +					retval = retval && model != NULL &&
    +					         strcmp(model, opts->device_list[currentDevice].model) == 0;
     				}
     
     				g_object_unref(drive);
    
  • src/pad.c+52 20 modified
    @@ -43,7 +43,7 @@ static int pusb_pad_build_device_path(
     	struct stat sb;
     
     	snprintf(path_devpad, sizeof(path_devpad), "%s/%s", mnt_point, opts->device_pad_directory);
    -	if (stat(path_devpad, &sb) != 0)
    +	if (lstat(path_devpad, &sb) != 0)
     	{
     		log_debug("Directory %s does not exist, creating it.\n", path_devpad);
     		if (mkdir(path_devpad, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
    @@ -52,6 +52,11 @@ static int pusb_pad_build_device_path(
     			return 0;
     		}
     	}
    +	else if (S_ISLNK(sb.st_mode))
    +	{
    +		log_error("Device pad directory %s is a symlink, refusing to use it.\n", path_devpad);
    +		return 0;
    +	}
     
     	snprintf(
     		path_out,
    @@ -91,7 +96,7 @@ static int pusb_pad_build_system_path(
     		user_ent->pw_dir,
     		opts->system_pad_directory
     	);
    -	if (stat(dir_path, &sb) != 0)
    +	if (lstat(dir_path, &sb) != 0)
     	{
     		log_debug("Directory %s does not exist, creating one.\n", dir_path);
     		if (mkdir(dir_path, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
    @@ -107,6 +112,11 @@ static int pusb_pad_build_system_path(
     
     		chmod(dir_path, S_IRUSR | S_IWUSR | S_IXUSR);
     	}
    +	else if (S_ISLNK(sb.st_mode))
    +	{
    +		log_error("System pad directory %s is a symlink, refusing to use it.\n", dir_path);
    +		return 0;
    +	}
     	/* change slashes in device name to underscores */
     	snprintf(device_name, sizeof(device_name), "%s", opts->device.name);
     	while (*device_name_ptr)
    @@ -137,19 +147,26 @@ static FILE *pusb_pad_open_device(
     	const char *mode
     )
     {
    -	FILE *f;
     	char path[1024*5];
    +	int flags = (mode[0] == 'r') ? O_RDONLY : (O_WRONLY | O_CREAT | O_TRUNC);
     
     	if (!pusb_pad_build_device_path(opts, mnt_point, user, path, sizeof(path)))
     	{
     		return NULL;
     	}
    -	f = fopen(path, mode);
    -	if (!f)
    +	int fd = open(path, flags | O_NOFOLLOW, 0600);
    +	if (fd < 0)
     	{
     		log_debug("Cannot open device file: %s\n", strerror(errno));
     		return NULL;
     	}
    +	FILE *f = fdopen(fd, mode);
    +	if (!f)
    +	{
    +		close(fd);
    +		log_debug("Cannot fdopen device file: %s\n", strerror(errno));
    +		return NULL;
    +	}
     	return f;
     }
     
    @@ -159,19 +176,26 @@ static FILE *pusb_pad_open_system(
     	const char *mode
     )
     {
    -	FILE *f;
     	char path[1024*5];
    +	int flags = (mode[0] == 'r') ? O_RDONLY : (O_WRONLY | O_CREAT | O_TRUNC);
     
     	if (!pusb_pad_build_system_path(opts, user, path, sizeof(path)))
     	{
     		return NULL;
     	}
    -	f = fopen(path, mode);
    -	if (!f)
    +	int fd = open(path, flags | O_NOFOLLOW, 0600);
    +	if (fd < 0)
     	{
     		log_debug("Cannot open system file: %s\n", strerror(errno));
     		return NULL;
     	}
    +	FILE *f = fdopen(fd, mode);
    +	if (!f)
    +	{
    +		close(fd);
    +		log_debug("Cannot fdopen system file: %s\n", strerror(errno));
    +		return NULL;
    +	}
     	return f;
     }
     
    @@ -295,19 +319,27 @@ static int pusb_pad_update(
     
     	generateRandom(magic, sizeof(magic));
     
    -	if (!(f_device = fopen(path_device_tmp, "w")))
     	{
    -		log_error("Unable to create temp device pad: %s\n", strerror(errno));
    -		return 0;
    +		int fd_dev = open(path_device_tmp, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600);
    +		if (fd_dev < 0 || !(f_device = fdopen(fd_dev, "w")))
    +		{
    +			if (fd_dev >= 0) close(fd_dev);
    +			log_error("Unable to create temp device pad: %s\n", strerror(errno));
    +			return 0;
    +		}
     	}
     	pusb_pad_protect(user, fileno(f_device));
     
    -	if (!(f_system = fopen(path_system_tmp, "w")))
     	{
    -		log_error("Unable to create temp system pad: %s\n", strerror(errno));
    -		fclose(f_device);
    -		unlink(path_device_tmp);
    -		return 0;
    +		int fd_sys = open(path_system_tmp, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600);
    +		if (fd_sys < 0 || !(f_system = fdopen(fd_sys, "w")))
    +		{
    +			if (fd_sys >= 0) close(fd_sys);
    +			log_error("Unable to create temp system pad: %s\n", strerror(errno));
    +			fclose(f_device);
    +			unlink(path_device_tmp);
    +			return 0;
    +		}
     	}
     	pusb_pad_protect(user, fileno(f_system));
     
    @@ -403,19 +435,19 @@ static int pusb_pad_compare(
     	}
     	log_debug("Loading device pad...\n");
     	bytes_read = fread(magic_device, sizeof(char), sizeof(magic_device), f_device);
    -	if (!bytes_read)
    +	if (bytes_read != sizeof(magic_device))
     	{
    -		log_error("Can't read device pad!\n");
    +		log_error("Device pad is incomplete (%zu/%zu bytes).\n", bytes_read, sizeof(magic_device));
     		fclose(f_system);
     		fclose(f_device);
     		return 0;
     	}
     
     	log_debug("Loading system pad...\n");
     	bytes_read = fread(magic_system, sizeof(char), sizeof(magic_system), f_system);
    -	if (!bytes_read)
    +	if (bytes_read != sizeof(magic_system))
     	{
    -		log_error("Can't read system pad!\n");
    +		log_error("System pad is incomplete (%zu/%zu bytes).\n", bytes_read, sizeof(magic_system));
     		fclose(f_system);
     		fclose(f_device);
     		return 0;
    
  • src/tmux.c+63 5 modified
    @@ -18,11 +18,52 @@
     #include <stdio.h>
     #include <string.h>
     #include <stdlib.h>
    +#include <ctype.h>
     #include <regex.h>
     #include "log.h"
     #include "process.h"
     #include "mem.h"
     
    +/* Reject characters that could break out of shell double-quotes or inject commands. */
    +static int pusb_tmux_is_safe_socket_path(const char *path)
    +{
    +    if (!path || *path == '\0') return 0;
    +    for (const char *p = path; *p; p++) {
    +        switch (*p) {
    +            case '"': case '\'': case '`': case '$': case '\\':
    +            case '\n': case '\r': case '\t': case '!': case ';':
    +            case '&': case '|': case '<': case '>': case '(':
    +            case ')': case '{': case '}':
    +                return 0;
    +        }
    +    }
    +    return 1;
    +}
    +
    +/* Client ID from TMUX must be purely numeric. */
    +static int pusb_tmux_is_numeric_id(const char *s)
    +{
    +    if (!s || *s == '\0') return 0;
    +    for (; *s; s++) {
    +        if (!isdigit((unsigned char)*s)) return 0;
    +    }
    +    return 1;
    +}
    +
    +/* Escape ERE metacharacters in username so it matches literally in the regex. */
    +static void pusb_tmux_escape_for_regex(const char *src, char *dst, size_t dstlen)
    +{
    +    const char *metachar = "\\.^$*+?{}[]|()";
    +    size_t j = 0;
    +    for (size_t i = 0; src[i] && j + 2 < dstlen; i++) {
    +        if (strchr(metachar, (int)src[i])) {
    +            dst[j++] = '\\';
    +        }
    +        dst[j++] = src[i];
    +    }
    +    dst[j] = '\0';
    +}
    +
     char *pusb_tmux_get_client_tty(pid_t env_pid)
     {
         char *tmux_details = getenv("TMUX");
    @@ -49,6 +90,18 @@ char *pusb_tmux_get_client_tty(pid_t env_pid)
         char *tmux_socket_path = strtok(tmux_details, ",");
         log_debug("		Got tmux_socket_path: %s\n", tmux_socket_path);
     
    +    if (!pusb_tmux_is_safe_socket_path(tmux_socket_path))
    +    {
    +        log_error("TMUX socket path contains invalid characters, denying.\n");
    +        return NULL;
    +    }
    +
    +    if (!pusb_tmux_is_numeric_id(tmux_client_id))
    +    {
    +        log_error("TMUX client ID is not numeric, denying.\n");
    +        return NULL;
    +    }
    +
         size_t get_tmux_session_details_cmd_len = strlen(tmux_socket_path) + strlen(tmux_client_id) + 64;
         char *get_tmux_session_details_cmd = xmalloc(get_tmux_session_details_cmd_len);
         snprintf(get_tmux_session_details_cmd, get_tmux_session_details_cmd_len, "LC_ALL=C; tmux -S \"%s\" list-clients -t \"\\$%s\"", tmux_socket_path, tmux_client_id);
    @@ -82,8 +135,9 @@ char *pusb_tmux_get_client_tty(pid_t env_pid)
                 log_debug("		Closing pipe for 'tmux list-clients' failed, this is quite a wtf...\n");
             }
     
    -        char *result = xmalloc(strlen(tmux_client_tty) + 1);
    -        strcpy(result, tmux_client_tty);
    +        size_t tty_len = strlen(tmux_client_tty);
    +        char *result = xmalloc(tty_len + 1);
    +        memcpy(result, tmux_client_tty, tty_len + 1);
             return result;
         }
         else
    @@ -107,24 +161,28 @@ int pusb_tmux_has_remote_clients(const char* username)
         char regex_raw[BUFSIZ];
         char buf[BUFSIZ];
         char msgbuf[100];
    -    char regex_tpl[2][BUFSIZ] = {
    +    const char *regex_tpl[2] = {
             "(.+)([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})(.+)tmux(.+)", //v4
             "(.+)([0-9A-Fa-f]{1,4}):([0-9A-Fa-f]{1,4}):([0-9A-Fa-f]{1,4}):([0-9A-Fa-f]{1,4})(.+)tmux(.+)" // v6
         }; // ... yes, these allow invalid addresses. No, I don't care. This isn't about validation but detecting remote access. Good enough ¯\_(ツ)_/¯
     
    +    /* Max Linux username is 32 chars; doubled for escaping + null terminator = 65 bytes. */
    +    char escaped_username[65] = {0};
    +    pusb_tmux_escape_for_regex(username, escaped_username, sizeof(escaped_username));
    +
         for (int i = 0; i <= 1; i++)
         {
             log_debug("		Checking for IPv%d connections...\n", (4 + (i * 2)));
     
    -        if ((fp = popen("LC_ALL=C; w", "r")) == NULL)
    +        if ((fp = popen("LC_ALL=C; /usr/bin/w", "r")) == NULL)
             {
                 log_error("tmux detected, but couldn't get `w`. Denying since remote check for tmux impossible without it!\n");
                 return -1;
             }
     
             while (fgets(buf, BUFSIZ, fp) != NULL)
             {
    -            snprintf(regex_raw, BUFSIZ, "%s%s", username, regex_tpl[i]);
    +            snprintf(regex_raw, BUFSIZ, "%s%s", escaped_username, regex_tpl[i]);
     
                 status = regcomp(&regex, regex_raw, REG_EXTENDED);
                 if (status)
    
  • tools/pamusb-agent+14 4 modified
    @@ -194,13 +194,22 @@ def userDeviceThread(user):
     			else:
     				logger.error('Ignoring empty command for user "%s".' % userName)
     
    +		_DANGEROUS_ENV_VARS = {
    +			'LD_PRELOAD', 'LD_LIBRARY_PATH', 'LD_AUDIT', 'LD_DEBUG',
    +			'GLIBC_TUNABLES', 'PYTHONPATH', 'PERL5LIB', 'RUBYLIB',
    +			'IFS', 'CDPATH', 'ENV', 'BASH_ENV',
    +		}
    +
     		for henv in hotplug.findall('env'):
     			if henv.text is not None:
     				henv_var = re.sub(r'^(.*?)=.*$', '\\1', henv.text)
     				henv_arg = re.sub(r'^.*?=(.*)$', '\\1', henv.text)
     
     				if henv_var != '' and henv_arg != '':
    -					henvs[henv_var] = henv_arg
    +					if henv_var in _DANGEROUS_ENV_VARS:
    +						logger.error('Rejecting dangerous env var "%s" for user "%s".' % (henv_var, userName))
    +					else:
    +						henvs[henv_var] = henv_arg
     				else:
     					logger.error('Ignoring invalid command environment variable for user "%s".' % userName)
     			else:
    @@ -269,9 +278,10 @@ def userDeviceThread(user):
     
     		logger.info('Device "%s" has been inserted. Performing verification...' % deviceName)
     
    -		cmdLine = "%s --debug --config=%s --service=pamusb-agent %s" % (options['check'], options['configFile'], userName)
    -		logger.info('Executing "%s"' % cmdLine)
    -		if not os.system(cmdLine):
    +		checkArgs = [options['check'], '--debug', '--config=' + options['configFile'], '--service=pamusb-agent', userName]
    +		logger.info('Executing "%s"' % ' '.join(checkArgs))
    +		checkResult = subprocess.run(checkArgs, capture_output=True)
    +		if checkResult.returncode == 0:
     			logger.info('Authentication succeeded. Unlocking user "%s"...' % userName)
     
     			for l in events['unlock']:
    
  • tools/pamusb-conf+11 1 modified
    @@ -17,6 +17,7 @@
     
     import sys
     import os
    +import re
     import gi
     import subprocess
     import socket
    @@ -352,14 +353,23 @@ def resetPads():
     			if user.getAttribute('id') == options['resetPads']:
     				# Device specific pad for user
     				userDevice = user.getElementsByTagName('device')[0].firstChild.nodeValue
    +				if '/' in userDevice or '..' in userDevice:
    +					print('Invalid device ID in config (path traversal): %s' % userDevice)
    +					sys.exit(1)
     				padFiles.append('/home/%s/.pamusb/%s.pad' % (options['resetPads'], userDevice))
     
     				# User specific pad for device
     				for details in devicesObj:
     					if details.getAttribute('id') == userDevice:
     						deviceUUID = details.getElementsByTagName('volume_uuid')[0].firstChild.nodeValue
    +						if not re.match(r'^[0-9a-fA-F\-]+$', deviceUUID):
    +							print('Invalid device UUID in config: %s' % deviceUUID)
    +							sys.exit(1)
     						try:
    -							deviceMountPoint = subprocess.check_output(['mount | grep `readlink -f /dev/disk/by-uuid/%s` | awk \'{print $3}\'' % (deviceUUID)], shell=True)
    +							deviceMountPoint = subprocess.check_output(
    +								['findmnt', '-n', '-o', 'TARGET', '--source', '/dev/disk/by-uuid/' + deviceUUID],
    +								stderr=subprocess.DEVNULL
    +							)
     							padFiles.append('%s/.pamusb/%s.%s.pad' % (deviceMountPoint.decode().strip(), options['resetPads'], socket.gethostname()))
     						except subprocess.CalledProcessError as err:
     							print('Could not get device mountpoint: ', err)
    
  • tools/pamusb-keyring-unlock-gnome+8 4 modified
    @@ -39,11 +39,15 @@ else
         logger -p local0.notice -t ${0##*/}[$$] Killed existing gnome-keyring-instance.
     fi
     
    -# Read UNLOCK_PASSWORD from $KEYFILE
    -. ~/.pamusb/.keyring_unlock_password
    +# Read UNLOCK_PASSWORD from $KEYFILE via grep to avoid sourcing arbitrary shell
    +UNLOCK_PASSWORD=$(grep -oP '^UNLOCK_PASSWORD=\K.*' ~/.pamusb/.keyring_unlock_password)
    +if [ -z "$UNLOCK_PASSWORD" ]; then
    +    logger -p local0.error -t ${0##*/}[$$] Could not read UNLOCK_PASSWORD from file.
    +    exit 1
    +fi
     
    -# Perform unlock
    -echo -n $UNLOCK_PASSWORD | gnome-keyring-daemon --daemonize --login \
    +# Perform unlock — pass via stdin pipe so the password never appears as a process argument
    +printf '%s' "$UNLOCK_PASSWORD" | gnome-keyring-daemon --daemonize --login \
         && gnome-keyring-daemon --start  > /dev/null 2>&1; UNLOCKED=$? \
         && logger -p local0.notice -t ${0##*/}[$$] Keyring unlocked. \
         || logger -p local0.error -t ${0##*/}[$$] Keyring unlock failed.
    
  • tools/pamusb-pinentry+6 1 modified
    @@ -16,6 +16,7 @@
     # Street, Fifth Floor, Boston, MA 02110-1301 USA.
     
     import os
    +import sys
     import subprocess
     import getpass
     from dotenv import load_dotenv
    @@ -35,4 +36,8 @@ if (isAuthenticated.returncode == 0):
                 exit()
             print("OK")
     else:
    -    subprocess.run(fallbackPinentryApp)
    +    if fallbackPinentryApp and os.path.isabs(fallbackPinentryApp) and os.path.isfile(fallbackPinentryApp) and os.access(fallbackPinentryApp, os.X_OK):
    +        subprocess.run([fallbackPinentryApp])
    +    else:
    +        sys.stderr.write('PINENTRY_FALLBACK_APP is not set or not a valid executable path, cannot fall back.\n')
    +        sys.exit(1)
    
9bce707cbb0c

#223: Enable forcing a specific device for sudo (#289)

https://github.com/mcdope/pam_usbMcDopeMay 5, 2026Fixed in 0.8.7via llm-release-walk
5 files changed · +625 256
  • doc/CONFIGURATION+383 255 modified
    @@ -1,255 +1,383 @@
    -Configuration file reference
    -============================
    -
    -The configuration file is formatted in XML and subdivided in 4 sections:
    -
    -* Default options, shared among every device, user and service
    -* Devices declaration and settings
    -* Users declaration and settings
    -* Services declaration and settings
    -
    -Note that for changes to the agent / events config you need to restart the agent service for them to take effect. Other changes are picked up on next pam_usb usage.
    -
    -The syntax is the following:
    -
    -```xml
    -<configuration>
    -    <defaults>
    -        <!-- default options -->
    -    </defaults>
    -
    -    <devices>
    -        <!-- devices definitions -->
    -    </devices>
    -
    -    <users>
    -        <!-- users definitions -->
    -    </users>
    -
    -    <services>
    -        <!-- services definitions -->
    -    </services>
    -</configuration>
    -```
    -
    -----------
    -
    -## Options
    -
    -|          Name          |  Type   |       Default       |                         Description                              |
    -|------------------------|---------|---------------------|------------------------------------------------------------------|
    -| `enable`               | Boolean | `true`              | Enable pam_usb                                                   |
    -| `debug`                | Boolean | `false`             | Enable debug messages                                            |
    -| `quiet`                | Boolean | `false`             | Quiet mode                                                       |
    -| `color_log`            | Boolean | `true`              | Enable colored output                                            |
    -| `one_time_pad`         | Boolean | `true`              | Enable the use of one time device-associated pad files           |
    -| `deny_remote`          | Boolean | `true`              | Deny access from remote host (SSH)                               |
    -| `probe_timeout`        | Time    | `10s`               | Time to wait for the volume to be detected                       |
    -| `pad_expiration`       | Time    | `1h`                | Time between pad file regeneration                               |
    -| `hostname`             | String  | Computer's hostname | Must be unique accross computers using the same device           |
    -| `system_pad_directory` | String  | `.pamusb`           | Relative path to the user's home used to store one time pads     |
    -| `device_pad_directory` | String  | `.pamusb`           | Relative path to the device used to store one time pad files     |
    -
    -### Example:
    -
    -```xml
    -<configuration>
    -    <defaults>
    -        <!-- Disable colored output by default -->
    -        <option name="color_log">false</option>
    -        <!-- Enable debug output -->
    -        <option name="debug">true</option>
    -    </defaults>
    -
    -    <users>
    -        <user id="root">
    -            <!-- Enable colored output for user "root" -->
    -            <option name="color_log">true</option>
    -        </user>
    -
    -        <user id="scox">
    -             <!-- Disable debug output for user "scox" -->
    -             <option name="debug">false</option>
    -        </user>
    -    </users>
    -
    -    <devices>
    -        <device id="mydevice">
    -            <!-- Wait 15 seconds instead of the default 10 seconds for "mydevice" to be detected -->
    -            <option name="probe_timeout">15</option>
    -        </device>
    -    </devices>
    -
    -    <services>
    -        <service id="su">
    -            <!-- Disable pam_usb for "su" ("su" will ask for a password as usual) -->
    -            <option name="enable">false<option>
    -       </service>
    -    </services>
    -</configuration>
    -```
    -
    -----------
    -
    -## Devices
    -
    -
    -|     Name      |   Type    |                  Description                   |        Example         |
    -|---------------|-----------|------------------------------------------------|------------------------|
    -| `id`          | Attribute | Arbitrary device name                          | `MyDevice`             |
    -| `vendor`      | Element   | Device's vendor name                           | `SanDisk Corp.`        |
    -| `model`       | Element   | Device's model name                            | `Cruzer Titanium`      |
    -| `serial`      | Element   | Serial number of the device                    | `SNDKXXXXXXXXXXXXXXXX` |
    -| `volume_uuid` | Element   | UUID of the device's volume used to store pads | `6F6B-42FC`            |
    -
    -### Note:
    -Some cheap devices don't report a vendor and/or model. To use these devices you can use "Generic" for these values, then it won't be checked.
    -Be aware that this reduces security if you have `one_time_pads` disabled since the device containing the volume won't be checked anymore (but these attributes could be faked with a custom firmware anyway).
    -
    -### Example:
    -
    -```xml
    -<device id="MyDevice">
    -    <vendor>SanDisk Corp.</vendor>
    -    <model>Cruzer Titanium</model>
    -    <serial>SNDKXXXXXXXXXXXXXXXX</serial>
    -    <volume_uuid>6F6B-42FC</volume_uuid>
    -</device>
    -```
    -
    -----------
    -
    -## Users
    -
    -|   Name   |   Type    |                Description                |  Example   |
    -|----------|-----------|-------------------------------------------|------------|
    -| `id`     | Attribute | Login of the user                         | `root`     |
    -| `device` | Element   | `id` of the device associated to the user | `MyDevice` |
    -| `agent`  | Element   | Agent commands, for use with pamusb-agent |            |
    -
    -Note that one `<user>` can have multiple `<device>` (from v0.8.5 up).
    -
    -### Agent
    -
    -The agent is to be run as system service. If you installed by using the debian package it will automatically be configured as
    -systemd service unit. In case you use another init / service management you will need to set it up yourself before any event
    -configuration will take effect.
    -
    -
    -| Name  |   Type    |                                             Description                                                         |
    -|-------|-----------|-----------------------------------------------------------------------------------------------------------------|
    -| `env` | Attribute | Environment variable for the command. For multiple environment variables use multiple `env` tags.               |
    -| `cmd` | Attribute | Agent command, associated with `env` tags in the same agent element. Multiple/chained `cmd` elements supported. |
    -
    -### Example:
    -
    -```xml
    -<user id="scox">
    -    <device>MyDevice</device>
    -
    -    <!-- When the user "scox" removes the usb device, lock the screen and pause beep-media-player -->
    -    <agent event="lock">
    -        <env>DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus</env>
    -        <env>HOME=/home/scox</env>
    -        <cmd>gnome-screensaver-command --lock</cmd>
    -        <cmd>sleep 5</cmd>
    -        <cmd>pkill -SIGSTOP -u 1000</cmd>
    -    </agent>
    -    <agent event="lock">
    -        <cmd>beep-media-player --pause</cmd>
    -    </agent>
    -
    -    <!-- Resume operations when the usb device is plugged back and authenticated -->
    -    <agent event="unlock">
    -        <env>DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus</env>
    -        <env>HOME=/home/scox</env>
    -        <cmd>pkill -SIGCONT -u 1000</cmd>
    -        <cmd>sleep 5</cmd>
    -        <cmd>gnome-screensaver-command --deactivate</cmd>
    -    </agent>
    -    <agent event="unlock">
    -        <cmd>beep-media-player --play</cmd>
    -    </agent>
    -</user>
    -```
    -
    -For systemd based distributions you can use `loginctl lock-session` as lock `<cmd>`, to unlock you can use `loginctl unlock-session`.
    -
    -----------
    -
    -## Services
    -
    -| Name |   Type    |     Description     | Example |
    -|------|-----------|---------------------|---------|
    -| `id` | Attribute | Name of the service | `su`    |
    -
    -### Example:
    -
    -```xml
    -<service id="su">
    -    <!--
    -       Here you can put service specific options such as "enable", "debug" etc.
    -       See the options section of this document.
    -    -->
    -</service>
    -```
    -
    -----------
    -
    -Location of the configuration file
    -----------------------------------
    -
    -By default, `pam_usb.so` and its tools will look for the configuration file at `/etc/security/pam_usb.conf`.
    -
    -If you want to use a different location, you will have to use the `-c` flag.
    -
    -```
    -# /etc/pam.d/system-auth
    -auth    sufficient      pam_usb.so -c /some/other/path.conf
    -auth    required        pam_unix.so nullok_secure
    -```
    -
    -You will also have to use the `-c` option when calling pam_usb's tools.
    -
    -```
    -pamusb-agent -c /some/other/path.conf
    -```
    -
    -Example configuration
    -----------------------------------
    -
    -1. Insert a removable block device
    -
    -2. Add necessary device configuration into `/etc/security/pam_usb.conf` by running:
    -
    -```
    -sudo pamusb-conf --add-device=<devicename>
    -```
    -
    -where `<devicename>` is a recognizable name for your device. This value is used internally in the configuration file as device `id` value and in output shown to users. (Note: because of it being used as an XML attribute value, it shouldn't contain ampersands etc.)
    -
    -You can do this for multiple devices obviously.
    -
    -3. Add necessary user configuration into `/etc/security/pam_usb.conf` by running:
    -
    -```
    -sudo pamusb-conf --add-user=<username>
    -```
    -
    -where `<username>` is a valid Unix user name. 
    -
    -If you added multiple devices you can repeat this command to choose an additional device for this user (from v0.8.5 up).
    -
    -4. Tweak `/etc/security/pam_usb.conf` manually as desired. Link devices and users, etc.
    -
    -If you use one time pads (default), you need to do the following:
    -
    -5. Run `/usr/bin/pamusb-check --debug <username>`
    -
    -where `<username>` is associated with the removable block device.
    -
    -By default, this command creates directory `$HOME/.pamusb/` with a protected device-associated `.pad` file. If you format the device, you must
    -delete the `$HOME/.pamusb/<devicename>.pad` file (or run `pamusb-conf --reset-pads=username`). The created `.pad` file can't be used with a new partition UUIDs for the same or any removable block device.
    -
    -6. Add proper PAM configuration into `/etc/pam.d/common-auth` as described in [Getting Started](https://github.com/mcdope/pam_usb/wiki/Getting-Started#setting-up-the-pam-module). For testing purposes, it's highly recommended to start with `sufficient` PAM option before possibly moving to `required` or `requisite` option since you can bypass faulty `pam_usb` configurations.
    -7. Test the device/user configuration by running `/usr/bin/pamusb-check <username>`. The removable block device must be attached (mount not required) and the user must have proper configuration in `/etc/security/pam_usb.conf` file.
    +  Configuration file reference                                                                                                                                                                                                                                                                                                                                                     
    +  ============================                                                                                                                                                                                                                                                                                                                                                     
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  The configuration file is formatted in XML and subdivided in 4 sections:                                                                                                                                                                                                                                                                                                         
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  * Default options, shared among every device, user and service                                                                                                                                                                                                                                                                                                                   
    +  * Devices declaration and settings                                                                                                                                                                                                                                                                                                                                               
    +  * Users declaration and settings                                                                                                                                                                                                                                                                                                                                                 
    +  * Services declaration and settings                                                                                                                                                                                                                                                                                                                                              
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  Note that for changes to the agent / events config you need to restart the agent service for them to take effect. Other changes are picked up on next pam_usb usage.                                                                                                                                                                                                             
    +   
    +  The syntax is the following:                                                                                                                                                                                                                                                                                                                                                     
    +                                                            
    +  ```xml
    +  <configuration>                                                                                                                                                                                                                                                                                                                                                                  
    +      <defaults>
    +          <!-- default options -->                                                                                                                                                                                                                                                                                                                                                 
    +      </defaults>                                           
    +
    +      <devices>
    +          <!-- devices definitions -->
    +      </devices>                                                                                                                                                                                                                                                                                                                                                                   
    +   
    +      <users>                                                                                                                                                                                                                                                                                                                                                                      
    +          <!-- users definitions -->                        
    +      </users>
    +
    +      <services>
    +          <!-- services definitions -->
    +      </services>
    +  </configuration>
    +  ```
    +
    +  ----------
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ## Options
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  |          Name          |  Type   |       Default       |                         Description                              |
    +  |------------------------|---------|---------------------|------------------------------------------------------------------|
    +  | `enable`               | Boolean | `true`              | Enable pam_usb                                                   |
    +  | `debug`                | Boolean | `false`             | Enable debug messages                                            |                                                                                                                                                                                                                                                    
    +  | `quiet`                | Boolean | `false`             | Quiet mode                                                       |
    +  | `color_log`            | Boolean | `true`              | Enable colored output                                            |                                                                                                                                                                                                                                                    
    +  | `one_time_pad`         | Boolean | `true`              | Enable the use of one time device-associated pad files           |                                                                                                                                                                                                                                                    
    +  | `deny_remote`          | Boolean | `true`              | Deny access from remote host (SSH)                               |                                                                                                                                                                                                                                                    
    +  | `superuser`            | Boolean | `false`             | Require a superuser-capable device for this service. Only meaningful on `<service>`. (v0.8.7+) |                                                                                                                                                                                                                      
    +  | `probe_timeout`        | Time    | `10s`               | Time to wait for the volume to be detected                       |                                                                                                                                                                                                                                                    
    +  | `pad_expiration`       | Time    | `1h`                | Time between pad file regeneration                               |                                                                                                                                                                                                                                                    
    +  | `hostname`             | String  | Computer's hostname | Must be unique accross computers using the same device           |                                                                                                                                                                                                                                                    
    +  | `system_pad_directory` | String  | `.pamusb`           | Relative path to the user's home used to store one time pads     |                                                                                                                                                                                                                                                    
    +  | `device_pad_directory` | String  | `.pamusb`           | Relative path to the device used to store one time pad files     |                                                                                                                                                                                                                                                    
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ### Example:                                                                                                                                                                                                                                                                                                                                                                     
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ```xml                                                                                                                                                                                                                                                                                                                                                                           
    +  <configuration>                                           
    +      <defaults>
    +          <!-- Disable colored output by default -->
    +          <option name="color_log">false</option>
    +          <!-- Enable debug output -->                                                                                                                                                                                                                                                                                                                                             
    +          <option name="debug">true</option>
    +      </defaults>                                                                                                                                                                                                                                                                                                                                                                  
    +                                                            
    +      <users>
    +          <user id="root">                                                                                                                                                                                                                                                                                                                                                         
    +              <!-- Enable colored output for user "root" -->
    +              <option name="color_log">true</option>                                                                                                                                                                                                                                                                                                                               
    +          </user>                                           
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +          <user id="scox">                                  
    +               <!-- Disable debug output for user "scox" -->
    +               <option name="debug">false</option>                                                                                                                                                                                                                                                                                                                                 
    +          </user>
    +      </users>                                                                                                                                                                                                                                                                                                                                                                     
    +                                                            
    +      <devices>
    +          <device id="mydevice">
    +              <!-- Wait 15 seconds instead of the default 10 seconds for "mydevice" to be detected -->                                                                                                                                                                                                                                                                             
    +              <option name="probe_timeout">15</option>                                                                                                                                                                                                                                                                                                                             
    +          </device>                                                                                                                                                                                                                                                                                                                                                                
    +      </devices>                                                                                                                                                                                                                                                                                                                                                                   
    +                                                            
    +      <services>
    +          <service id="su">
    +              <!-- Disable pam_usb for "su" ("su" will ask for a password as usual) -->
    +              <option name="enable">false<option>                                                                                                                                                                                                                                                                                                                                  
    +         </service>
    +      </services>                                                                                                                                                                                                                                                                                                                                                                  
    +  </configuration>                                          
    +  ```
    +
    +  ----------
    +
    +  ## Devices                                                                                                                                                                                                                                                                                                                                                                       
    +   
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  |     Name      |   Type    |                  Description                   |        Example         |
    +  |---------------|-----------|------------------------------------------------|------------------------|                                                                                                                                                                                                                                                                          
    +  | `id`          | Attribute | Arbitrary device name                          | `MyDevice`             |
    +  | `vendor`      | Element   | Device's vendor name                           | `SanDisk Corp.`        |                                                                                                                                                                                                                                                                          
    +  | `model`       | Element   | Device's model name                            | `Cruzer Titanium`      |                                                                                                                                                                                                                                                                          
    +  | `serial`      | Element   | Serial number of the device                    | `SNDKXXXXXXXXXXXXXXXX` |                                                                                                                                                                                                                                                                          
    +  | `volume_uuid` | Element   | UUID of the device's volume used to store pads | `6F6B-42FC`            |                                                                                                                                                                                                                                                                          
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ### Note:                                                                                                                                                                                                                                                                                                                                                                        
    +  Some cheap devices don't report a vendor and/or model. To use these devices you can use "Generic" for these values, then it won't be checked.                                                                                                                                                                                                                                    
    +  Be aware that this reduces security if you have `one_time_pads` disabled since the device containing the volume won't be checked anymore (but these attributes could be faked with a custom firmware anyway).                                                                                                                                                                    
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ### Example:                                                                                                                                                                                                                                                                                                                                                                     
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ```xml                                                    
    +  <device id="MyDevice">
    +      <vendor>SanDisk Corp.</vendor>
    +      <model>Cruzer Titanium</model>                                                                                                                                                                                                                                                                                                                                               
    +      <serial>SNDKXXXXXXXXXXXXXXXX</serial>
    +      <volume_uuid>6F6B-42FC</volume_uuid>                                                                                                                                                                                                                                                                                                                                         
    +  </device>                                                                                                                                                                                                                                                                                                                                                                        
    +  ```
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ----------                                                
    +
    +  ## Users
    +
    +  |   Name   |   Type    |                Description                |  Example   |
    +  |----------|-----------|-------------------------------------------|------------|
    +  | `id`     | Attribute | Login of the user                         | `root`     |                                                                                                                                                                                                                                                                                                
    +  | `device` | Element   | `id` of the device associated to the user | `MyDevice` |
    +  | `agent`  | Element   | Agent commands, for use with pamusb-agent |            |                                                                                                                                                                                                                                                                                                
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  Note that one `<user>` can have multiple `<device>` (from v0.8.5 up).
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  The `<device>` element accepts an optional `superuser="true"` attribute to mark that device as eligible for superuser services such as `sudo`, `su`, and `polkit-1`. Devices without this attribute are excluded when the service requires a superuser device. See [Superuser device restriction](#superuser-device-restriction) (v0.8.7+).                                      
    +   
    +  ### Agent                                                                                                                                                                                                                                                                                                                                                                        
    +                                                            
    +  The agent is to be run as system service. If you installed by using the debian package it will automatically be configured as                                                                                                                                                                                                                                                    
    +  systemd service unit. In case you use another init / service management you will need to set it up yourself before any event
    +  configuration will take effect.                                                                                                                                                                                                                                                                                                                                                  
    +                                                            
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  | Name  |   Type    |                                             Description                                                         |
    +  |-------|-----------|-----------------------------------------------------------------------------------------------------------------|                                                                                                                                                                                                                                          
    +  | `env` | Attribute | Environment variable for the command. For multiple environment variables use multiple `env` tags.               |
    +  | `cmd` | Attribute | Agent command, associated with `env` tags in the same agent element. Multiple/chained `cmd` elements supported. |                                                                                                                                                                                                                                          
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ### Example:                                                                                                                                                                                                                                                                                                                                                                     
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  ```xml                                                    
    +  <user id="scox">
    +      <device>MyDevice</device>
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +      <!-- When the user "scox" removes the usb device, lock the screen and pause beep-media-player -->
    +      <agent event="lock">                                                                                                                                                                                                                                                                                                                                                         
    +          <env>DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus</env>
    +          <env>HOME=/home/scox</env>                                                                                                                                                                                                                                                                                                                                               
    +          <cmd>gnome-screensaver-command --lock</cmd>       
    +          <cmd>sleep 5</cmd>                                                                                                                                                                                                                                                                                                                                                       
    +          <cmd>pkill -SIGSTOP -u 1000</cmd>                 
    +      </agent>                                                                                                                                                                                                                                                                                                                                                                     
    +      <agent event="lock">                                  
    +          <cmd>beep-media-player --pause</cmd>                                                                                                                                                                                                                                                                                                                                     
    +      </agent>                                              
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +      <!-- Resume operations when the usb device is plugged back and authenticated -->
    +      <agent event="unlock">                                                                                                                                                                                                                                                                                                                                                       
    +          <env>DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus</env>
    +          <env>HOME=/home/scox</env>                                                                                                                                                                                                                                                                                                                                               
    +          <cmd>pkill -SIGCONT -u 1000</cmd>                 
    +          <cmd>sleep 5</cmd>                                                                                                                                                                                                                                                                                                                                                       
    +          <cmd>gnome-screensaver-command --deactivate</cmd>                                                                                                                                                                                                                                                                                                                        
    +      </agent>
    +      <agent event="unlock">                                                                                                                                                                                                                                                                                                                                                       
    +          <cmd>beep-media-player --play</cmd>               
    +      </agent>                                                                                                                                                                                                                                                                                                                                                                     
    +  </user>
    +  ```                                                                                                                                                                                                                                                                                                                                                                              
    +                                                            
    +  For systemd based distributions you can use `loginctl lock-session` as lock `<cmd>`, to unlock you can use `loginctl unlock-session`.                                                                                                                                                                                                                                            
    +   
    +  ----------                                                                                                                                                                                                                                                                                                                                                                       
    +                                                            
    +  ## Services
    +
    +  | Name |   Type    |     Description     | Example |
    +  |------|-----------|---------------------|---------|
    +  | `id` | Attribute | Name of the service | `su`    |                                                                                                                                                                                                                                                                                                                             
    +   
    +  Services can use all options from the [Options](#options) section. The `superuser` option (v0.8.7+) is only meaningful here — setting it on a service requires users to authenticate with a device marked `superuser="true"`. See [Superuser device restriction](#superuser-device-restriction).                                                                                 
    +                                                            
    +  ### Example:                                                                                                                                                                                                                                                                                                                                                                     
    +                                                            
    +  ```xml
    +  <service id="su">
    +      <!--
    +         Here you can put service specific options such as "enable", "debug" etc.
    +         See the options section of this document.                                                                                                                                                                                                                                                                                                                                 
    +      -->                                                                                                                                                                                                                                                                                                                                                                          
    +  </service>                                                                                                                                                                                                                                                                                                                                                                       
    +  ```                                                                                                                                                                                                                                                                                                                                                                              
    +                                                            
    +  ----------
    +
    +  ## Superuser device restriction
    +
    +  *Available from v0.8.7.*                                                                                                                                                                                                                                                                                                                                                         
    +   
    +  This feature lets you designate specific USB devices as **superuser-capable** — valid for privilege-escalation services such as `sudo`, `su`, and `polkit-1` — while other registered devices for the same user 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. a 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 its `<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 `superuser=true`, any device in their list that does **not** carry `superuser="true"` is excluded for that attempt. If no superuser-capable device is present, authentication is denied and the next PAM module in the stack runs.                                                                                            
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  Services **not** marked `superuser=true` are unaffected — all registered devices remain valid (fully backward-compatible).                                                                                                                                                                                                                                                       
    +                                                            
    +  ### User configuration                                                                                                                                                                                                                                                                                                                                                           
    +                                                            
    +  ```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                                                                                                                                                                                                                                                                                                                                                        
    +                                                            
    +  ```xml
    +  <service id="sudo">
    +      <option name="superuser">true</option>
    +  </service>
    +
    +  <service id="su">
    +      <option name="superuser">true</option>                                                                                                                                                                                                                                                                                                                                       
    +  </service>
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  <!-- polkit-1 is already whitelisted for deny_remote; add superuser on top -->
    +  <service id="polkit-1">                                                                                                                                                                                                                                                                                                                                                          
    +      <option name="superuser">true</option>
    +      <option name="deny_remote">false</option>                                                                                                                                                                                                                                                                                                                                    
    +  </service>                                                                                                                                                                                                                                                                                                                                                                       
    +  ```
    +                                                                                                                                                                                                                                                                                                                                                                                   
    +  The `superuser` option can be applied to any service name that appears in your PAM configuration — it is not limited to `sudo`, `su`, and `polkit-1`.                                                                                                                                                                                                                            
    +   
    +  ### Complete example                                                                                                                                                                                                                                                                                                                                                             
    +                                                            
    +  ```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">                                                                        
    ... [truncated]
    
  • doc/pam_usb.conf+23 0 modified
    @@ -106,5 +106,28 @@ See https://github.com/mcdope/pam_usb/wiki/Configuration
     				<service id="polkit-1"><option name="deny_remote">false</option></service>
     				<service id="kde"><option name="deny_remote">false</option></service>
     				<service id="login"><option name="deny_remote">false</option></service>
    +
    +				<!--
    +					Superuser device restriction:
    +					Mark a device with superuser="true" in the <user> block to designate it as
    +					valid for privilege-escalation services. Mark a service with
    +					<option name="superuser">true</option> to require such a device.
    +					Devices without superuser="true" are excluded for those services.
    +					Services without the option: all user devices are accepted (default behavior).
    +
    +					Common superuser 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>
    +
    +					And in the user block:
    +					<user id="alex">
    +						<device>StudentUSB</device>
    +						<device superuser="true">TeacherUSB</device>
    +					</user>
    +				-->
     		</services>
     </configuration>
    
  • doc/SECURITY+156 1 modified
    @@ -32,4 +32,159 @@ If you use the ability to auto-unlock your keyring while using pam_usb you are e
     
     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.
    \ No newline at end of file
    +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`.                                                                                                                                                                                                
    +    
    \ No newline at end of file
    
  • src/conf.c+61 0 modified
    @@ -40,6 +40,7 @@ static void pusb_conf_options_get_from(
     	pusb_xpath_get_time_from(doc, from, "option[@name='pad_expiration']", &(opts->pad_expiration));
     	pusb_xpath_get_time_from(doc, from, "option[@name='probe_timeout']", &(opts->probe_timeout));
     	pusb_xpath_get_bool_from(doc, from, "option[@name='deny_remote']", &(opts->deny_remote));
    +	pusb_xpath_get_bool_from(doc, from, "option[@name='superuser']", &(opts->superuser));
     }
     
     static int pusb_conf_parse_options(
    @@ -220,6 +221,49 @@ int pusb_conf_parse(
     		pusb_conf_parse_device(opts, doc, currentDevice, device_list[currentDevice]);
     	}
     
    +	/* Mark devices that carry superuser="true" in the user's <device> elements. */
    +	{
    +		size_t su_len = sizeof(CONF_USER_XPATH) + CONF_USER_MAXLEN
    +		                + sizeof("device[@superuser='true']");
    +		char *su_xpath = xmalloc(su_len);
    +		if (!su_xpath)
    +		{
    +			log_error("Memory allocation failed\n");
    +			xmlFreeDoc(doc);
    +			xmlCleanupParser();
    +			for (int i = 0; i < 10; i++) xfree(device_list[i]);
    +			return 0;
    +		}
    +		snprintf(su_xpath, su_len, CONF_USER_XPATH, user, "device[@superuser='true']");
    +
    +		char *su_names[10];
    +		for (int i = 0; i < 10; i++)
    +		{
    +			su_names[i] = xmalloc(128);
    +			memset(su_names[i], 0, 128);
    +		}
    +
    +		if (pusb_xpath_get_string_list(doc, su_xpath, su_names, sizeof(opts->device.name), 10))
    +		{
    +			for (int i = 0; i < 10; i++)
    +			{
    +				if (opts->device_list[i].name[0] == '\0') continue;
    +				for (int j = 0; j < 10; j++)
    +				{
    +					if (su_names[j][0] == '\0') continue;
    +					if (strcmp(opts->device_list[i].name, su_names[j]) == 0)
    +					{
    +						opts->device_list[i].superuser = 1;
    +						break;
    +					}
    +				}
    +			}
    +		}
    +
    +		for (int i = 0; i < 10; i++) xfree(su_names[i]);
    +		xfree(su_xpath);
    +	}
    +
     	if (!pusb_conf_parse_options(opts, doc, user, service))
     	{
     		xmlFreeDoc(doc);
    @@ -231,6 +275,23 @@ int pusb_conf_parse(
     		}
     		return (0);
     	}
    +
    +	/* If the service requires a superuser device, remove non-superuser devices. */
    +	if (opts->superuser)
    +	{
    +		log_debug("Service \"%s\" requires superuser device. Filtering device list.\n", service);
    +		for (int i = 0; i < 10; i++)
    +		{
    +			if (opts->device_list[i].name[0] == '\0') continue;
    +			if (!opts->device_list[i].superuser)
    +			{
    +				log_debug("Device \"%s\" excluded for service \"%s\" (no superuser attribute).\n",
    +				          opts->device_list[i].name, service);
    +				memset(&opts->device_list[i], 0, sizeof(t_pusb_device));
    +			}
    +		}
    +	}
    +
     	xmlFreeDoc(doc);
     	xmlCleanupParser();
     
    
  • src/conf.h+2 0 modified
    @@ -41,6 +41,7 @@ typedef struct	pusb_device
     	char		model[128];
     	char		serial[128];
     	char		volume_uuid[128];
    +	int			superuser;
     }				t_pusb_device;
     
     typedef struct		pusb_options
    @@ -58,6 +59,7 @@ typedef struct		pusb_options
     	char			device_pad_directory[PATH_MAX];
     	t_pusb_device	device;
     	t_pusb_device	device_list[10];
    +	int				superuser;
     }					t_pusb_options;
     
     struct		s_opt_list
    
987f4f6ddf0a

Prepare v0.8.7

https://github.com/mcdope/pam_usbMcDopeMay 5, 2026Fixed in 0.8.7via release-tag
7 files changed · +46 7
  • arch_linux/PKGBUILD_git+1 1 modified
    @@ -2,7 +2,7 @@
     # Contributor: Pekka Helenius <fincer89 [at] hotmail [dot] com>
     
     pkgname=pam_usb-git
    -pkgver=0.8.6_r589.g370655a
    +pkgver=0.8.7_r596.g9bce707
     pkgrel=1
     pkgdesc='Hardware authentication for Linux using ordinary flash media (USB & Card based).'
     arch=($CARCH)
    
  • arch_linux/PKGBUILD_stable+1 1 modified
    @@ -2,7 +2,7 @@
     # Contributor: Pekka Helenius <fincer89 [at] hotmail [dot] com>
     
     pkgname=pam_usb
    -pkgver=0.8.6
    +pkgver=0.8.7
     pkgrel=1
     pkgdesc='Hardware authentication for Linux using ordinary flash media (USB & Card based).'
     arch=($CARCH)
    
  • ChangeLog+10 0 modified
    @@ -1,3 +1,13 @@
    +* 0.8.7
    +  [Enhancement] Specify a dedicated device for superuser services
    +  [Enhancement] Restore PolicyKit support (also for 127)
    +  [Enhancement] Remove default installation of pamusb-pinentry
    +  [Security] Fixed GHSA-822m-whrh-vrj8
    +  [Security] Fixed GHSA-jgv5-w6rm-7wxg
    +  [Security] Fixed GHSA-fjpm-p9pj-mp34
    +  [Security] Fixed GHSA-j8cq-2gv6-gfwf
    +  [Security] Fixed GHSA-jxrj-q67x-wr4c
    +
     * 0.8.6
       [Enhancement] Documentation updates
       [Enhancement] Remote VSCode tunnels are now detected in deny_remote check (thx @jaoppb)
    
  • debian/changelog+12 0 modified
    @@ -1,3 +1,15 @@
    +libpam-usb (0.8.7) unstable; urgency=critical
    +  * [Enhancement] Specify a dedicated device for superuser services
    +  * [Enhancement] Restore PolicyKit support (also for 127)
    +  * [Enhancement] Remove default installation of pamusb-pinentry
    +  * [Security] Fixed GHSA-822m-whrh-vrj8
    +  * [Security] Fixed GHSA-jgv5-w6rm-7wxg
    +  * [Security] Fixed GHSA-fjpm-p9pj-mp34
    +  * [Security] Fixed GHSA-j8cq-2gv6-gfwf
    +  * [Security] Fixed GHSA-jxrj-q67x-wr4c
    +
    + -- Tobias Bäumer <tobiasbaeumer@gmail.com>  Tue, 05 May 2026 21:00:00 +0200
    +
     libpam-usb (0.8.6) unstable; urgency=medium
       * [Enhancement] Documentation updates
       * [Enhancement] Remote VSCode tunnels are now detected in deny_remote check (thx @jaoppb)
    
  • fedora/SPECS/pam_usb.spec+12 1 modified
    @@ -1,7 +1,7 @@
     %define _topdir         /usr/local/src/pam_usb/fedora
     %define name            pam_usb 
     %define release         1
    -%define version         0.8.6
    +%define version         0.8.7
     %define buildroot       %{_topdir}/%{name}‑%{version}‑root
     
     BuildRoot: %{buildroot}
    @@ -61,6 +61,17 @@ rm -rf %{buildroot}/usr/share/pam-configs
     %doc %attr(0644,root,root) /usr/share/doc/pam_usb/TROUBLESHOOTING
     
     %changelog
    +
    +* Tue May 05 2026 Tobias Bäumer <tobiasbaeumer@gmail.com> - 0.8.7
    +- [Enhancement] Specify a dedicated device for superuser services
    +- [Enhancement] Restore PolicyKit support (also for 127)
    +- [Enhancement] Remove default installation of pamusb-pinentry
    +- [Security] Fixed GHSA-822m-whrh-vrj8
    +- [Security] Fixed GHSA-jgv5-w6rm-7wxg
    +- [Security] Fixed GHSA-fjpm-p9pj-mp34
    +- [Security] Fixed GHSA-j8cq-2gv6-gfwf
    +- [Security] Fixed GHSA-jxrj-q67x-wr4c
    +
     * Fri May 03 2026 Tobias Bäumer <tobiasbaeumer@gmail.com> - 0.8.6
     - [Enhancement] Documentation updates
     - [Enhancement] Remote VSCode tunnels are now detected in deny_remote check (thx @jaoppb)
    
  • SECURITY.md+9 3 modified
    @@ -5,10 +5,16 @@
     At every point in time only the most recent release is supported.
     
     | Version | Supported          |
    -| ------- | ------------------ |
    -| 0.8.6   | :white_check_mark: |
    -| < 0.8.6 | :x:                |
    +|---------| ------------------ |
    +| 0.8.7   | :white_check_mark: |
    +| < 0.8.7 | :x:                |
     
     ## Reporting a Vulnerability
     
     Please email me at tobiasbaeumer@gmail.com, since Github issues are public.
    +
    +## Note on versions <= 0.8.6
    +
    +There are multiple not yet published security advisories for these versions. Details will follow.
    +
    +But if you're running anything except 0.8.7 please update immediately!
    
  • src/version.h+1 1 modified
    @@ -18,6 +18,6 @@
     #ifndef PUSB_VERSION_H_
     # define PUSB_VERSION_H_
     
    -# define PUSB_VERSION "0.8.6"
    +# define PUSB_VERSION "0.8.7"
     
     #endif /* !PUSB_VERSION_H_ */
    

Vulnerability mechanics

No source-code context for this CVE — mechanics is only generated when we can read the actual fix diff. Without that, the four sections (root cause, attack vector, affected code, fix) would be speculation rather than analysis.

References

1

News mentions

0

No linked articles in our index yet.