From ac71ece3c6ccc67dd5965c64026c879bcaec77f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 16 Jan 2021 00:06:13 +0100 Subject: [PATCH] import: refactor how we do gpg validation Let's split out the actual gpg logic into a helper function, so that we can add alternative validations later on. --- src/import/pull-common.c | 143 +++++++++++++++++++++------------------ src/import/pull-common.h | 2 +- src/import/pull-raw.c | 2 +- src/import/pull-tar.c | 2 +- 4 files changed, 82 insertions(+), 67 deletions(-) diff --git a/src/import/pull-common.c b/src/import/pull-common.c index 8f295090038..403a0952bcf 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -363,77 +363,35 @@ static int verify_one(PullJob *checksum_job, PullJob *job) { return 1; } -int pull_verify(PullJob *main_job, - PullJob *roothash_job, - PullJob *settings_job, - PullJob *checksum_job, - PullJob *signature_job) { +static int verify_gpg( + const void *payload, size_t payload_size, + const void *signature, size_t signature_size) { _cleanup_close_pair_ int gpg_pipe[2] = { -1, -1 }; - _cleanup_close_ int sig_file = -1; char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX"; _cleanup_(sigkill_waitp) pid_t pid = 0; bool gpg_home_created = false; - VerificationStyle style; int r; - assert(main_job); - assert(main_job->state == PULL_JOB_DONE); - - if (!checksum_job) - return 0; - - assert(main_job->calc_checksum); - assert(main_job->checksum); - - assert(checksum_job->state == PULL_JOB_DONE); - - if (!checksum_job->payload || checksum_job->payload_size <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), - "Checksum is empty, cannot verify."); - - r = verify_one(checksum_job, main_job); - if (r < 0) - return r; - - r = verify_one(checksum_job, roothash_job); - if (r < 0) - return r; - - r = verify_one(checksum_job, settings_job); - if (r < 0) - return r; - - if (!signature_job) - return 0; - - r = verification_style_from_url(checksum_job->url, &style); - if (r < 0) - return log_error_errno(r, "Failed to determine verification style from URL '%s': %m", checksum_job->url); - - if (style == VERIFICATION_PER_FILE) /* if this is per-file verification, then the signature is in the - * checksum job, let's thus ignore the signature job from now on, - * and use the checksum job as signature job. */ - signature_job = checksum_job; - - assert(signature_job->state == PULL_JOB_DONE); - - if (!signature_job->payload || signature_job->payload_size <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), - "Signature is empty, cannot verify."); + assert(payload || payload_size == 0); + assert(signature || signature_size == 0); r = pipe2(gpg_pipe, O_CLOEXEC); if (r < 0) return log_error_errno(errno, "Failed to create pipe for gpg: %m"); - sig_file = mkostemp(sig_file_path, O_RDWR); - if (sig_file < 0) - return log_error_errno(errno, "Failed to create temporary file: %m"); + if (signature_size > 0) { + _cleanup_close_ int sig_file = -1; - r = loop_write(sig_file, signature_job->payload, signature_job->payload_size, false); - if (r < 0) { - log_error_errno(r, "Failed to write to temporary file: %m"); - goto finish; + sig_file = mkostemp(sig_file_path, O_RDWR); + if (sig_file < 0) + return log_error_errno(errno, "Failed to create temporary file: %m"); + + r = loop_write(sig_file, signature, signature_size, false); + if (r < 0) { + log_error_errno(r, "Failed to write to temporary file: %m"); + goto finish; + } } if (!mkdtemp(gpg_home)) { @@ -462,7 +420,7 @@ int pull_verify(PullJob *main_job, NULL, /* dash */ NULL /* trailing NULL */ }; - unsigned k = ELEMENTSOF(cmd) - 6; + size_t k = ELEMENTSOF(cmd) - 6; /* Child */ @@ -478,8 +436,7 @@ int pull_verify(PullJob *main_job, cmd[k++] = strjoina("--homedir=", gpg_home); - /* We add the user keyring only to the command line - * arguments, if it's around since gpg fails + /* We add the user keyring only to the command line arguments, if it's around since gpg fails * otherwise. */ if (access(USER_KEYRING_PATH, F_OK) >= 0) cmd[k++] = "--keyring=" USER_KEYRING_PATH; @@ -487,7 +444,7 @@ int pull_verify(PullJob *main_job, cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH; cmd[k++] = "--verify"; - if (style == VERIFICATION_PER_DIRECTORY) { + if (signature) { cmd[k++] = sig_file_path; cmd[k++] = "-"; cmd[k++] = NULL; @@ -501,7 +458,7 @@ int pull_verify(PullJob *main_job, gpg_pipe[0] = safe_close(gpg_pipe[0]); - r = loop_write(gpg_pipe[1], checksum_job->payload, checksum_job->payload_size, false); + r = loop_write(gpg_pipe[1], payload, payload_size, false); if (r < 0) { log_error_errno(r, "Failed to write to pipe: %m"); goto finish; @@ -522,7 +479,8 @@ int pull_verify(PullJob *main_job, } finish: - (void) unlink(sig_file_path); + if (signature_size > 0) + (void) unlink(sig_file_path); if (gpg_home_created) (void) rm_rf(gpg_home, REMOVE_ROOT|REMOVE_PHYSICAL); @@ -530,6 +488,63 @@ finish: return r; } +int pull_verify(ImportVerify verify, + PullJob *main_job, + PullJob *roothash_job, + PullJob *settings_job, + PullJob *checksum_job, + PullJob *signature_job) { + + VerificationStyle style; + int r; + + assert(main_job); + assert(main_job->state == PULL_JOB_DONE); + + if (verify == IMPORT_VERIFY_NO) + return 0; + + assert(main_job->calc_checksum); + assert(main_job->checksum); + assert(checksum_job); + assert(checksum_job->state == PULL_JOB_DONE); + + if (!checksum_job->payload || checksum_job->payload_size <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Checksum is empty, cannot verify."); + + r = verify_one(checksum_job, main_job); + if (r < 0) + return r; + + r = verify_one(checksum_job, roothash_job); + if (r < 0) + return r; + + r = verify_one(checksum_job, settings_job); + if (r < 0) + return r; + + if (verify == IMPORT_VERIFY_CHECKSUM) + return 0; + + r = verification_style_from_url(checksum_job->url, &style); + if (r < 0) + return log_error_errno(r, "Failed to determine verification style from URL '%s': %m", checksum_job->url); + + if (style == VERIFICATION_PER_DIRECTORY) { + assert(signature_job); + assert(signature_job->state == PULL_JOB_DONE); + + if (!signature_job->payload || signature_job->payload_size <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Signature is empty, cannot verify."); + + return verify_gpg(checksum_job->payload, checksum_job->payload_size, signature_job->payload, signature_job->payload_size); + } else + return verify_gpg(checksum_job->payload, checksum_job->payload_size, NULL, 0); +} + int verification_style_from_url(const char *url, VerificationStyle *ret) { _cleanup_free_ char *last = NULL; int r; diff --git a/src/import/pull-common.h b/src/import/pull-common.h index f24093e6e11..acbbab7eabf 100644 --- a/src/import/pull-common.h +++ b/src/import/pull-common.h @@ -27,7 +27,7 @@ int pull_make_path(const char *url, const char *etag, const char *image_root, co int pull_make_auxiliary_job(PullJob **ret, const char *url, int (*strip_suffixes)(const char *name, char **ret), const char *suffix, CurlGlue *glue, PullJobFinished on_finished, void *userdata); int pull_make_verification_jobs(PullJob **ret_checksum_job, PullJob **ret_signature_job, ImportVerify verify, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata); -int pull_verify(PullJob *main_job, PullJob *roothash_job, PullJob *settings_job, PullJob *checksum_job, PullJob *signature_job); +int pull_verify(ImportVerify verify, PullJob *main_job, PullJob *roothash_job, PullJob *settings_job, PullJob *checksum_job, PullJob *signature_job); typedef enum VerificationStyle { VERIFICATION_PER_FILE, /* SuSE-style ".sha256" files with inline gpg signature */ diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 5b4525d456c..0985dddef37 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -542,7 +542,7 @@ static void raw_pull_job_on_finished(PullJob *j) { raw_pull_report_progress(i, RAW_VERIFYING); - r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job); + r = pull_verify(i->verify, i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job); if (r < 0) goto finish; diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c index 1ee0db15604..b52569d20c5 100644 --- a/src/import/pull-tar.c +++ b/src/import/pull-tar.c @@ -336,7 +336,7 @@ static void tar_pull_job_on_finished(PullJob *j) { tar_pull_report_progress(i, TAR_VERIFYING); - r = pull_verify(i->tar_job, NULL, i->settings_job, i->checksum_job, i->signature_job); + r = pull_verify(i->verify, i->tar_job, NULL, i->settings_job, i->checksum_job, i->signature_job); if (r < 0) goto finish; -- 2.47.3