mirror of
https://github.com/systemd/systemd.git
synced 2026-08-09 09:32:04 +00:00
import: Trust subkeys included in signature
With gpg sub keys one can rotate signing keys while having a stable trust anchor. So far one still had to ship the sub key out of band but a newer gpg has the option to include the sub key in the signature and import it automatically. This is safe if we only allow importing a sub key signed by the top key we already have in the key ring. Add the --auto-key-import argument to gpg to import subkeys but also set --import-options=merge-only,import-clean to restrict what we import to only be sub keys signed by the top key we have in the keyring and discard any irrelevant parts. The ugly part is that we also have to work on a temporary copy of the keyring because gpg wants to persist the added key material but we don't what that here.
This commit is contained in:
2
README
2
README
@@ -270,6 +270,8 @@ REQUIREMENTS:
|
||||
NOTE: If using dbus < 1.9.18, you should override the default
|
||||
policy directory (--with-dbuspolicydir=/etc/dbus-1/system.d).
|
||||
polkit (optional)
|
||||
gnupg >= 2.4 optional (for signature verification in: importctl,
|
||||
systemd-sysupdate)
|
||||
|
||||
To build in directory build/:
|
||||
meson setup build/ && ninja -C build/
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "copy.h"
|
||||
#include "dirent-util.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
@@ -409,7 +410,8 @@ static int verify_gpg(
|
||||
_cleanup_(rm_rf_physical_and_freep) char *gpg_home = NULL;
|
||||
char sig_file_path[] = "/tmp/sigXXXXXX";
|
||||
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||
const char *keyring_override;
|
||||
_cleanup_free_ char *keyring_copy = NULL;
|
||||
const char *keyring_override, *keyring_source;
|
||||
int r;
|
||||
|
||||
assert(iovec_is_valid(payload));
|
||||
@@ -446,6 +448,31 @@ static int verify_gpg(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (keyring_override)
|
||||
keyring_source = keyring_override;
|
||||
else if (access(USER_KEYRING_PATH, F_OK) >= 0)
|
||||
keyring_source = USER_KEYRING_PATH;
|
||||
else if (access(USER_KEYRING_PATH_LEGACY, F_OK) >= 0)
|
||||
keyring_source = USER_KEYRING_PATH_LEGACY;
|
||||
else
|
||||
keyring_source = VENDOR_KEYRING_PATH;
|
||||
|
||||
/* For whatever reason gpg --auto-key-import writes the key material embedded in the signature
|
||||
* (the signing subkey) back into the keyring it verifies against instead of just using it
|
||||
* temporarily. Verify against a throwaway copy in the tmp home so we never write to the
|
||||
* original keyring. */
|
||||
keyring_copy = path_join(gpg_home, "keyring.gpg");
|
||||
if (!keyring_copy) {
|
||||
r = log_oom();
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = copy_file(keyring_source, keyring_copy, 0, 0600, /* copy_flags= */ 0);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to copy keyring '%s': %m", keyring_source);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = pidref_safe_fork_full(
|
||||
"(gpg)",
|
||||
(int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO },
|
||||
@@ -463,6 +490,8 @@ static int verify_gpg(
|
||||
"--no-auto-check-trustdb",
|
||||
"--batch",
|
||||
"--trust-model=always",
|
||||
"--auto-key-import",
|
||||
"--import-options=merge-only,import-clean",
|
||||
NULL, /* --homedir= */
|
||||
NULL, /* --keyring= */
|
||||
NULL, /* --verify */
|
||||
@@ -475,18 +504,7 @@ static int verify_gpg(
|
||||
/* Child */
|
||||
|
||||
cmd[k++] = strjoina("--homedir=", gpg_home);
|
||||
|
||||
if (keyring_override)
|
||||
cmd[k++] = strjoina("--keyring=", keyring_override);
|
||||
else if (access(USER_KEYRING_PATH, F_OK) >= 0) /* We add the user keyring only to the
|
||||
* command line arguments, if it's around
|
||||
* since gpg fails otherwise. */
|
||||
cmd[k++] = "--keyring=" USER_KEYRING_PATH;
|
||||
else if (access(USER_KEYRING_PATH_LEGACY, F_OK) >= 0)
|
||||
cmd[k++] = "--keyring=" USER_KEYRING_PATH_LEGACY;
|
||||
else
|
||||
cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH;
|
||||
|
||||
cmd[k++] = strjoina("--keyring=", keyring_copy);
|
||||
cmd[k++] = "--verify";
|
||||
if (signature) {
|
||||
cmd[k++] = sig_file_path;
|
||||
|
||||
Reference in New Issue
Block a user