Skip to content

Commit

Permalink
Cleanup & fix shell-quoting in generated 'env' and 'run-agent.sh' scr…
Browse files Browse the repository at this point in the history
…ipts

* Fix shell-quoting of arguments in .gnupg/trezor/`env` and
  .gnupg/trezor/`run-agent.sh` for non-Windows platforms.

* Fix `AttributeError: 'float' object has no attribute 'translate'` when
  passing --cache-expiry-seconds to `*-gpg init` on all platforms.

* Add "exec" to the sh scripts, where appropriate, so that the wrapped
  command replaces the shell, rather than running in a subprocess.

* Move Bourne sh and Windows batch-file templates into separate sections
  of code, since it doesn't make sense to combine them once we're doing
  quoting properly.

* Use standard POSIX /bin/sh syntax in the env script so that this has
  the possibility of working on systems without /bin/bash.
  • Loading branch information
dlitz committed Aug 2, 2024
1 parent dace3eb commit 1042946
Showing 1 changed file with 31 additions and 22 deletions.
53 changes: 31 additions & 22 deletions libagent/gpg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
import logging
import os
import re
import shlex
import stat
import subprocess
import sys
import textwrap

try:
# TODO: Not supported on Windows. Use daemoniker instead?
Expand Down Expand Up @@ -152,26 +154,33 @@ def run_init(device_type, args):
agent_path = util.which('{}-gpg-agent'.format(device_name))

# Prepare GPG agent invocation script (to pass the PATH from environment).
extra_options = {}
for arg in ['pin_entry_binary', 'passphrase_entry_binary', 'cache_expiry_seconds']:
if hasattr(args, arg):
extra_options[arg.replace('_', '-')] = getattr(args, arg)
with open(os.path.join(homedir, ('run-agent.sh'
if sys.platform != 'win32' else
'run-agent.bat')), 'w') as f:
if sys.platform != 'win32':
f.write(r"""#!/bin/sh
export PATH="{0}"
""".format(util.escape_cmd_quotes(os.environ['PATH'])))
quoted_extra_args = shlex.join(
f"--{name}={value}" for name, value in extra_options.items()
)
f.write(textwrap.dedent(rf"""
#!/bin/sh
export PATH={shlex.quote(os.environ['PATH'])}
exec {shlex.quote(agent_path)} -vv {quoted_extra_args} "$@"
"""
).lstrip())
else:
f.write(r"""@echo off
set PATH={0}
""".format(util.escape_cmd_win(os.environ['PATH'])))
f.write('"{0}" -vv'.format(util.escape_cmd_quotes(agent_path)))
for arg in ['pin_entry_binary', 'passphrase_entry_binary', 'cache_expiry_seconds']:
if hasattr(args, arg):
f.write(' "--{0}={1}"'.format(arg.replace('_', '-'),
util.escape_cmd_quotes(getattr(args, arg))))
if sys.platform != 'win32':
f.write(' $*\n')
else:
f.write(' %*\n')
quoted_extra_args = " ".join(
f"--{name}={util.escape_cmd_quotes(str(value))}"
for name, value in extra_options.items()
)
f.write(textwrap.dedent(rf"""
@echo off
set PATH={util.escape_cmd_win(os.environ['PATH'])}
{util.escape_cmd_quotes(agent_path)} -vv {quoted_extra_args} %*
""").lstrip())
os.chmod(f.name, 0o700)
run_agent_script = f.name

Expand All @@ -185,17 +194,17 @@ def run_init(device_type, args):

# Prepare a helper script for setting up the new identity
with open(os.path.join(homedir, 'env'), 'w') as f:
f.write("""#!/bin/bash
f.write("""#!/bin/sh
set -eu
export GNUPGHOME={0}
COMMAND=$*
if [ -z "${{COMMAND}}" ]
GNUPGHOME={0}
export GNUPGHOME
if [ -z "$*" ]
then
${{SHELL}}
exec "$SHELL"
else
${{COMMAND}}
exec "$@"
fi
""".format(homedir))
""".format(shlex.quote(homedir)))
os.chmod(f.name, 0o700)

# Generate new GPG identity and import into GPG keyring
Expand Down

0 comments on commit 1042946

Please sign in to comment.