src/_pakfire/capabilities.h \
src/_pakfire/constants.h \
src/_pakfire/errors.h \
+ src/_pakfire/key.c \
+ src/_pakfire/key.h \
src/_pakfire/package.c \
src/_pakfire/package.h \
src/_pakfire/pool.c \
src/libpakfire/errno.c \
src/libpakfire/file.c \
src/libpakfire/filter.c \
+ src/libpakfire/key.c \
src/libpakfire/package.c \
src/libpakfire/packagelist.c \
src/libpakfire/pool.c \
src/libpakfire/include/pakfire/file.h \
src/libpakfire/include/pakfire/filter.h \
src/libpakfire/include/pakfire/i18n.h \
+ src/libpakfire/include/pakfire/key.h \
src/libpakfire/include/pakfire/package.h \
src/libpakfire/include/pakfire/packagecache.h \
src/libpakfire/include/pakfire/packagelist.h \
#include "capabilities.h"
#include "constants.h"
#include "errors.h"
+#include "key.h"
#include "package.h"
#include "pool.h"
#include "problem.h"
Py_INCREF(&ArchiveType);
PyModule_AddObject(module, "Archive", (PyObject *)&ArchiveType);
+ // Key
+ if (PyType_Ready(&KeyType) < 0)
+ return NULL;
+
+ Py_INCREF(&KeyType);
+ PyModule_AddObject(module, "Key", (PyObject *)&KeyType);
+
// Package
if (PyType_Ready(&PackageType) < 0)
return NULL;
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2017 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <Python.h>
+
+#include <pakfire/key.h>
+#include <pakfire/util.h>
+
+#include "key.h"
+
+static PyObject* Key_new_core(PyTypeObject* type, PoolObject* pool, PakfireKey key) {
+ KeyObject* self = (KeyObject *)type->tp_alloc(type, 0);
+ if (self) {
+ self->pool = pool;
+ self->key = key;
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject* new_key(PoolObject* pool, PakfireKey key) {
+ return Key_new_core(&KeyType, pool, key);
+}
+
+static PyObject* Key_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
+ return Key_new_core(type, NULL, NULL);
+}
+
+static void Key_dealloc(KeyObject* self) {
+ if (self->key)
+ pakfire_key_free(self->key);
+
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static int Key_init(KeyObject* self, PyObject* args, PyObject* kwds) {
+ PyObject* pool;
+ const char* fingerprint = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!s", &PoolType, &pool, &fingerprint))
+ return -1;
+
+ self->pool = (PoolObject *)pool;
+ Py_INCREF(self->pool);
+
+ self->key = pakfire_key_get(self->pool->pool, fingerprint);
+ if (!self->key)
+ return -1;
+
+ return 0;
+}
+
+static PyObject* Key_repr(KeyObject* self) {
+ const char* fingerprint = pakfire_key_get_fingerprint(self->key);
+
+ return PyUnicode_FromFormat("<_pakfire.Key (%s)>", fingerprint);
+}
+
+static PyObject* Key_str(KeyObject* self) {
+ return NULL;
+}
+
+static PyObject* Key_export(KeyObject* self, PyObject* args) {
+ int secret = 0;
+
+ if (!PyArg_ParseTuple(args, "|p", &secret))
+ return NULL;
+
+ pakfire_key_export_mode_t mode;
+ if (secret)
+ mode = PAKFIRE_KEY_EXPORT_MODE_SECRET;
+ else
+ mode = PAKFIRE_KEY_EXPORT_MODE_PUBLIC;
+
+ // Export the key
+ char* export = pakfire_key_export(self->key, mode);
+
+ PyObject* object = PyUnicode_FromFormat("%s", export);
+ pakfire_free(export);
+
+ return object;
+}
+
+static struct PyMethodDef Key_methods[] = {
+ {"export", (PyCFunction)Key_export, METH_VARARGS, NULL},
+ { NULL },
+};
+
+PyTypeObject KeyType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ tp_name: "_pakfire.Key",
+ tp_basicsize: sizeof(KeyObject),
+ tp_flags: Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ tp_new: Key_new,
+ tp_dealloc: (destructor)Key_dealloc,
+ tp_init: (initproc)Key_init,
+ tp_doc: "Key object",
+ tp_methods: Key_methods,
+ //tp_getset: Key_getsetters,
+ tp_repr: (reprfunc)Key_repr,
+ tp_str: (reprfunc)Key_str,
+};
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2017 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef PYTHON_PAKFIRE_KEY_H
+#define PYTHON_PAKFIRE_KEY_H
+
+#include <Python.h>
+
+#include <pakfire/key.h>
+
+#include "pool.h"
+
+typedef struct {
+ PyObject_HEAD
+ PoolObject* pool;
+ PakfireKey key;
+} KeyObject;
+
+extern PyTypeObject KeyType;
+
+PyObject* new_key(PoolObject* pool, PakfireKey key);
+
+#endif /* PYTHON_PAKFIRE_KEY_H */
#include <solv/solver.h>
#include <pakfire/errno.h>
+#include <pakfire/key.h>
#include <pakfire/pool.h>
#include <pakfire/repo.h>
#include "constants.h"
+#include "key.h"
#include "pool.h"
#include "relation.h"
#include "repo.h"
return PyList_FromPackageList(self, list);
}
+static PyObject* Pool_get_keys(PoolObject* self) {
+ PyObject* list = PyList_New(0);
+
+ PakfireKey* keys = pakfire_key_list(self->pool);
+ while (keys && *keys) {
+ PakfireKey key = *keys++;
+
+ PyObject* object = new_key(self, key);
+ PyList_Append(list, object);
+ Py_DECREF(object);
+
+ pakfire_key_free(key);
+ }
+
+ return list;
+}
+
+static PyObject* Pool_get_key(PoolObject* self, PyObject* args) {
+ const char* pattern = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &pattern))
+ return NULL;
+
+ PakfireKey key = pakfire_key_get(self->pool, pattern);
+ if (!key)
+ Py_RETURN_NONE;
+
+ return new_key(self, key);
+}
+
+static PyObject* Pool_generate_key(PoolObject* self, PyObject* args) {
+ const char* userid = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &userid))
+ return NULL;
+
+ PakfireKey key = pakfire_key_generate(self->pool, userid);
+ assert(key);
+
+ return new_key(self, key);
+}
+
static struct PyMethodDef Pool_methods[] = {
+ {
+ "generate_key",
+ (PyCFunction)Pool_generate_key,
+ METH_VARARGS,
+ NULL
+ },
+ {
+ "get_key",
+ (PyCFunction)Pool_get_key,
+ METH_VARARGS,
+ NULL
+ },
{
"search",
(PyCFunction)Pool_search,
NULL,
NULL
},
+ {
+ "keys",
+ (getter)Pool_get_keys,
+ NULL,
+ NULL,
+ NULL
+ },
{ NULL }
};
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2017 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef PAKFIRE_KEY_H
+#define PAKFIRE_KEY_H
+
+#include <gpgme.h>
+
+#include <pakfire/types.h>
+
+typedef enum pakfire_key_export_mode {
+ PAKFIRE_KEY_EXPORT_MODE_PUBLIC = 0,
+ PAKFIRE_KEY_EXPORT_MODE_SECRET,
+} pakfire_key_export_mode_t;
+
+PakfireKey* pakfire_key_list(PakfirePool pool);
+
+PakfireKey pakfire_key_create(PakfirePool pool, gpgme_key_t gpgkey);
+void pakfire_key_free(PakfireKey key);
+
+PakfireKey pakfire_key_get(PakfirePool pool, const char* fingerprint);
+const char* pakfire_key_get_fingerprint(PakfireKey key);
+PakfireKey pakfire_key_generate(PakfirePool pool, const char* userid);
+char* pakfire_key_export(PakfireKey key, pakfire_key_export_mode_t mode);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireKey {
+ PakfirePool pool;
+ gpgme_key_t gpgkey;
+ int nrefs;
+};
+
+#endif
+
+#endif /* PAKFIRE_KEY_H */
typedef struct _PakfireCache* PakfireCache;
typedef struct _PakfireFile* PakfireFile;
typedef struct _PakfireFilter* PakfireFilter;
+typedef struct _PakfireKey* PakfireKey;
typedef struct _PakfirePackage* PakfirePackage;
typedef struct _PakfirePackageCache* PakfirePackageCache;
typedef struct _PakfirePackageList* PakfirePackageList;
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2017 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <assert.h>
+#include <gpgme.h>
+
+#include <pakfire/key.h>
+#include <pakfire/pool.h>
+#include <pakfire/util.h>
+
+static gpgme_ctx_t pakfire_get_gpgctx(PakfirePool pool) {
+ static int gpg_initialized = 0;
+ gpgme_error_t error;
+ const char* error_string;
+
+ if (!gpg_initialized) {
+ // Initialise gpgme
+ const char* version = gpgme_check_version(NULL);
+ assert(version);
+#if 0
+ printf("version = %s\n", version);
+#endif
+
+ // Check if we support GPG
+ error = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
+ if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+ goto FAIL;
+
+ // Use GPG
+ error = gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,
+ NULL, "/etc/pakfire/gnupg");
+ if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+ goto FAIL;
+
+ gpgme_engine_info_t engine_info;
+ error = gpgme_get_engine_info(&engine_info);
+ if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+ goto FAIL;
+
+#if 0
+ printf("GPGME engine info: %s, %s\n",
+ engine_info->file_name, engine_info->home_dir);
+#endif
+
+ // GPG has been initialized
+ gpg_initialized++;
+ }
+
+ // Create a new context
+ gpgme_ctx_t ctx;
+ error = gpgme_new(&ctx);
+ if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+ goto FAIL;
+
+ // Set output to be ASCII armoured
+ gpgme_set_armor(ctx, 1);
+
+ return ctx;
+
+FAIL:
+ error_string = gpgme_strerror(error);
+ printf("ERROR: %s\n", error_string);
+
+ return NULL;
+}
+
+PakfireKey* pakfire_key_list(PakfirePool pool) {
+ gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pool);
+ assert(gpgctx);
+
+ PakfireKey* first = pakfire_calloc(1, sizeof(PakfireKey));
+ PakfireKey* list = first;
+
+ gpgme_key_t gpgkey = NULL;
+ gpgme_error_t error = gpgme_op_keylist_start(gpgctx, NULL, 0);
+ while (!error) {
+ error = gpgme_op_keylist_next(gpgctx, &gpgkey);
+ if (error)
+ break;
+
+ // Add key to the list
+ *list++ = pakfire_key_create(pool, gpgkey);
+
+ gpgme_key_release(gpgkey);
+ }
+
+ // Last list item must be NULL
+ *list = NULL;
+
+ return first;
+}
+
+PakfireKey pakfire_key_create(PakfirePool pool, gpgme_key_t gpgkey) {
+ PakfireKey key = pakfire_calloc(1, sizeof(*key));
+
+ if (key) {
+ key->pool = pool;
+
+ key->gpgkey = gpgkey;
+ gpgme_key_ref(key->gpgkey);
+ }
+
+ return key;
+}
+
+void pakfire_key_free(PakfireKey key) {
+ gpgme_key_unref(key->gpgkey);
+
+ pakfire_free(key);
+}
+
+PakfireKey pakfire_key_get(PakfirePool pool, const char* fingerprint) {
+ gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pool);
+ assert(gpgctx);
+
+ gpgme_key_t gpgkey = NULL;
+ gpgme_error_t error = gpgme_get_key(gpgctx, fingerprint, &gpgkey, 1);
+ if (error != GPG_ERR_NO_ERROR)
+ return NULL;
+
+ PakfireKey key = pakfire_key_create(pool, gpgkey);
+ gpgme_key_unref(gpgkey);
+ gpgme_release(gpgctx);
+
+ return key;
+}
+
+const char* pakfire_key_get_fingerprint(PakfireKey key) {
+ return key->gpgkey->fpr;
+}
+
+PakfireKey pakfire_key_generate(PakfirePool pool, const char* userid) {
+ gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pool);
+ assert(gpgctx);
+
+ unsigned int flags = 0;
+
+ // Key should be able to be used to sign
+ flags |= GPGME_CREATE_SIGN;
+
+ // Don't set a password
+ flags |= GPGME_CREATE_NOPASSWD;
+
+ // The key should never expire
+ flags |= GPGME_CREATE_NOEXPIRE;
+
+ // Generate the key
+ gpgme_error_t error = gpgme_op_createkey(gpgctx, userid,
+ "rsa512", 0, 0, NULL, flags);
+
+ if (error != GPG_ERR_NO_ERROR) {
+ printf("ERROR: %s\n", gpgme_strerror(error));
+ return NULL;
+ }
+
+ // Retrieve the result
+ gpgme_genkey_result_t result = gpgme_op_genkey_result(gpgctx);
+ gpgme_release(gpgctx);
+
+ // Retrieve the key by its fingerprint
+ return pakfire_key_get(pool, result->fpr);
+}
+
+char* pakfire_key_export(PakfireKey key, pakfire_key_export_mode_t mode) {
+ gpgme_ctx_t gpgctx = pakfire_get_gpgctx(key->pool);
+ assert(gpgctx);
+
+ gpgme_export_mode_t gpgmode = 0;
+ switch (mode) {
+ case PAKFIRE_KEY_EXPORT_MODE_SECRET:
+ gpgmode |= GPGME_EXPORT_MODE_SECRET;
+ break;
+
+ default:
+ break;
+ }
+
+ const char* fingerprint = pakfire_key_get_fingerprint(key);
+
+ // 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;
+
+ // 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;
+
+ // 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;
+
+ // Export key in ASCII format
+ size_t length;
+ char* mem = gpgme_data_release_and_get_mem(keydata, &length);
+ gpgme_release(gpgctx);
+
+ // Copy to our own string buffer
+ char* buffer = pakfire_strdup(mem);
+
+ // Release the exported key
+ gpgme_free(mem);
+
+ return buffer;
+
+FAIL:
+ gpgme_data_release(keydata);
+ gpgme_release(gpgctx);
+
+ return NULL;
+}
pakfire_file_sort;
pakfire_file_swap;
+ # key
+ pakfire_key_create;
+ pakfire_key_export;
+ pakfire_key_free;
+ pakfire_key_generate;
+ pakfire_key_get;
+ pakfire_key_get_fingerprint;
+ pakfire_key_list;
+
# package
pakfire_package_add_conflicts;
pakfire_package_add_obsoletes;
from . import _pakfire
from . import distro
from . import filelist
-from . import keyring
+#from . import keyring
from . import packages
from . import repository
from . import transaction
self.config = config or Config("general.conf")
# Initialize the keyring
- self.keyring = keyring.Keyring(self)
+ #self.keyring = keyring.Keyring(self)
self.pool = _pakfire.Pool(self.arch.name)
self.pool.cache_path = cache_path or \
class CliKey(Cli):
- pakfire = base.PakfireKey
-
- def __init__(self):
- self.parser = argparse.ArgumentParser(
- description = _("Pakfire key command line interface."),
+ def parse_cli(self):
+ parser = argparse.ArgumentParser(
+ description = _("Pakfire key command line interface"),
)
- self._add_common_arguments(self.parser, offline_switch=True)
-
- # Add sub-commands.
- self.sub_commands = self.parser.add_subparsers()
-
- self.parse_command_generate()
- self.parse_command_import()
- self.parse_command_export()
- self.parse_command_delete()
- self.parse_command_list()
- self.parse_command_sign()
- self.parse_command_verify()
+ subparsers = parser.add_subparsers()
- # Finally parse all arguments from the command line and save them.
- self.args = self.parser.parse_args()
+ # Add common arguments
+ self._add_common_arguments(parser)
- self.action2func = {
- "generate" : self.handle_generate,
- "import" : self.handle_import,
- "export" : self.handle_export,
- "delete" : self.handle_delete,
- "list" : self.handle_list,
- "sign" : self.handle_sign,
- "verify" : self.handle_verify,
- }
+ # generate
+ generate = subparsers.add_parser("generate", help=_("Import a key from file"))
+ generate.add_argument("--realname", nargs=1,
+ help=_("The real name of the owner of this key"))
+ generate.add_argument("--email", nargs=1,
+ help=_("The email address of the owner of this key"))
+ generate.set_defaults(func=self.handle_generate)
+
+ # list
+ 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)
- @property
- def pakfire_args(self):
- return {}
+ return parser.parse_args()
def parse_command_generate(self):
# Parse "generate" command.
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.add_argument("action", action="store_const", const="generate")
+ sub_gen.set_defaults(func=self.handle_generate)
def parse_command_import(self):
# Parse "import" command.
help=_("Filename of that key to import."))
sub_import.add_argument("action", action="store_const", const="import")
- def parse_command_export(self):
- # Parse "export" command.
- sub_export = self.sub_commands.add_parser("export",
- help=_("Export a key to a file."))
- sub_export.add_argument("keyid", nargs=1,
- help=_("The ID of the key to export."))
- sub_export.add_argument("filename", nargs=1,
- help=_("Write the key to this file."))
- sub_export.add_argument("action", action="store_const", const="export")
-
def parse_command_delete(self):
# Parse "delete" command.
sub_del = self.sub_commands.add_parser("delete",
help=_("The ID of the key to delete."))
sub_del.add_argument("action", action="store_const", const="delete")
- def parse_command_list(self):
- # Parse "list" command.
- sub_list = self.sub_commands.add_parser("list",
- help=_("List all imported keys."))
- sub_list.add_argument("action", action="store_const", const="list")
-
def parse_command_sign(self):
# Implement the "sign" command.
sub_sign = self.sub_commands.add_parser("sign",
help=_("Package(s) to verify."))
sub_verify.add_argument("action", action="store_const", const="verify")
- def handle_generate(self):
- realname = self.args.realname[0]
- email = self.args.email[0]
+ def handle_generate(self, ns):
+ p = self.pakfire(ns)
print(_("Generating the key may take a moment..."))
print()
- # Generate the key.
- p = self.create_pakfire()
- p.keyring.gen_key(realname, email)
+ key = p.pool.generate_key("%s <%s>" % (ns.realname.pop(), ns.email.pop()))
+
+ def handle_list(self, ns):
+ p = self.pakfire(ns)
+
+ for key in p.pool.keys:
+ print(key)
+
+ def handle_export(self, ns):
+ p = self.pakfire(ns)
+
+ for fingerprint in ns.fingerprint:
+ key = p.pool.get_key(fingerprint)
+ if not key:
+ print(_("Could not find key with fingerprint %s") % fingerprint)
+ continue
+
+ data = key.export(ns.secret)
+
+ for file in ns.filename:
+ with open(file, "w") as f:
+ f.write(data)
+ else:
+ print(data)
def handle_import(self):
filename = self.args.filename[0]
p = self.create_pakfire()
p.keyring.import_key(filename)
- def handle_export(self):
- keyid = self.args.keyid[0]
- filename = self.args.filename[0]
-
- p = self.create_pakfire()
- p.keyring.export_key(keyid, filename)
-
def handle_delete(self):
keyid = self.args.keyid[0]
p = self.create_pakfire()
p.keyring.delete_key(keyid)
- def handle_list(self):
- p = self.create_pakfire()
- for line in p.keyring.list_keys():
- print(line)
-
def handle_sign(self):
# Get the files from the command line options
files = []