diff --git a/doc/CONFIGURATION.md b/doc/CONFIGURATION.md
index 0613e0b..a5943a1 100644
--- a/doc/CONFIGURATION.md
+++ b/doc/CONFIGURATION.md
@@ -244,6 +244,13 @@ Users
agent |
+ env |
+ Element |
+ An environment variable for the command. For multiple variables use multiple env tags |
+
+ cmd |
+ Element |
+ Agent command, associated with env tags in the same agent element |
Element |
Agent commands, for use with pamusb-agent |
@@ -257,12 +264,24 @@ Example:
- gnome-screensaver-command --lock
- beep-media-player --pause
+
+ DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
+ HOME=/home/scox
+ gnome-screensaver-command --lock
+
+
+ beep-media-player --pause
+
- gnome-screensaver-command --deactivate
- beep-media-player --play
+
+ DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
+ HOME=/home/scox
+ gnome-screensaver-command --deactivate
+
+
+ beep-media-player --play
+
```
@@ -299,7 +318,7 @@ Example:
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`.
+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.
diff --git a/tools/pamusb-agent b/tools/pamusb-agent
index 759ba85..0cec85d 100755
--- a/tools/pamusb-agent
+++ b/tools/pamusb-agent
@@ -21,6 +21,7 @@ import pwd
import getopt
import signal
import re
+import subprocess
import syslog
import gi
import threading
@@ -110,6 +111,12 @@ def usage():
os.path.basename(__file__))
sys.exit(1)
+def runAs(uid, gid):
+ def set_id():
+ os.setuid(uid)
+ os.setgid(gid)
+ return set_id
+
import getopt
try:
@@ -149,6 +156,9 @@ users = doc.findall('users/user')
def userDeviceThread(user):
userName = user.get('id')
+ uid = pwd.getpwnam(userName)[2]
+ gid = pwd.getpwnam(userName)[3]
+ os.environ = None
events = {
'lock' : [],
@@ -156,7 +166,19 @@ def userDeviceThread(user):
}
for hotplug in user.findall('agent'):
- events[hotplug.get('event')].append(hotplug.text)
+ henvs = {}
+
+ for henv in hotplug.findall('env'):
+ henv_var = re.sub(r'^(.*?)=.*$', '\\1', henv.text)
+ henv_arg = re.sub(r'^.*?=(.*)$', '\\1', henv.text)
+ henvs[henv_var] = henv_arg
+
+ events[hotplug.get('event')].append(
+ {
+ 'env': henvs,
+ 'cmd': hotplug.find('cmd').text
+ }
+ )
deviceName = user.find('device').text.strip()
@@ -174,9 +196,13 @@ def userDeviceThread(user):
if event == 'removed':
logger.info('Device "%s" has been removed, ' \
'locking down user "%s"...' % (deviceName, userName))
- for cmd in events['lock']:
+
+ for l in events['lock']:
+ cmd = l['cmd']
+
logger.info('Running "%s"' % cmd)
- os.system(cmd)
+ subprocess.run(cmd.split(), env=l['env'], preexec_fn=runAs(uid, gid))
+
logger.info('Locked.')
return
@@ -188,10 +214,15 @@ def userDeviceThread(user):
if not os.system(cmdLine):
logger.info('Authentication succeeded. ' \
'Unlocking user "%s"...' % userName)
- for cmd in events['unlock']:
+
+ for l in events['unlock']:
+ cmd = l['cmd']
+
logger.info('Running "%s"' % cmd)
- os.system(cmd)
+ subprocess.run(cmd.split(), env=l['env'], preexec_fn=runAs(uid, gid))
+
logger.info('Unlocked.')
+
else:
logger.info('Authentication failed for device %s. ' \
'Keeping user "%s" locked down.' % (deviceName, userName))