]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: Support importing keys
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 23 Nov 2017 18:45:52 +0000 (19:45 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 23 Nov 2017 18:45:52 +0000 (19:45 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/key.c
src/_pakfire/pakfire.c
src/libpakfire/include/pakfire/errno.h
src/libpakfire/include/pakfire/key.h
src/libpakfire/key.c
src/libpakfire/libpakfire.sym
src/pakfire/cli.py

index 5486e487cf71be1ec14e4bf6ae0bd4e8cc2a3f5b..110e63edb465e30e4bf15c5caf124e51e668156c 100644 (file)
@@ -37,7 +37,7 @@ static PyObject* Key_new_core(PyTypeObject* type, PakfireObject* pakfire, Pakfir
 }
 
 PyObject* new_key(PakfireObject* pakfire, PakfireKey key) {
-       return Key_new_core(&KeyType, pakfire, key);
+       return Key_new_core(&KeyType, pakfire, pakfire_key_ref(key));
 }
 
 static PyObject* Key_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
@@ -46,7 +46,7 @@ static PyObject* Key_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
 
 static void Key_dealloc(KeyObject* self) {
        if (self->key)
-               pakfire_key_free(self->key);
+               pakfire_key_unref(self->key);
 
        if (self->pakfire)
                Py_DECREF(self->pakfire);
index 6449e6b4f89294793c7a5bda513e967ee26fde00..2b45a07990556325d434437860693f2753588d4f 100644 (file)
@@ -75,23 +75,31 @@ static PyObject* Pakfire_get_arch(PakfireObject* self) {
     return PyUnicode_FromString(arch);
 }
 
-static PyObject* Pakfire_get_keys(PakfireObject* self) {
+static PyObject* _import_keylist(PakfireObject* pakfire, PakfireKey* keys) {
        PyObject* list = PyList_New(0);
 
-       PakfireKey* keys = pakfire_key_list(self->pakfire);
        while (keys && *keys) {
                PakfireKey key = *keys++;
 
-               PyObject* object = new_key(self, key);
+               PyObject* object = new_key(pakfire, key);
                PyList_Append(list, object);
+
+               // Drop reference to the Python object
                Py_DECREF(object);
 
-               pakfire_key_free(key);
+               // Drop reference to the key object
+               pakfire_key_unref(key);
        }
 
        return list;
 }
 
+static PyObject* Pakfire_get_keys(PakfireObject* self) {
+       PakfireKey* keys = pakfire_key_list(self->pakfire);
+
+       return _import_keylist(self, keys);
+}
+
 static PyObject* Pakfire_get_key(PakfireObject* self, PyObject* args) {
        const char* pattern = NULL;
 
@@ -117,6 +125,19 @@ static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args) {
        return new_key(self, key);
 }
 
+static PyObject* Pakfire_import_key(PakfireObject* self, PyObject* args) {
+       const char* data = NULL;
+
+       if (!PyArg_ParseTuple(args, "s", &data))
+               return NULL;
+
+       PakfireKey* keys = pakfire_key_import(self->pakfire, data);
+       if (!keys)
+               return NULL; // TODO Raise error from errno
+
+       return _import_keylist(self, keys);
+}
+
 static struct PyMethodDef Pakfire_methods[] = {
        {
                "generate_key",
@@ -130,6 +151,12 @@ static struct PyMethodDef Pakfire_methods[] = {
                METH_VARARGS,
                NULL
        },
+       {
+               "import_key",
+               (PyCFunction)Pakfire_import_key,
+               METH_VARARGS,
+               NULL
+       },
        { NULL },
 };
 
index dbb5ce71463409cf2994b86dfdb65a9deb0d159a..f112d81291d6406427b76599093f7e002125272d 100644 (file)
@@ -33,6 +33,7 @@ enum _pakfire_errors {
        PAKFIRE_E_SOLV_NOT_SOLV,                                // SOLV file in not in SOLV format
        PAKFIRE_E_SOLV_UNSUPPORTED,                             // SOLV file is in an unsupported format
        PAKFIRE_E_SOLV_CORRUPTED,                               // SOLV file is corrupted
+       PAKFIRE_E_INVALID_INPUT,
 };
 
 extern __thread int pakfire_errno;
index 47be3866da7f773e193d80432f1607d51b7ad444..27073cee9a78a10073eed0d2b693b56190b9f48e 100644 (file)
@@ -33,12 +33,14 @@ typedef enum pakfire_key_export_mode {
 PakfireKey* pakfire_key_list(Pakfire pakfire);
 
 PakfireKey pakfire_key_create(Pakfire pakfire, gpgme_key_t gpgkey);
-void pakfire_key_free(PakfireKey key);
+PakfireKey pakfire_key_ref(PakfireKey key);
+void pakfire_key_unref(PakfireKey key);
 
 PakfireKey pakfire_key_get(Pakfire pakfire, const char* fingerprint);
 const char* pakfire_key_get_fingerprint(PakfireKey key);
 PakfireKey pakfire_key_generate(Pakfire pakfire, const char* userid);
 char* pakfire_key_export(PakfireKey key, pakfire_key_export_mode_t mode);
+PakfireKey* pakfire_key_import(Pakfire pakfire, const char* data);
 
 #ifdef PAKFIRE_PRIVATE
 
index f0d6d8e530c2685ffe4ba685f5969718fcfed08e..7c42a360c200e7700a6a9ddb18262170df5050fc 100644 (file)
@@ -20,7 +20,9 @@
 
 #include <assert.h>
 #include <gpgme.h>
+#include <string.h>
 
+#include <pakfire/errno.h>
 #include <pakfire/key.h>
 #include <pakfire/pakfire.h>
 #include <pakfire/util.h>
@@ -112,6 +114,7 @@ PakfireKey pakfire_key_create(Pakfire pakfire, gpgme_key_t gpgkey) {
        PakfireKey key = pakfire_calloc(1, sizeof(*key));
 
        if (key) {
+               key->nrefs = 1;
                key->pakfire = pakfire_ref(pakfire);
 
                key->gpgkey = gpgkey;
@@ -121,13 +124,26 @@ PakfireKey pakfire_key_create(Pakfire pakfire, gpgme_key_t gpgkey) {
        return key;
 }
 
-void pakfire_key_free(PakfireKey key) {
+static void pakfire_key_free(PakfireKey key) {
        pakfire_unref(key->pakfire);
        gpgme_key_unref(key->gpgkey);
 
        pakfire_free(key);
 }
 
+PakfireKey pakfire_key_ref(PakfireKey key) {
+       ++key->nrefs;
+
+       return key;
+}
+
+void pakfire_key_unref(PakfireKey key) {
+       if (--key->nrefs > 0)
+               return;
+
+       pakfire_key_free(key);
+}
+
 PakfireKey pakfire_key_get(Pakfire pakfire, const char* fingerprint) {
        gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pakfire);
        assert(gpgctx);
@@ -231,3 +247,64 @@ FAIL:
 
        return NULL;
 }
+
+PakfireKey* pakfire_key_import(Pakfire pakfire, const char* data) {
+       gpgme_error_t error;
+       gpgme_data_t keydata;
+
+       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pakfire);
+       assert(gpgctx);
+
+       // 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;
+
+       // Try importing the key(s)
+       error = gpgme_op_import(gpgctx, keydata);
+
+       gpgme_import_result_t result;
+       switch (error) {
+               // Everything went fine
+               case GPG_ERR_NO_ERROR:
+                       result = gpgme_op_import_result(gpgctx);
+
+                       PakfireKey* head = pakfire_calloc(result->imported + 1, sizeof(*head));
+                       PakfireKey* list = head;
+
+                       // Retrieve all imported keys
+                       gpgme_import_status_t status = result->imports;
+                       while (status) {
+                               PakfireKey key = pakfire_key_get(pakfire, status->fpr);
+                               if (key) {
+                                       // Append key to list
+                                       *list++ = key;
+                               }
+
+                               status = status->next;
+                       }
+
+                       // Terminate list
+                       *list = NULL;
+
+                       gpgme_data_release(keydata);
+                       gpgme_release(gpgctx);
+
+                       return head;
+
+               // Input was invalid
+               case GPG_ERR_INV_VALUE:
+                       pakfire_errno = PAKFIRE_E_INVALID_INPUT;
+                       break;
+
+               // Fall through for any other errors
+               default:
+                       break;
+       }
+
+FAIL:
+       gpgme_data_release(keydata);
+       gpgme_release(gpgctx);
+
+       return NULL;
+}
index abd0487238e0e096d3e25a07bd49bec92080c51f..bea1d07e713fea56d55c49751aee4447f64b4a2a 100644 (file)
@@ -72,11 +72,13 @@ global:
        # key
        pakfire_key_create;
        pakfire_key_export;
-       pakfire_key_free;
        pakfire_key_generate;
        pakfire_key_get;
        pakfire_key_get_fingerprint;
+       pakfire_key_import;
        pakfire_key_list;
+       pakfire_key_ref;
+       pakfire_key_unref;
 
        # package
        pakfire_package_add_conflicts;
index caa124606bb3257a50c1f195f6e5ef1c52b57091..9f8115f40ddb0d599b4272c0277ad6d943b07ec3 100644 (file)
@@ -775,6 +775,20 @@ class CliKey(Cli):
                # Add common arguments
                self._add_common_arguments(parser)
 
+               # export
+               export = subparsers.add_parser("export", help=_("Export a key to a file"))
+               export.add_argument("fingerprint", nargs=1,
+                       help=_("The fingerprint of the key to export"))
+               export.add_argument("--filename", nargs="*", help=_("Write the key to this file"))
+               export.add_argument("--secret", action="store_true",
+                       help=_("Export the secret key"))
+               export.set_defaults(func=self.handle_export)
+
+               # import 
+               _import = subparsers.add_parser("import", help=_("Import a key from file"))
+               _import.add_argument("filename", nargs="+", help=_("Filename of that key to import"))
+               _import.set_defaults(func=self.handle_import)
+
                # generate
                generate = subparsers.add_parser("generate", help=_("Import a key from file"))
                generate.add_argument("--realname", nargs=1,
@@ -787,35 +801,8 @@ class CliKey(Cli):
                list = subparsers.add_parser("list", help=_("List all imported keys"))
                list.set_defaults(func=self.handle_list)
 
-               # export
-               export = subparsers.add_parser("export", help=_("Export a key to a file"))
-               export.add_argument("fingerprint", nargs=1,
-                       help=_("The fingerprint of the key to export"))
-               export.add_argument("--filename", nargs="*", help=_("Write the key to this file"))
-               export.add_argument("--secret", action="store_true",
-                       help=_("Export the secret key"))
-               export.set_defaults(func=self.handle_export)
-
                return parser.parse_args()
 
-       def parse_command_generate(self):
-               # Parse "generate" command.
-               sub_gen = self.sub_commands.add_parser("generate",
-                       help=_("Import a key from file."))
-               sub_gen.add_argument("--realname", nargs=1,
-                       help=_("The real name of the owner of this key."))
-               sub_gen.add_argument("--email", nargs=1,
-                       help=_("The email address of the owner of this key."))
-               sub_gen.set_defaults(func=self.handle_generate)
-
-       def parse_command_import(self):
-               # Parse "import" command.
-               sub_import = self.sub_commands.add_parser("import",
-                       help=_("Import a key from file."))
-               sub_import.add_argument("filename", nargs=1,
-                       help=_("Filename of that key to import."))
-               sub_import.add_argument("action", action="store_const", const="import")
-
        def parse_command_delete(self):
                # Parse "delete" command.
                sub_del = self.sub_commands.add_parser("delete",
@@ -875,12 +862,15 @@ class CliKey(Cli):
                        else:
                                print(data)
 
-       def handle_import(self):
-               filename = self.args.filename[0]
+       def handle_import(self, ns):
+               p = self.pakfire(ns)
 
-               # Simply import the file.
-               p = self.create_pakfire()
-               p.keyring.import_key(filename)
+               for filename in ns.filename:
+                       with open(filename) as f:
+                               data = f.read()
+
+                               key = p.import_key(data)
+                               print(key)
 
        def handle_delete(self):
                keyid = self.args.keyid[0]