From: Michael Tremer Date: Fri, 9 Jul 2021 10:12:58 +0000 (+0000) Subject: key: Refactor exporting keys X-Git-Tag: 0.9.28~1068 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4e6b878c31cee2b8ce678647abca2943783f98d2;p=pakfire.git key: Refactor exporting keys Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/key.c b/src/_pakfire/key.c index a5e561865..b5b3286f4 100644 --- a/src/_pakfire/key.c +++ b/src/_pakfire/key.c @@ -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) { diff --git a/src/libpakfire/include/pakfire/key.h b/src/libpakfire/include/pakfire/key.h index 4e96e2bf1..533036d65 100644 --- a/src/libpakfire/include/pakfire/key.h +++ b/src/libpakfire/include/pakfire/key.h @@ -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); diff --git a/src/libpakfire/key.c b/src/libpakfire/key.c index 3196fdbb5..963671684 100644 --- a/src/libpakfire/key.c +++ b/src/libpakfire/key.c @@ -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, diff --git a/src/scripts/pakfire.in b/src/scripts/pakfire.in index f52ce27e1..1cacb5208 100644 --- a/src/scripts/pakfire.in +++ b/src/scripts/pakfire.in @@ -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)