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

index a5e5618650629a67e6a0ecf5b560d66d374cd9ed..b5b3286f4d68ce7d139715ea75978ef08070f61c 100644 (file)
@@ -86,11 +86,24 @@ static PyObject* Key_get_fingerprint(KeyObject* self) {
 }
 
 static PyObject* Key_export(KeyObject* self, PyObject* args) {
+       PyObject* file = NULL;
        int secret = 0;
 
-       if (!PyArg_ParseTuple(args, "|p", &secret))
+       if (!PyArg_ParseTuple(args, "O|p", &file, &secret))
                return NULL;
 
+       // Get a file descriptor
+       int fd = PyObject_AsFileDescriptor(file);
+       if (fd < 0)
+               return NULL;
+
+       // Convert to FILE*
+       FILE* f = fdopen(fd, "w");
+       if (!f) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
+
        pakfire_key_export_mode_t mode;
        if (secret)
                mode = PAKFIRE_KEY_EXPORT_MODE_SECRET;
@@ -98,12 +111,13 @@ static PyObject* Key_export(KeyObject* self, PyObject* args) {
                mode = PAKFIRE_KEY_EXPORT_MODE_PUBLIC;
 
        // Export the key
-       char* export = pakfire_key_export(self->key, mode);
-
-       PyObject* object = PyUnicode_FromFormat("%s", export);
-       free(export);
+       int r = pakfire_key_export(self->key, f, mode);
+       if (r) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
 
-       return object;
+       Py_RETURN_NONE;
 }
 
 static PyObject* Key_delete(KeyObject* self) {
index 4e96e2bf1dc664ce811dcbe8dfb787d298f3e26e..533036d659a9385dc67db20de3d7eb0134bbefba 100644 (file)
@@ -54,7 +54,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);
+int pakfire_key_export(struct pakfire_key* key, FILE* f, pakfire_key_export_mode_t mode);
 int pakfire_key_import(Pakfire pakfire, FILE* f, struct pakfire_key*** keys);
 
 char* pakfire_key_dump(struct pakfire_key* key);
index 3196fdbb59114c1e9f663d3a35b550f15a57aab8..963671684750ca44f7245ada3eefd8bf785da3bf 100644 (file)
@@ -381,8 +381,16 @@ PAKFIRE_EXPORT int pakfire_key_generate(struct pakfire_key** key, Pakfire pakfir
        return pakfire_find_key(key, pakfire, result->fpr);
 }
 
-PAKFIRE_EXPORT char* pakfire_key_export(struct pakfire_key* key, pakfire_key_export_mode_t mode) {
+PAKFIRE_EXPORT int pakfire_key_export(struct pakfire_key* key, FILE* f,
+               pakfire_key_export_mode_t mode) {
+       if (!f) {
+               errno = EINVAL;
+               return 1;
+       }
+
        gpgme_ctx_t gpgctx = pakfire_get_gpgctx(key->pakfire);
+       if (!gpgctx)
+               return 1;
 
        gpgme_export_mode_t gpgmode = 0;
        switch (mode) {
@@ -396,41 +404,53 @@ PAKFIRE_EXPORT char* pakfire_key_export(struct pakfire_key* key, pakfire_key_exp
 
        const char* fingerprint = pakfire_key_get_fingerprint(key);
 
+       gpgme_data_t data = NULL;
+       char* buffer = NULL;
+       int r = 1;
+
        // Initialize the buffer
-       gpgme_data_t keydata;
-       gpgme_error_t error = gpgme_data_new(&keydata);
-       if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
-               goto FAIL;
+       gpgme_error_t e = gpgme_data_new(&data);
+       if (gpg_err_code(e) != GPG_ERR_NO_ERROR)
+               goto ERROR;
 
        // Encode output as ASCII
-       error = gpgme_data_set_encoding(keydata, GPGME_DATA_ENCODING_ARMOR);
-       if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
-               goto FAIL;
+       e = gpgme_data_set_encoding(data, GPGME_DATA_ENCODING_ARMOR);
+       if (gpg_err_code(e) != GPG_ERR_NO_ERROR)
+               goto ERROR;
 
        // Copy the key to the buffer
-       error = gpgme_op_export(gpgctx, fingerprint, gpgmode, keydata);
-       if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
-               goto FAIL;
+       e = gpgme_op_export(gpgctx, fingerprint, gpgmode, data);
+       if (gpg_err_code(e) != GPG_ERR_NO_ERROR)
+               goto ERROR;
+
+       size_t size;
 
-       // Export key in ASCII format
-       size_t length;
-       char* mem = gpgme_data_release_and_get_mem(keydata, &length);
+       // Fetch data from buffer
+       buffer = gpgme_data_release_and_get_mem(data, &size);
 
-       // Terminate the string
-       mem[length] = '\0';
+       // Reset data
+       data = NULL;
 
-       // Copy to our own string buffer
-       char* buffer = strdup(mem);
+       // Write key to file
+       size_t bytes_written = fwrite(buffer, 1, size, f);
+       if (bytes_written < size)
+               goto ERROR;
 
-       // Release the exported key
-       gpgme_free(mem);
+       // Flush f
+       r = fflush(f);
+       if (r)
+               goto ERROR;
 
-       return buffer;
+       // Success
+       r = 0;
 
-FAIL:
-       gpgme_data_release(keydata);
+ERROR:
+       if (buffer)
+               gpgme_free(buffer);
+       if (data)
+               gpgme_data_release(data);
 
-       return NULL;
+       return r;
 }
 
 PAKFIRE_EXPORT int pakfire_key_import(Pakfire pakfire, FILE* f,
index f52ce27e1a3c99a2daf78f6715e8584982841180..1cacb52087fd0211ffc28c1a7c4ca8d804ad8339 100644 (file)
@@ -109,8 +109,8 @@ class Cli(object):
                        help=_("Export a key to a file"))
                key_export.add_argument("fingerprint",
                        help=_("The fingerprint of the key to export"))
-               key_export.add_argument("--filename", nargs="?",
-                       help=_("Write the key to this file"))
+               key_export.add_argument("--file", nargs="?", type=argparse.FileType("w"),
+                       help=_("Write the key to this file"), default=sys.stdout)
                key_export.add_argument("--secret", action="store_true",
                        help=_("Include the secret key"))
                key_export.set_defaults(func=self._key_export)
@@ -295,15 +295,8 @@ class Cli(object):
                        print(_("Could not find key with fingerprint %s") % fingerprint)
                        return
 
-               # Convert key to text
-               data = key.export(args.secret)
-
-               # Write out the key
-               if args.filename:
-                       with open(args.filename, "w") as f:
-                               f.write(data)
-               else:
-                       print(data)
+               # Export the key
+               key.export(args.file, args.secret)
 
        def _key_fetch(self, p, args):
                key = p.fetch_key(userid=args.userid, fingerprint=args.fingerprint)