]> git.ipfire.org Git - pakfire.git/commitdiff
repos: Implement creating a detached signature for databases
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 15:53:02 +0000 (15:53 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 15:53:02 +0000 (15:53 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/pakfire.c
src/libpakfire/include/pakfire/key.h
src/libpakfire/include/pakfire/repo.h
src/libpakfire/key.c
src/libpakfire/repo.c
tests/libpakfire/repo.c

index f41ccaec2483450fec16dc052a5a930fbdbe0ecd..8154a59cd05ea89d483aa53ccc6ee3e6d04a0ae6 100644 (file)
@@ -1403,13 +1403,14 @@ static PyObject* Pakfire_open(PakfireObject* self, PyObject* args) {
 }
 
 static PyObject* Pakfire_repo_compose(PakfireObject* self, PyObject* args, PyObject* kwargs) {
-       char* kwlist[] = { "path", "files", NULL };
+       char* kwlist[] = { "path", "files", "key", NULL };
        const char* path = NULL;
        PyObject* list = NULL;
+       KeyObject* key = NULL;
 
        PyObject* ret = NULL;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO", kwlist, &path, &list))
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|O!", kwlist, &path, &list, &KeyType, &key))
                return NULL;
 
        // List must be a sequence
@@ -1451,7 +1452,7 @@ static PyObject* Pakfire_repo_compose(PakfireObject* self, PyObject* args, PyObj
 
        Py_BEGIN_ALLOW_THREADS
 
-       int r = pakfire_repo_compose(self->pakfire, path, files);
+       int r = pakfire_repo_compose(self->pakfire, path, (key) ? key->key : NULL, files);
        if (r) {
                Py_BLOCK_THREADS
                PyErr_SetFromErrno(PyExc_OSError);
index ecc6c98bd91014ae4fb121b1e05b56bbd506bb6c..286e35637feb248e8ed26e0c4a279b45b4219061 100644 (file)
@@ -60,6 +60,7 @@ int pakfire_key_import_from_string(struct pakfire_key** key,
 
 int pakfire_key_sign(struct pakfire_key* key,
        FILE* f, const void* data, const size_t length, const char* comment);
+int pakfire_key_signf(struct pakfire_key* key, FILE* s, FILE* f, const char* comment);
 int pakfire_key_verify(struct pakfire_key* key,
        FILE* f, const void* data, const size_t length);
 
index 44096f9fd19cb24fd73ddca7e4041cc5c7d2b409..982e51ca428815e783f321278ece4cb0cff80f3e 100644 (file)
@@ -90,7 +90,7 @@ int pakfire_repo_refresh(struct pakfire_repo* repo, int force);
 // Compose
 
 int pakfire_repo_compose(struct pakfire* pakfire, const char* path,
-       const char** files);
+       struct pakfire_key* key, const char** files);
 
 #ifdef PAKFIRE_PRIVATE
 
index 803045637386e5bca58742436b11118e3312c674..d78b2ca36527ce315b43c6ee017b1a7ebcd30603 100644 (file)
@@ -871,6 +871,26 @@ ERROR:
        return r;
 }
 
+int pakfire_key_signf(struct pakfire_key* key, FILE* s, FILE* f, const char* comment) {
+       char* buffer = NULL;
+       size_t length = 0;
+       int r;
+
+       // Load the entire content into memory
+       r = pakfire_read_file_into_buffer(f, &buffer, &length);
+       if (r)
+               goto ERROR;
+
+       // Sign!
+       r = pakfire_key_sign(key, s, buffer, length, comment);
+
+ERROR:
+       if (buffer)
+               free(buffer);
+
+       return r;
+}
+
 static int pakfire_key_read_signature(struct pakfire_key* key,
                struct pakfire_key_signature* signature, FILE* f) {
        void* buffer = NULL;
index f9c099a6df228b5ce547f6470bc16b0ee299212e..1055ce180bb477dcf6274e1e0f9b201d5dc46aef 100644 (file)
@@ -1439,7 +1439,51 @@ ERROR:
        return r;
 }
 
-static int pakfire_repo_write_metadata(struct pakfire_repo* repo) {
+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->pakfire, "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->pakfire, "Could not open %s for reading: %m\n", database_path);
+               r = 1;
+               goto ERROR;
+       }
+
+       // Create the signature
+       r = pakfire_key_signf(key, s, f, "Database Signature");
+       if (r) {
+               ERROR(repo->pakfire, "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_metadata(struct pakfire_repo* repo, struct pakfire_key* key) {
        struct json_object* repomd = NULL;
        FILE* f = NULL;
        int r = 1;
@@ -1462,6 +1506,15 @@ static int pakfire_repo_write_metadata(struct pakfire_repo* repo) {
        if (r)
                return r;
 
+       // Sign the database
+       if (key) {
+               r = pakfire_repo_sign_database(repo, key, database);
+               if (r) {
+                       ERROR(repo->pakfire, "Could not sign the database: %m\n");
+                       goto ERROR;
+               }
+       }
+
        // Compose JSON object
        repomd = json_object_new_object();
        if (!repomd) {
@@ -1550,7 +1603,7 @@ ERROR:
 }
 
 PAKFIRE_EXPORT int pakfire_repo_compose(struct pakfire* pakfire, const char* path,
-               const char** files) {
+               struct pakfire_key* key, const char** files) {
        struct pakfire_repo* repo = NULL;
        char realpath[PATH_MAX];
        char baseurl[PATH_MAX];
@@ -1562,6 +1615,8 @@ PAKFIRE_EXPORT int pakfire_repo_compose(struct pakfire* pakfire, const char* pat
                return 1;
        }
 
+       // XXX Check if the key is a secret key
+
        size_t num_files = 0;
 
        // Count files
@@ -1662,7 +1717,7 @@ OUT:
        }
 
        // Write metadata to disk
-       r = pakfire_repo_write_metadata(repo);
+       r = pakfire_repo_write_metadata(repo, key);
        if (r)
                goto ERROR;
 
index 7bd32d7d91771af78e7f9c94c88adad42fc84fdc..1b692807614de60f08666c5b548ce8555bae2d79 100644 (file)
@@ -90,7 +90,7 @@ static int test_compose(const struct test* t) {
 
        // Compose the repository
        ASSERT_SUCCESS(
-               pakfire_repo_compose(t->pakfire, path, files)
+               pakfire_repo_compose(t->pakfire, path, NULL, files)
        );
 
        // Everything passed