]> git.ipfire.org Git - pakfire.git/commitdiff
keys: Carry the comment with us and require it
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 21:16:41 +0000 (21:16 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 21:16:41 +0000 (21:16 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/key.c
src/_pakfire/pakfire.c
src/libpakfire/include/pakfire/key.h
src/libpakfire/key.c
src/libpakfire/libpakfire.sym
tests/libpakfire/key.c
tests/python/keys.py

index ef4e936599127ee2944e949caeeb48d239148165..9bf6935ceed21e3d6a37c6e67650297d159fc7f9 100644 (file)
@@ -98,6 +98,14 @@ static PyObject* Key_get_algorithm(KeyObject* self) {
        return PyUnicode_FromString(algorithm);
 }
 
+static PyObject* Key_get_comment(KeyObject* self) {
+       const char* comment = pakfire_key_get_comment(self->key);
+       if (!comment)
+               Py_RETURN_NONE;
+
+       return PyUnicode_FromString(comment);
+}
+
 static PyObject* Key_export(KeyObject* self, PyObject* args) {
        pakfire_key_export_mode_t mode = PAKFIRE_KEY_EXPORT_MODE_PUBLIC;
        PyObject* object = NULL;
@@ -243,6 +251,13 @@ static struct PyGetSetDef Key_getsetters[] = {
                NULL,
                NULL,
        },
+       {
+               "comment",
+               (getter)Key_get_comment,
+               NULL,
+               NULL,
+               NULL,
+       },
        {
                "id",
                (getter)Key_get_id,
index d40e0d5dfc79c771ae74519d3d9bbaa6dc44e1df..a37c80c0f82cfb9e19d57ffe3476403145090a9d 100644 (file)
@@ -596,15 +596,16 @@ static PyObject* Pakfire_update(PakfireObject* self, PyObject* args, PyObject* k
 }
 
 static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args, PyObject* kwds) {
-       char* kwlist[] = { "algorithm", NULL };
+       char* kwlist[] = { "algorithm", "comment", NULL };
        struct pakfire_key* key = NULL;
        pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_NULL;
+       const char* comment = NULL;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &algo))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &algo, &comment))
                return NULL;
 
        // Generate a new key
-       int r = pakfire_key_generate(&key, self->pakfire, algo);
+       int r = pakfire_key_generate(&key, self->pakfire, algo, comment);
        if (r) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
index 5ccc01c4307ffcb98b3b5b6bdb3110582655e960..22f24c2f7c606c6bc599649ace36a9f630cc73bf 100644 (file)
@@ -45,9 +45,10 @@ void pakfire_key_unref(struct pakfire_key* key);
 // Access key properties
 pakfire_key_id* pakfire_key_get_id(struct pakfire_key* key);
 const char* pakfire_key_get_algo(struct pakfire_key* key);
+const char* pakfire_key_get_comment(struct pakfire_key* key);
 
 int pakfire_key_generate(struct pakfire_key** key, struct pakfire* pakfire,
-       const pakfire_key_algo_t algo);
+       const pakfire_key_algo_t algo, const char* comment);
 int pakfire_key_export(struct pakfire_key* key, FILE* f, const pakfire_key_export_mode_t mode);
 int pakfire_key_import(struct pakfire_key** key, struct pakfire* pakfire, FILE* f);
 
index db893e5f22d884120ea86935e209bab8e0eb0b9f..44844c9899085656caf4f8efa12708f8c908e4c3 100644 (file)
@@ -41,6 +41,9 @@
 #include <pakfire/string.h>
 #include <pakfire/util.h>
 
+// The maximum length of the comment
+#define COMMENT_MAX            1024
+
 // Size of the buffer to allocate for error messages
 #define ERROR_MAX              1024
 
@@ -56,6 +59,9 @@ struct pakfire_key {
 
        // The public (or private) key
        EVP_PKEY* pkey;
+
+       // Comment
+       char comment[COMMENT_MAX];
 };
 
 struct pakfire_key_public_key {
@@ -88,7 +94,9 @@ static int pakfire_key_id_equals(const pakfire_key_id* id1, const pakfire_key_id
 }
 
 static int pakfire_key_create(struct pakfire_key** key, struct pakfire* pakfire,
-               const pakfire_key_algo_t algo, const pakfire_key_id id, EVP_PKEY* pkey) {
+               const pakfire_key_algo_t algo, const pakfire_key_id id, EVP_PKEY* pkey, const char* comment) {
+       int r;
+
        if (!pkey) {
                errno = EINVAL;
                return 1;
@@ -122,6 +130,16 @@ static int pakfire_key_create(struct pakfire_key** key, struct pakfire* pakfire,
        EVP_PKEY_up_ref(pkey);
        k->pkey = pkey;
 
+       // Store the comment
+       if (comment) {
+               r = pakfire_string_set(k->comment, comment);
+               if (r)
+                       goto ERROR;
+
+               // Remove any trailing newline
+               pakfire_remove_trailing_newline(k->comment);
+       }
+
        *key = k;
        return 0;
 
@@ -169,8 +187,12 @@ PAKFIRE_EXPORT const char* pakfire_key_get_algo(struct pakfire_key* key) {
        return NULL;
 }
 
+PAKFIRE_EXPORT const char* pakfire_key_get_comment(struct pakfire_key* key) {
+       return &key->comment;
+}
+
 PAKFIRE_EXPORT int pakfire_key_generate(struct pakfire_key** key, struct pakfire* pakfire,
-               const pakfire_key_algo_t algo) {
+               const pakfire_key_algo_t algo, const char* comment) {
        EVP_PKEY* pkey = NULL;
        EVP_PKEY_CTX* pctx = NULL;
        pakfire_key_id key_id;
@@ -226,7 +248,7 @@ PAKFIRE_EXPORT int pakfire_key_generate(struct pakfire_key** key, struct pakfire
        }
 
        // Create a key object
-       r = pakfire_key_create(key, pakfire, algo, key_id, pkey);
+       r = pakfire_key_create(key, pakfire, algo, key_id, pkey, comment);
        if (r)
                goto ERROR;
 
@@ -247,7 +269,8 @@ ERROR:
 */
 
 static int pakfire_key_import_secret_key(struct pakfire_key** key,
-               struct pakfire* pakfire, const struct pakfire_key_private_key* buffer) {
+               struct pakfire* pakfire, const char* comment,
+               const struct pakfire_key_private_key* buffer) {
        const pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_ED25519;
        EVP_PKEY* pkey = NULL;
        char error[ERROR_MAX];
@@ -313,7 +336,7 @@ static int pakfire_key_import_secret_key(struct pakfire_key** key,
        }
 
        // Create a new key object
-       r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey);
+       r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey, comment);
        if (r)
                goto ERROR;
 
@@ -325,7 +348,8 @@ ERROR:
 }
 
 static int pakfire_key_import_public_key(struct pakfire_key** key,
-               struct pakfire* pakfire, const struct pakfire_key_public_key* buffer) {
+               struct pakfire* pakfire, const char* comment,
+               const struct pakfire_key_public_key* buffer) {
        const pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_ED25519;
        EVP_PKEY* pkey = NULL;
        char error[ERROR_MAX];
@@ -357,7 +381,7 @@ static int pakfire_key_import_public_key(struct pakfire_key** key,
        }
 
        // Create a new key object
-       r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey);
+       r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey, comment);
        if (r)
                goto ERROR;
 
@@ -378,40 +402,74 @@ PAKFIRE_EXPORT int pakfire_key_import(struct pakfire_key** key,
        size_t length = 0;
        size_t lineno = 0;
 
+       char comment[COMMENT_MAX];
+
        for (;;) {
                ssize_t bytes_read = getline(&line, &length, f);
                if (bytes_read < 0)
                        break;
 
-               // Decode the key
-               r = pakfire_b64decode(pakfire, &buffer, &buffer_length, line);
-               if (r) {
-                       ERROR(pakfire, "Could not decode the key: %m\n");
-                       errno = EINVAL;
-                       r = 1;
-                       goto ERROR;
-               }
+               // Increment the line counter
+               lineno++;
+
+               switch (lineno) {
+                       // The first line must start with "untrusted comment:"
+                       case 1:
+                               if (!pakfire_string_startswith(line, "untrusted comment: ")) {
+                                       ERROR(pakfire, "The first line must start with 'untrusted comment: '"
+                                               " and not %s\n", line);
+                                       errno = EINVAL;
+                                       r = 1;
+                                       goto ERROR;
+                               }
+
+                               // Copy the comment
+                               r = pakfire_string_set(comment, line + strlen("untrusted comment: "));
+                               if (r) {
+                                       ERROR(pakfire, "Could not copy comment: %m\n");
+                                       r = 1;
+                                       goto ERROR;
+                               }
 
-               // What kind of key do we have?
-               switch (buffer_length) {
-                       // Public Key
-                       case sizeof(struct pakfire_key_public_key):
-                               r = pakfire_key_import_public_key(key, pakfire,
-                                       (struct pakfire_key_public_key*)buffer);
                                break;
 
-                       // Private Key
-                       case sizeof(struct pakfire_key_private_key):
-                               r = pakfire_key_import_secret_key(key, pakfire,
-                                       (struct pakfire_key_private_key*)buffer);
+                       // The second line should hold the key
+                       case 2:
+                               // Decode the key
+                               r = pakfire_b64decode(pakfire, &buffer, &buffer_length, line);
+                               if (r) {
+                                       ERROR(pakfire, "Could not decode the key: %m\n");
+                                       errno = EINVAL;
+                                       r = 1;
+                                       goto ERROR;
+                               }
+
+                               // What kind of key do we have?
+                               switch (buffer_length) {
+                                       // Public Key
+                                       case sizeof(struct pakfire_key_public_key):
+                                               r = pakfire_key_import_public_key(key, pakfire, comment,
+                                                       (struct pakfire_key_public_key*)buffer);
+                                               break;
+
+                                       // Private Key
+                                       case sizeof(struct pakfire_key_private_key):
+                                               r = pakfire_key_import_secret_key(key, pakfire, comment,
+                                                       (struct pakfire_key_private_key*)buffer);
+                                               break;
+
+                                       // Unknown key
+                                       default:
+                                               ERROR(pakfire, "Unsupported key type\n");
+                                               errno = ENOTSUP;
+                                               r = 1;
+                                               goto ERROR;
+                               }
                                break;
 
-                       // Unknown key
+                       // Ignore any further data
                        default:
-                               ERROR(pakfire, "Unsupported key type\n");
-                               errno = ENOTSUP;
-                               r = 1;
-                               goto ERROR;
+                               break;
                }
        }
 
@@ -606,6 +664,16 @@ PAKFIRE_EXPORT int pakfire_key_export(struct pakfire_key* key, FILE* f,
        BIO* bio = NULL;
        BIO* b64 = NULL;
 
+       // Write the comment
+       if (*key->comment) {
+               r = fprintf(f, "untrusted comment: %s\n", key->comment);
+               if (r < 0) {
+                       ERROR(key->pakfire, "Could not write comment: %m\n");
+                       r = 1;
+                       goto ERROR;
+               }
+       }
+
        // Setup the base64 encoder
        b64 = BIO_new(BIO_f_base64());
        if (!b64) {
index a342da8d92b8ee84678147c92d9c2b0da3918bfb..0a0093b18968f9c75111d00a48c72973fef59e97 100644 (file)
@@ -132,6 +132,7 @@ global:
        pakfire_key_generate;
        pakfire_key_get;
        pakfire_key_get_algo;
+       pakfire_key_get_comment;
        pakfire_key_get_id;
        pakfire_key_import;
        pakfire_key_ref;
index 360c1df9ba6715679cbeead9c86d25d77796ade6..d0f5f30e823db24150167aeb2ab3e5f798c4eb2f 100644 (file)
@@ -34,10 +34,12 @@ static int test_generate(const struct test* t) {
        int r = EXIT_FAILURE;
 
        // Try to call pakfire_key_generate() with some invalid inputs
-       ASSERT_ERRNO(pakfire_key_generate(&key, t->pakfire, PAKFIRE_KEY_ALGO_NULL), EINVAL);
+       ASSERT_ERRNO(pakfire_key_generate(&key, t->pakfire,
+               PAKFIRE_KEY_ALGO_NULL, "Key 1"), EINVAL);
 
        // Generate a new key using ed25519
-       ASSERT_SUCCESS(pakfire_key_generate(&key, t->pakfire, PAKFIRE_KEY_ALGO_ED25519));
+       ASSERT_SUCCESS(pakfire_key_generate(&key, t->pakfire,
+               PAKFIRE_KEY_ALGO_ED25519, "Key 2"));
 
        // Write the public key to the console
        ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PUBLIC));
@@ -67,7 +69,8 @@ static int test_sign_and_verify(const struct test* t) {
        ASSERT(f = test_mktemp(NULL));
 
        // Generate a new key using ed25519
-       ASSERT_SUCCESS(pakfire_key_generate(&key, t->pakfire, PAKFIRE_KEY_ALGO_ED25519));
+       ASSERT_SUCCESS(pakfire_key_generate(&key, t->pakfire,
+               PAKFIRE_KEY_ALGO_ED25519, "Key 1"));
 
        // Write the public key to the console
        ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PUBLIC));
index 4ea76b1c77cd30864a422d38ea64b0309882d43c..a444e8ea6416a668927903c5accc6fab6f29d5ce 100755 (executable)
@@ -38,7 +38,8 @@ class KeysTests(unittest.TestCase):
                """
                        Generate a new key
                """
-               key = self.pakfire.generate_key(algorithm=pakfire.PAKFIRE_KEY_ALGO_ED25519)
+               key = self.pakfire.generate_key(
+                       algorithm=pakfire.PAKFIRE_KEY_ALGO_ED25519, comment="Key 1")
 
                # Check if we got the correct type
                self.assertIsInstance(key, pakfire.Key)
@@ -75,7 +76,8 @@ class KeysTests(unittest.TestCase):
                """
                        Generate a new key
                """
-               key = self.pakfire.generate_key(algorithm=pakfire.PAKFIRE_KEY_ALGO_ED25519)
+               key = self.pakfire.generate_key(
+                       algorithm=pakfire.PAKFIRE_KEY_ALGO_ED25519, key="Key 1")
 
                data = b"Pakfire"