]> git.ipfire.org Git - people/ms/pakfire.git/commitdiff
key: Refactor importing keys
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 9 Jul 2021 09:50:47 +0000 (09:50 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 9 Jul 2021 09:50:47 +0000 (09:50 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/pakfire.c
src/libpakfire/include/pakfire/key.h
src/libpakfire/key.c
src/scripts/pakfire.in

index 8e476b45ca63e6fc8101c58bad18e6ddc5c814ea..9cdf190f493c88c68fabedc3331cd7e913a5bac8 100644 (file)
@@ -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);
 }
 
index ccfa151dbe432e640f0faafd5afc7a12917b29ad..4e96e2bf1dc664ce811dcbe8dfb787d298f3e26e 100644 (file)
@@ -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);
 
index 20047f070a33050987fc3a973e573bbfdf7bcdad..3196fdbb59114c1e9f663d3a35b550f15a57aab8 100644 (file)
@@ -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) {
index 74bf21ccb3867db98c977ace25ddc8a643b7bc11..f52ce27e1a3c99a2daf78f6715e8584982841180 100644 (file)
@@ -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)