Skip to content

Commit

Permalink
Always use a non-default GnuPG home directory
Browse files Browse the repository at this point in the history
For split-gpg2, using the default GnuPG home directory is unsafe.
split-gpg2 must not have access to a key capable of certification.
Using a different home directory (~/.config/qubes-split-gpg2/gnupg by
default) is the first step in enforcing this.  Users who *really* want
to use the original home directory can specify it explicitly in
`~/.config/qubes-split-gpg2/qubes-split-gpg.conf`.
  • Loading branch information
DemiMarie committed Oct 24, 2022
1 parent e29878b commit 06326e4
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 4 deletions.
3 changes: 3 additions & 0 deletions qubes.Gpg2.service
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#!/bin/bash

# Unset GNUPGHOME; the default (which might be set in the user's login
# scripts) is not what is wanted.
unset GNUPGHOME
for d in /etc "${XDG_CONFIG_HOME:-$HOME/.config}"; do
rc_file="$d/split-gpg2-rc"
if [ -r "$rc_file" ]; then
Expand Down
9 changes: 6 additions & 3 deletions splitgpg2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ class GpgServer:
commands: Dict[bytes, 'NoneCallback']
client_domain: str
seen_data: bool
config_loaded: bool
keygrip_map: Dict[bytes, Union[KeyInfo, SubKeyInfo]]
notify_on_disconnect: Set[Awaitable[object]]
gnupghome: Optional[str]
Expand All @@ -231,22 +232,23 @@ def __init__(self, reader: asyncio.StreamReader,
#: signal those Futures when connection is terminated
self.notify_on_disconnect = set()
self.log_io_enable = False
self.gnupghome = None
self.gnupghome = xdg.BaseDirectory.xdg_config_home + '/qubes-split-gpg2/gnupg'

self.client_reader = reader
self.client_writer = writer
self.client_domain = client_domain
self.commands = self.default_commands()
self.options = self.default_options()
self.hash_algos = self.default_hash_algos()
self.keygrip_map = {}

self.log = logging.getLogger('splitgpg2.Server')
self.agent_socket_path = None
self.agent_reader: Optional[asyncio.StreamReader] = None
self.agent_writer: Optional[asyncio.StreamWriter] = None

self.update_keygrip_map()
self.seen_data = False
self.config_loaded = False

if debug_log:
handler = logging.FileHandler(debug_log)
Expand Down Expand Up @@ -283,6 +285,7 @@ def _parse_bool_val(self, value, option_name) -> bool:
raise ValueError(value)

def load_config(self, config) -> None:
self.config_loaded = True
default_autoaccept = config.get('autoaccept', 'no')
for timer_name in TIMER_NAMES:
timer_value = config.get(timer_name + '_autoaccept',
Expand Down Expand Up @@ -350,6 +353,7 @@ def homedir_opts(self) -> List[str]:
return []

async def connect_agent(self) -> None:
assert self.config_loaded, 'Config not loaded?'
try:
subprocess.check_call(
['gpgconf', *self.homedir_opts(), '--launch', 'gpg-agent'])
Expand Down Expand Up @@ -781,7 +785,6 @@ def update_keygrip_map(self) -> None:
elif fields[0] == b"ssb":
assert primary_key is not None, 'subkey before primary key?'
subkey = SubKeyInfo(fields[11], primary_key)
primary_key.subkeys.append(subkey)
elif fields[0] == b"fpr":
assert primary_key is not None, 'bad output from GnuPG'
if subkey is None:
Expand Down
3 changes: 2 additions & 1 deletion splitgpg2/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
from unittest import mock
from . import GpgServer


class SimplePinentry(asyncio.Protocol):
def __init__(self, cmd_mock) -> None:
super().__init__()
Expand Down Expand Up @@ -72,6 +71,8 @@ def setup_server(self, reader, writer):
self.notify_mock = mock.patch.object(
gpg_server, 'notify').start()
gpg_server.log_io_enable = True
gpg_server.gnupghome = os.environ['GNUPGHOME']
gpg_server.config_loaded = True
asyncio.ensure_future(gpg_server.run())

def start_dummy_pinentry(self):
Expand Down

0 comments on commit 06326e4

Please sign in to comment.