From 7e0d9942bac5477f3f16e65f060ff16725525486 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 1 Feb 2025 16:18:24 +0000 Subject: [PATCH] repo: Sign the repository metadata instead of the database I don't think that there is any chance that we will be able to get rid of the JSON object. Signed-off-by: Michael Tremer --- src/pakfire/repo.c | 147 +++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 91 deletions(-) diff --git a/src/pakfire/repo.c b/src/pakfire/repo.c index aa19f84c..58141da4 100644 --- a/src/pakfire/repo.c +++ b/src/pakfire/repo.c @@ -1964,59 +1964,15 @@ int pakfire_repo_refresh(struct pakfire_repo* repo, int force) { return 0; } -static int pakfire_repo_sign_database(struct pakfire_repo* repo, struct pakfire_key* key, - const char* database_path) { - char signature_path[PATH_MAX]; - FILE* f = NULL; - FILE* s = NULL; - int r; - - // Compose the signature path - r = pakfire_string_format(signature_path, "%s.sig", database_path); - if (r) - return r; - - // Open the signature file for writing - s = fopen(signature_path, "w"); - if (!s) { - ERROR(repo->ctx, "Could not open %s for writing: %m\n", signature_path); - r = 1; - goto ERROR; - } - - // Open the database for reading - f = fopen(database_path, "r"); - if (!f) { - ERROR(repo->ctx, "Could not open %s for reading: %m\n", database_path); - r = 1; - goto ERROR; - } - - // Create the signature - r = pakfire_key_sign(key, s, f, "Database Signature"); - if (r) { - ERROR(repo->ctx, "Could not sign the database: %m\n"); - goto ERROR; - } - -ERROR: - if (f) - fclose(f); - if (s) - fclose(s); - - return r; -} - -static int pakfire_repo_write_database(struct pakfire_repo* repo, struct pakfire_key* key, - const char* path, char* filename, size_t length) { +static int pakfire_repo_write_database( + struct pakfire_repo* repo, char* filename, size_t length) { char database[PATH_MAX]; char tmp[PATH_MAX]; int r; // Create path for a temporary database export file - r = pakfire_string_format(tmp, "%s/repodata/.pakfire-solv.XXXXXX", path); - if (r) + r = pakfire_repo_path(repo, tmp, "%s", "repodata/.pakfire-solv.XXXXXX"); + if (r < 0) return r; // Create a temporary file to write to @@ -2052,28 +2008,20 @@ static int pakfire_repo_write_database(struct pakfire_repo* repo, struct pakfire } // Make final database path - r = pakfire_string_format(database, "%s/repodata/%s", path, filename); - if (r) { + r = pakfire_repo_path(repo, database, "repodata/%s", filename); + if (r < 0) { ERROR(repo->ctx, "Could not join database path: %m\n"); goto ERROR; } // Link database to its destination r = link(tmp, database); - if (r) { + if (r < 0) { ERROR(repo->ctx, "Could not link database %s: %m\n", database); + r = -errno; goto ERROR; } - // Sign the database - if (key) { - r = pakfire_repo_sign_database(repo, key, database); - if (r) { - ERROR(repo->ctx, "Could not sign the database: %m\n"); - goto ERROR; - } - } - ERROR: if (f) fclose(f); @@ -2084,33 +2032,38 @@ ERROR: return r; } -int pakfire_repo_write_metadata(struct pakfire_repo* repo, struct pakfire_key* key) { +int pakfire_repo_write_metadata(struct pakfire_repo* self, struct pakfire_key* key) { struct json_object* repomd = NULL; + char repomd_path[PATH_MAX]; + char sigpath[PATH_MAX]; + char database[PATH_MAX]; FILE* f = NULL; + FILE* s = NULL; int r = 1; // This can only be called for local repositories - if (!pakfire_repo_is_local(repo)) { - errno = ENOTSUP; - return 1; - } + if (!pakfire_repo_is_local(self)) + return -ENOTSUP; - // Fetch the base path - const char* path = pakfire_repo_get_path(repo); - if (!path) - return 1; + // Make path to repomd.json + r = pakfire_repo_path(self, repomd_path, "%s", "repodata/repomd.json"); + if (r < 0) + goto ERROR; - char database[PATH_MAX]; + // Make the signature path + r = pakfire_string_format(sigpath, "%s.sig", repomd_path); + if (r < 0) + goto ERROR; // Write the database - r = pakfire_repo_write_database(repo, key, path, database, sizeof(database)); - if (r) - return r; + r = pakfire_repo_write_database(self, database, sizeof(database)); + if (r < 0) + goto ERROR; // Compose JSON object repomd = json_object_new_object(); if (!repomd) { - ERROR(repo->ctx, "Could not allocate a new JSON object: %m\n"); + ERROR(self->ctx, "Could not allocate a new JSON object: %m\n"); r = 1; goto ERROR; } @@ -2118,14 +2071,14 @@ int pakfire_repo_write_metadata(struct pakfire_repo* repo, struct pakfire_key* k // Set version struct json_object* repomd_version = json_object_new_int64(0); if (!repomd_version) { - ERROR(repo->ctx, "Could not create version: %m\n"); + ERROR(self->ctx, "Could not create version: %m\n"); r = 1; goto ERROR; } r = json_object_object_add(repomd, "version", repomd_version); if (r) { - ERROR(repo->ctx, "Could not add version to repomd.json: %m\n"); + ERROR(self->ctx, "Could not add version to repomd.json: %m\n"); goto ERROR; } @@ -2134,61 +2087,73 @@ int pakfire_repo_write_metadata(struct pakfire_repo* repo, struct pakfire_key* k // Set revision struct json_object* repomd_revision = json_object_new_int64(revision); if (!repomd_revision) { - ERROR(repo->ctx, "Could not create revision: %m\n"); + ERROR(self->ctx, "Could not create revision: %m\n"); r = 1; goto ERROR; } r = json_object_object_add(repomd, "revision", repomd_revision); if (r) { - ERROR(repo->ctx, "Could not add revision to repomd.json: %m\n"); + ERROR(self->ctx, "Could not add revision to repomd.json: %m\n"); goto ERROR; } // Set database struct json_object* repomd_database = json_object_new_string(database); if (!repomd_database) { - ERROR(repo->ctx, "Could not create database string: %m\n"); + ERROR(self->ctx, "Could not create database string: %m\n"); r = 1; goto ERROR; } r = json_object_object_add(repomd, "database", repomd_database); if (r) { - ERROR(repo->ctx, "Could not add database to repomd.json: %m\n"); + ERROR(self->ctx, "Could not add database to repomd.json: %m\n"); goto ERROR; } // XXX database hash is missing - char repomd_path[PATH_MAX]; - - // Make path to repomd.json - r = pakfire_string_format(repomd_path, "%s/repodata/repomd.json", path); - if (r) - goto ERROR; - // Open repomd.json for writing - f = fopen(repomd_path, "w"); + f = fopen(repomd_path, "w+"); if (!f) { - ERROR(repo->ctx, "Could not open %s for writing: %m\n", repomd_path); - r = 1; + ERROR(self->ctx, "Could not open %s for writing: %m\n", repomd_path); + r = -errno; goto ERROR; } // Write out repomd.json r = json_object_to_fd(fileno(f), repomd, JSON_C_TO_STRING_PRETTY); if (r) { - ERROR(repo->ctx, "Could not write repomd.json: %m\n"); + ERROR(self->ctx, "Could not write repomd.json: %m\n"); goto ERROR; } + // Open the signature path for writing + s = fopen(sigpath, "w"); + if (!s) { + ERROR(self->ctx, "Could not open %s for writing: %m\n", sigpath); + r = -errno; + goto ERROR; + } + + // Sign the metadata + if (key) { + r = pakfire_key_sign(key, s, f, NULL); + if (r < 0) { + ERROR(self->ctx, "Could not sign the repository: %s\n", strerror(-r)); + goto ERROR; + } + } + // Success r = 0; ERROR: if (f) fclose(f); + if (s) + fclose(s); json_object_put(repomd); return r; -- 2.39.5