Skip to content

Commit

Permalink
openpgp: Support specifying connection timeout
Browse files Browse the repository at this point in the history
Support specifying connection timeout for key refresh operations.  Set
the default to 3 minutes.  This affects both WKD requests (via
requests, supports sub-second timeouts) and GPG requests (via dirmngr,
supports second precision).

Closes: #26
Signed-off-by: Michał Górny <mgorny@gentoo.org>
  • Loading branch information
mgorny committed Apr 29, 2023
1 parent dae1e28 commit a098d83
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
11 changes: 10 additions & 1 deletion gemato/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,20 @@ def __init__(self):
def add_options(self, subp):
super().add_options(subp)

default_timeout = 180

subp.add_argument(
'-K', '--openpgp-key',
help='Use only the OpenPGP key(s) from a specific file')
subp.add_argument(
'--proxy',
help='Use HTTP proxy')
subp.add_argument(
"--timeout",
default=default_timeout,
type=float,
help="Connection timeout (for WKD requests, in seconds, "
f"default: {default_timeout})")

def parse_args(self, args, argp):
super().parse_args(args, argp)
Expand All @@ -116,7 +124,8 @@ def parse_args(self, args, argp):
else:
env_class = OpenPGPSystemEnvironment
self.openpgp_env = env_class(debug=args.log_level == logging.DEBUG,
proxy=args.proxy)
proxy=args.proxy,
timeout=args.timeout)

if args.openpgp_key is not None:
with open(args.openpgp_key, 'rb') as f:
Expand Down
26 changes: 21 additions & 5 deletions gemato/openpgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import errno
import hashlib
import logging
import math
import os
import os.path
import shutil
Expand Down Expand Up @@ -112,7 +113,7 @@ class SystemGPGEnvironment:
(user's home directory or GNUPGHOME).
"""

def __init__(self, debug=False, proxy=None):
def __init__(self, debug=False, proxy=None, timeout=None):
self.debug = debug
self._trusted_keys = set()

Expand Down Expand Up @@ -402,9 +403,10 @@ class IsolatedGPGEnvironment(SystemGPGEnvironment):
or use as a context manager (via 'with').
"""

def __init__(self, debug=False, proxy=None):
def __init__(self, debug=False, proxy=None, timeout=None):
super().__init__(debug=debug)
self.proxy = proxy
self.timeout = timeout
self._home = tempfile.mkdtemp(prefix='gemato.')

with open(os.path.join(self._home, 'dirmngr.conf'), 'w') as f:
Expand All @@ -423,6 +425,19 @@ def __init__(self, debug=False, proxy=None):
log-file {os.path.join(self._home, 'dirmngr.log')}
debug-level guru
''')

if timeout is not None:
# GPG doesn't accept sub-second timeouts
gpg_timeout = math.ceil(timeout)
f.write(f"""
# respect user-specified timeouts
resolver-timeout {gpg_timeout}
connect-timeout {gpg_timeout}
""")

with open(os.path.join(self._home, 'dirmngr.conf'), 'r') as f:
print(f.read())

with open(os.path.join(self._home, 'gpg.conf'), 'w') as f:
f.write('''# autogenerated by gemato
Expand All @@ -445,7 +460,8 @@ def __exit__(self, exc_type, exc_value, exc_cb):
self.close()

def clone(self):
return IsolatedGPGEnvironment(debug=self.debug, proxy=self.proxy)
return IsolatedGPGEnvironment(debug=self.debug, proxy=self.proxy,
timeout=self.timeout)

def close(self):
if self._home is not None:
Expand Down Expand Up @@ -573,7 +589,7 @@ def refresh_keys_wkd(self):
for a in addrs:
url = get_wkd_url(a)
try:
resp = requests.get(url, proxies=proxies)
resp = requests.get(url, proxies=proxies, timeout=self.timeout)
resp.raise_for_status()
except (requests.exceptions.ConnectionError,
requests.exceptions.HTTPError,
Expand Down Expand Up @@ -660,7 +676,7 @@ class PGPyEnvironment:

__slots__ = ['debug', 'keyring', 'proxy']

def __init__(self, debug=False, proxy=None):
def __init__(self, debug=False, proxy=None, timeout=None):
if pgpy is None:
raise OpenPGPNoImplementation('install PGPy')
self.debug = debug
Expand Down

0 comments on commit a098d83

Please sign in to comment.