summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/import/pull-common.c33
-rw-r--r--src/import/pull-job.c50
-rw-r--r--src/import/pull-job.h8
-rw-r--r--src/import/pull-raw.c12
-rw-r--r--src/import/pull-tar.c12
5 files changed, 103 insertions, 12 deletions
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index 62a9195cc4..4c745288f5 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -275,6 +275,7 @@ int pull_make_verification_jobs(
_cleanup_(pull_job_unrefp) PullJob *checksum_job = NULL, *signature_job = NULL;
int r;
+ const char *chksums = NULL;
assert(ret_checksum_job);
assert(ret_signature_job);
@@ -284,10 +285,16 @@ int pull_make_verification_jobs(
assert(glue);
if (verify != IMPORT_VERIFY_NO) {
- _cleanup_free_ char *checksum_url = NULL;
+ _cleanup_free_ char *checksum_url = NULL, *fn = NULL;
- /* Queue job for the SHA256SUMS file for the image */
- r = import_url_change_last_component(url, "SHA256SUMS", &checksum_url);
+ /* Queue jobs for the checksum file for the image. */
+ r = import_url_last_component(url, &fn);
+ if (r < 0)
+ return r;
+
+ chksums = strjoina(fn, ".sha256");
+
+ r = import_url_change_last_component(url, chksums, &checksum_url);
if (r < 0)
return r;
@@ -362,6 +369,15 @@ static int verify_one(PullJob *checksum_job, PullJob *job) {
line,
strlen(line));
+ if (!p) {
+ line = strjoina(job->checksum, " ", fn, "\n");
+
+ p = memmem(checksum_job->payload,
+ checksum_job->payload_size,
+ line,
+ strlen(line));
+ }
+
if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n')) {
log_error("DOWNLOAD INVALID: Checksum of %s file did not checkout, file has been tampered with.", fn);
return -EBADMSG;
@@ -416,6 +432,9 @@ int pull_verify(PullJob *main_job,
if (!signature_job)
return 0;
+ if (checksum_job->style == VERIFICATION_PER_FILE)
+ signature_job = checksum_job;
+
assert(signature_job->state == PULL_JOB_DONE);
if (!signature_job->payload || signature_job->payload_size <= 0) {
@@ -507,9 +526,11 @@ int pull_verify(PullJob *main_job,
cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH;
cmd[k++] = "--verify";
- cmd[k++] = sig_file_path;
- cmd[k++] = "-";
- cmd[k++] = NULL;
+ if (checksum_job->style == VERIFICATION_PER_DIRECTORY) {
+ cmd[k++] = sig_file_path;
+ cmd[k++] = "-";
+ cmd[k++] = NULL;
+ }
stdio_unset_cloexec();
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index 70aaa5c291..8eabb09eed 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -29,6 +29,8 @@
#include "string-util.h"
#include "strv.h"
#include "xattr-util.h"
+#include "pull-common.h"
+#include "import-util.h"
PullJob* pull_job_unref(PullJob *j) {
if (!j)
@@ -73,6 +75,33 @@ static void pull_job_finish(PullJob *j, int ret) {
j->on_finished(j);
}
+static int pull_job_restart(PullJob *j) {
+ int r;
+ char *chksum_url = NULL;
+
+ r = import_url_change_last_component(j->url, "SHA256SUMS", &chksum_url);
+ if (r < 0)
+ return r;
+
+ free(j->url);
+ free(j->payload);
+ j->url = chksum_url;
+ j->state = PULL_JOB_INIT;
+ j->payload = NULL;
+ j->payload_size = 0;
+ j->payload_allocated = 0;
+ j->written_compressed = 0;
+ j->written_uncompressed = 0;
+ j->written_since_last_grow = 0;
+
+ r = pull_job_begin(j);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+
void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
PullJob *j = NULL;
CURLcode code;
@@ -102,6 +131,26 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
r = 0;
goto finish;
} else if (status >= 300) {
+ if (status == 404 && j->style == VERIFICATION_PER_FILE) {
+
+ /* retry pull job with SHA256SUMS file */
+ r = pull_job_restart(j);
+ if (r < 0)
+ goto finish;
+
+ code = curl_easy_getinfo(j->curl, CURLINFO_RESPONSE_CODE, &status);
+ if (code != CURLE_OK) {
+ log_error("Failed to retrieve response code: %s", curl_easy_strerror(code));
+ r = -EIO;
+ goto finish;
+ }
+
+ if (status == 0) {
+ j->style = VERIFICATION_PER_DIRECTORY;
+ return;
+ }
+ }
+
log_error("HTTP request to %s failed with code %li.", j->url, status);
r = -EIO;
goto finish;
@@ -528,6 +577,7 @@ int pull_job_new(PullJob **ret, const char *url, CurlGlue *glue, void *userdata)
j->content_length = (uint64_t) -1;
j->start_usec = now(CLOCK_MONOTONIC);
j->compressed_max = j->uncompressed_max = 64LLU * 1024LLU * 1024LLU * 1024LLU; /* 64GB safety limit */
+ j->style = VERIFICATION_STYLE_UNSET;
j->url = strdup(url);
if (!j->url)
diff --git a/src/import/pull-job.h b/src/import/pull-job.h
index 3a152a50e3..412b66cf22 100644
--- a/src/import/pull-job.h
+++ b/src/import/pull-job.h
@@ -42,6 +42,12 @@ typedef enum PullJobState {
_PULL_JOB_STATE_INVALID = -1,
} PullJobState;
+typedef enum VerificationStyle {
+ VERIFICATION_STYLE_UNSET,
+ VERIFICATION_PER_FILE, /* SuSE-style ".sha256" files with inline signature */
+ VERIFICATION_PER_DIRECTORY, /* Ubuntu-style SHA256SUM files with detach SHA256SUM.gpg signatures */
+} VerificationStyle;
+
#define PULL_JOB_IS_COMPLETE(j) (IN_SET((j)->state, PULL_JOB_DONE, PULL_JOB_FAILED))
struct PullJob {
@@ -94,6 +100,8 @@ struct PullJob {
bool grow_machine_directory;
uint64_t written_since_last_grow;
+
+ VerificationStyle style;
};
int pull_job_new(PullJob **job, const char *url, CurlGlue *glue, void *userdata);
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 60a769e944..fd2e472f09 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -478,11 +478,9 @@ static void raw_pull_job_on_finished(PullJob *j) {
} else if (j == i->settings_job) {
if (j->error != 0)
log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
- } else if (j->error != 0) {
+ } else if (j->error != 0 && j != i->signature_job) {
if (j == i->checksum_job)
log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
- else if (j == i->signature_job)
- log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
else
log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
@@ -500,6 +498,13 @@ static void raw_pull_job_on_finished(PullJob *j) {
if (!raw_pull_is_done(i))
return;
+ if (i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
+ log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+
+ r = i->signature_job->error;
+ goto finish;
+ }
+
if (i->roothash_job)
i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
if (i->settings_job)
@@ -744,6 +749,7 @@ int raw_pull_start(
if (i->checksum_job) {
i->checksum_job->on_progress = raw_pull_job_on_progress;
+ i->checksum_job->style = VERIFICATION_PER_FILE;
r = pull_job_begin(i->checksum_job);
if (r < 0)
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index 91833d6174..d4b599ba95 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -298,11 +298,9 @@ static void tar_pull_job_on_finished(PullJob *j) {
if (j == i->settings_job) {
if (j->error != 0)
log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
- } else if (j->error != 0) {
+ } else if (j->error != 0 && j != i->signature_job) {
if (j == i->checksum_job)
log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
- else if (j == i->signature_job)
- log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
else
log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
@@ -317,6 +315,13 @@ static void tar_pull_job_on_finished(PullJob *j) {
if (!tar_pull_is_done(i))
return;
+ if (i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
+ log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+
+ r = i->signature_job->error;
+ goto finish;
+ }
+
i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd);
if (i->settings_job)
i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
@@ -547,6 +552,7 @@ int tar_pull_start(
if (i->checksum_job) {
i->checksum_job->on_progress = tar_pull_job_on_progress;
+ i->checksum_job->style = VERIFICATION_PER_FILE;
r = pull_job_begin(i->checksum_job);
if (r < 0)