From: Michael Tremer Date: Fri, 9 Jul 2021 09:50:47 +0000 (+0000) Subject: key: Refactor importing keys X-Git-Tag: 0.9.28~1069 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a2bc504ce5d598dc19c088f0e8be801cf31d575;p=pakfire.git key: Refactor importing keys Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/pakfire.c b/src/_pakfire/pakfire.c index 8e476b45c..9cdf190f4 100644 --- a/src/_pakfire/pakfire.c +++ b/src/_pakfire/pakfire.c @@ -472,15 +472,33 @@ static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args, PyObj } static PyObject* Pakfire_import_key(PakfireObject* self, PyObject* args) { - const char* data = NULL; + PyObject* object = NULL; - if (!PyArg_ParseTuple(args, "s", &data)) + if (!PyArg_ParseTuple(args, "O", &object)) return NULL; - struct pakfire_key** keys = pakfire_key_import(self->pakfire, data); - if (!keys) - return NULL; // TODO Raise error from errno + // Get a file descriptor from object + int fd = PyObject_AsFileDescriptor(object); + if (fd < 0) + return NULL; + + // Convert to FILE* + FILE* f = fdopen(fd, "r"); + if (!f) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + struct pakfire_key** keys = NULL; + // Import keys from f + int r = pakfire_key_import(self->pakfire, f, &keys); + if (r) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + +#warning THIS LEAKS MEMORY return _import_keylist(self, keys); } diff --git a/src/libpakfire/include/pakfire/key.h b/src/libpakfire/include/pakfire/key.h index ccfa151db..4e96e2bf1 100644 --- a/src/libpakfire/include/pakfire/key.h +++ b/src/libpakfire/include/pakfire/key.h @@ -55,7 +55,7 @@ int pakfire_key_is_revoked(struct pakfire_key* key); int pakfire_key_generate(struct pakfire_key** key, Pakfire pakfire, const char* algo, const char* userid); char* pakfire_key_export(struct pakfire_key* key, pakfire_key_export_mode_t mode); -struct pakfire_key** pakfire_key_import(Pakfire pakfire, const char* data); +int pakfire_key_import(Pakfire pakfire, FILE* f, struct pakfire_key*** keys); char* pakfire_key_dump(struct pakfire_key* key); diff --git a/src/libpakfire/key.c b/src/libpakfire/key.c index 20047f070..3196fdbb5 100644 --- a/src/libpakfire/key.c +++ b/src/libpakfire/key.c @@ -433,60 +433,70 @@ FAIL: return NULL; } -PAKFIRE_EXPORT struct pakfire_key** pakfire_key_import(Pakfire pakfire, const char* data) { - gpgme_error_t error; - gpgme_data_t keydata; +PAKFIRE_EXPORT int pakfire_key_import(Pakfire pakfire, FILE* f, + struct pakfire_key*** keys) { + gpgme_data_t data; + int r = 1; + + if (!f) { + errno = EINVAL; + return 1; + } + + // Reset keys + if (keys) + *keys = NULL; + // Fetch GPGME context gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pakfire); + if (!gpgctx) + return 1; - // Form a data object out of the input without copying data - error = gpgme_data_new_from_mem(&keydata, data, strlen(data), 0); - if (error != GPG_ERR_NO_ERROR) - goto FAIL; + // Import key data + gpgme_error_t e = gpgme_data_new_from_stream(&data, f); + if (gpg_error(e) != GPG_ERR_NO_ERROR) + goto ERROR; + + gpgme_import_result_t result = NULL; // Try importing the key(s) - error = gpgme_op_import(gpgctx, keydata); + e = gpgme_op_import(gpgctx, data); - gpgme_import_result_t result; - switch (error) { + switch (gpg_error(e)) { // Everything went fine case GPG_ERR_NO_ERROR: result = gpgme_op_import_result(gpgctx); - DEBUG(pakfire, "Keys considered = %d\n", result->considered); - DEBUG(pakfire, "Keys imported = %d\n", result->imported); - DEBUG(pakfire, "Keys not imported = %d\n", result->not_imported); - // Did we import any keys? gpgme_import_status_t status = result->imports; - if (!status) - return NULL; + if (!status) { + errno = ENOENT; + goto ERROR; + } - struct pakfire_key** head = calloc(result->imported + 1, sizeof(*head)); - struct pakfire_key** list = head; + DEBUG(pakfire, "Keys considered = %d\n", result->considered); + DEBUG(pakfire, "Keys imported = %d\n", result->imported); + DEBUG(pakfire, "Keys not imported = %d\n", result->not_imported); - // Retrieve all imported keys - struct pakfire_key* key; - while (status) { - int r = pakfire_find_key(&key, pakfire, status->fpr); - if (r) - goto FAIL; + if (keys) { + // Allocate array + *keys = calloc(result->imported + 1, sizeof(**keys)); + if (!*keys) + goto ERROR; - const char* fingerprint = pakfire_key_get_fingerprint(key); - INFO(pakfire, "Imported key %s\n", fingerprint); + // Retrieve all imported keys - // Append key to list - *list++ = key; + struct pakfire_key* key; + for (int i = 0; i < result->imported && status; i++, status = status->next) { + r = pakfire_find_key(&key, pakfire, status->fpr); + if (r) + goto ERROR; - status = status->next; + // Append to array + (*keys)[i] = key; + } } - - // Terminate list - *list = NULL; - - gpgme_data_release(keydata); - - return head; + break; // Input was invalid case GPG_ERR_INV_VALUE: @@ -495,14 +505,26 @@ PAKFIRE_EXPORT struct pakfire_key** pakfire_key_import(Pakfire pakfire, const ch // Fall through for any other errors default: - ERROR(pakfire, "Failed with gpgme error: %s\n", gpgme_strerror(error)); + ERROR(pakfire, "Failed with gpgme error: %s\n", gpgme_strerror(e)); break; } -FAIL: - gpgme_data_release(keydata); + // Success + r = 0; - return NULL; +ERROR: + gpgme_data_release(data); + + // Free keys on error + if (r && keys && *keys) { + for (struct pakfire_key** key = *keys; *key; key++) + pakfire_key_unref(*key); + free(*keys); + + *keys = NULL; + } + + return r; } PAKFIRE_EXPORT char* pakfire_key_dump(struct pakfire_key* key) { diff --git a/src/scripts/pakfire.in b/src/scripts/pakfire.in index 74bf21ccb..f52ce27e1 100644 --- a/src/scripts/pakfire.in +++ b/src/scripts/pakfire.in @@ -137,6 +137,13 @@ class Cli(object): help=_("Algorithm to use for this key")) key_generate.set_defaults(func=self._key_generate) + # import + key_import = key_subparsers.add_parser("import", + help=_("Import a key from file")) + key_import.add_argument("file", nargs="+", type=argparse.FileType("r"), + help=_("File of that key to import")) + key_import.set_defaults(func=self._key_import) + # key list key_list = key_subparsers.add_parser("list", help=_("List all imported keys")) @@ -315,6 +322,13 @@ class Cli(object): # Print the generated key print(key) + def _key_import(self, p, args): + for file in args.file: + keys = p.import_key(file) + + for key in keys: + print(key) + def _key_list(self, p, args): for key in p.keys: print(key)