From: Michael Tremer Date: Thu, 1 Jun 2023 21:16:41 +0000 (+0000) Subject: keys: Carry the comment with us and require it X-Git-Tag: 0.9.29~120 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=391eeca005e951f560a47ba32c2e193330d16b5b;p=pakfire.git keys: Carry the comment with us and require it Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/key.c b/src/_pakfire/key.c index ef4e93659..9bf6935ce 100644 --- a/src/_pakfire/key.c +++ b/src/_pakfire/key.c @@ -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, diff --git a/src/_pakfire/pakfire.c b/src/_pakfire/pakfire.c index d40e0d5df..a37c80c0f 100644 --- a/src/_pakfire/pakfire.c +++ b/src/_pakfire/pakfire.c @@ -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; diff --git a/src/libpakfire/include/pakfire/key.h b/src/libpakfire/include/pakfire/key.h index 5ccc01c43..22f24c2f7 100644 --- a/src/libpakfire/include/pakfire/key.h +++ b/src/libpakfire/include/pakfire/key.h @@ -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); diff --git a/src/libpakfire/key.c b/src/libpakfire/key.c index db893e5f2..44844c989 100644 --- a/src/libpakfire/key.c +++ b/src/libpakfire/key.c @@ -41,6 +41,9 @@ #include #include +// 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) { diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index a342da8d9..0a0093b18 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -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; diff --git a/tests/libpakfire/key.c b/tests/libpakfire/key.c index 360c1df9b..d0f5f30e8 100644 --- a/tests/libpakfire/key.c +++ b/tests/libpakfire/key.c @@ -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)); diff --git a/tests/python/keys.py b/tests/python/keys.py index 4ea76b1c7..a444e8ea6 100755 --- a/tests/python/keys.py +++ b/tests/python/keys.py @@ -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"