]> git.ipfire.org Git - pakfire.git/commitdiff
repo: Load metadata into memory and verify it
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 2 Feb 2025 16:36:50 +0000 (16:36 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 2 Feb 2025 16:36:50 +0000 (16:36 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/repo.c

index 019a2d1367e52436e6aa0b96c0553907109b8ae8..2be824776a28f3146bd0d92fda313d2794f7fc6a 100644 (file)
@@ -759,7 +759,60 @@ ERROR:
        return r;
 }
 
+static int pakfire_repo_verify_metadata(
+               struct pakfire_repo* self, const struct pakfire_buffer* repomd) {
+       struct pakfire_buffer signature = {};
+       struct pakfire_xfer* xfer = NULL;
+       FILE* f = NULL;
+       int r;
+
+       // Create a new xfer
+       r = pakfire_repo_xfer_create(&xfer, self, "repomd.json.sig");
+       if (r < 0)
+               goto ERROR;
+
+       // Write the signature to a buffer
+       r = pakfire_xfer_set_output_buffer(xfer, &signature.data, &signature.length);
+       if (r < 0)
+               goto ERROR;
+
+       // Perform the transfer
+       r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
+       if (r < 0)
+               goto ERROR;
+
+       // Fail if we could not fetch any data
+       if (!signature.data) {
+               ERROR(self->ctx, "Could not fetch repository signature\n");
+               r = -ENODATA;
+               goto ERROR;
+       }
+
+       // Map the signature in a file handle
+       f = fmemopen(signature.data, signature.length, "r");
+       if (!f) {
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Verify the downloaded metadata
+       r = pakfire_key_verify(self->appdata->key, f, repomd->data, repomd->length);
+       if (r < 0)
+               goto ERROR;
+
+ERROR:
+       if (xfer)
+               pakfire_xfer_unref(xfer);
+       if (f)
+               fclose(f);
+       if (signature.data)
+               free(signature.data);
+
+       return r;
+}
+
 static int pakfire_repo_download_metadata(struct pakfire_repo* repo, const char* path, int force) {
+       struct pakfire_buffer repomd = {};
        struct pakfire_xfer* xfer = NULL;
        int r;
 
@@ -793,23 +846,32 @@ static int pakfire_repo_download_metadata(struct pakfire_repo* repo, const char*
        }
 
        // Create a new transfer
-       r = pakfire_repo_xfer_create(&xfer, repo, "repodata/repomd.json");
-       if (r)
+       r = pakfire_repo_xfer_create(&xfer, repo, "repomd.json");
+       if (r < 0)
                goto ERROR;
 
        // Set the output path
-       r = pakfire_xfer_set_output_path(xfer, path);
-       if (r)
+       r = pakfire_xfer_set_output_buffer(xfer, &repomd.data, &repomd.length);
+       if (r < 0)
                goto ERROR;
 
        // Perform the transfer
        r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
-       if (r)
+       if (r < 0)
                goto ERROR;
 
+       // Verify the downloaded data
+       if (repo->appdata->key) {
+               r = pakfire_repo_verify_metadata(repo, &repomd);
+               if (r < 0)
+                       goto ERROR;
+       }
+
 ERROR:
        if (xfer)
                pakfire_xfer_unref(xfer);
+       if (repomd.data)
+               free(repomd.data);
 
        return r;
 }