123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- #if defined(HAVE_LIBSECRET)
- #include <libsecret/secret.h>
- #endif
- #include "libsecret_p.h"
- #include <QLibrary>
- #if defined(HAVE_LIBSECRET)
- const SecretSchema* qtkeychainSchema(void) {
- static const SecretSchema schema = {
- "org.qt.keychain", SECRET_SCHEMA_DONT_MATCH_NAME,
- {
- { "user", SECRET_SCHEMA_ATTRIBUTE_STRING },
- { "server", SECRET_SCHEMA_ATTRIBUTE_STRING },
- { "type", SECRET_SCHEMA_ATTRIBUTE_STRING }
- }
- };
- return &schema;
- }
- typedef struct {
- QKeychain::JobPrivate *self;
- QString user;
- QString server;
- } callbackArg;
- typedef void (*secret_password_lookup_t) (const SecretSchema *schema,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data,
- ...) G_GNUC_NULL_TERMINATED;
- typedef gchar *(*secret_password_lookup_finish_t) (GAsyncResult *result,
- GError **error);
- typedef void (*secret_password_store_t) (const SecretSchema *schema,
- const gchar *collection,
- const gchar *label,
- const gchar *password,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data,
- ...) G_GNUC_NULL_TERMINATED;
- typedef gboolean (*secret_password_store_finish_t) (GAsyncResult *result,
- GError **error);
- typedef void (*secret_password_clear_t) (const SecretSchema *schema,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data,
- ...) G_GNUC_NULL_TERMINATED;
- typedef gboolean (*secret_password_clear_finish_t) (GAsyncResult *result,
- GError **error);
- typedef void (*secret_password_free_t) (gchar *password);
- typedef GQuark (*secret_error_get_quark_t) (void) G_GNUC_CONST;
- static secret_password_lookup_t secret_password_lookup_fn = nullptr;
- static secret_password_lookup_finish_t secret_password_lookup_finish_fn = nullptr;
- static secret_password_store_t secret_password_store_fn = nullptr;
- static secret_password_store_finish_t secret_password_store_finish_fn = nullptr;
- static secret_password_clear_t secret_password_clear_fn = nullptr;
- static secret_password_clear_finish_t secret_password_clear_finish_fn = nullptr;
- static secret_password_free_t secret_password_free_fn = nullptr;
- static secret_error_get_quark_t secret_error_get_quark_fn = nullptr;
- static QKeychain::Error gerrorToCode(const GError *error) {
- if (error->domain != secret_error_get_quark_fn()) {
- return QKeychain::OtherError;
- }
- switch(error->code) {
- case SECRET_ERROR_NO_SUCH_OBJECT:
- return QKeychain::EntryNotFound;
- case SECRET_ERROR_IS_LOCKED:
- return QKeychain::AccessDenied;
- default:
- return QKeychain::OtherError;
- }
- }
- static void
- on_password_lookup (GObject *source,
- GAsyncResult *result,
- gpointer inst)
- {
- GError *error = nullptr;
- callbackArg *arg = (callbackArg*)inst;
- gchar *password = secret_password_lookup_finish_fn (result, &error);
- Q_UNUSED(source);
- if (arg) {
- if (error) {
- QKeychain::Error code = gerrorToCode(error);
- arg->self->q->emitFinishedWithError( code, QString::fromUtf8(error->message) );
- } else {
- if (password) {
- QByteArray raw = QByteArray(password);
- switch(arg->self->mode) {
- case QKeychain::JobPrivate::Binary:
- arg->self->data = QByteArray::fromBase64(raw);
- break;
- case QKeychain::JobPrivate::Text:
- default:
- arg->self->data = raw;
- }
- arg->self->q->emitFinished();
- } else if (arg->self->mode == QKeychain::JobPrivate::Text) {
- arg->self->mode = QKeychain::JobPrivate::Binary;
- secret_password_lookup_fn (qtkeychainSchema(), nullptr,
- on_password_lookup, arg,
- "user", arg->user.toUtf8().constData(),
- "server", arg->server.toUtf8().constData(),
- "type", "base64",
- nullptr);
- return;
- } else {
- arg->self->q->emitFinishedWithError( QKeychain::EntryNotFound, QObject::tr("Entry not found") );
- }
- }
- }
- if (error) {
- g_error_free (error);
- }
- if (password) {
- secret_password_free_fn (password);
- }
- if (arg) {
- delete arg;
- }
- }
- static void
- on_password_stored (GObject *source,
- GAsyncResult *result,
- gpointer inst)
- {
- GError *error = nullptr;
- QKeychain::JobPrivate *self = (QKeychain::JobPrivate*)inst;
- Q_UNUSED(source);
- secret_password_store_finish_fn (result, &error);
- if (self) {
- if (error) {
- self->q->emitFinishedWithError( gerrorToCode(error),
- QString::fromUtf8(error->message) );
- } else {
- self->q->emitFinished();
- }
- }
- if (error) {
- g_error_free (error);
- }
- }
- static void
- on_password_cleared (GObject *source,
- GAsyncResult *result,
- gpointer inst)
- {
- GError *error = nullptr;
- QKeychain::JobPrivate *self = (QKeychain::JobPrivate*)inst;
- gboolean removed = secret_password_clear_finish_fn (result, &error);
- Q_UNUSED(source);
- if (self) {
- if ( error ) {
- self->q->emitFinishedWithError( gerrorToCode(error),
- QString::fromUtf8(error->message) );
- } else {
- Q_UNUSED(removed);
- self->q->emitFinished();
- }
- }
- if (error) {
- g_error_free (error);
- }
- }
- static QString modeToString(QKeychain::JobPrivate::Mode mode) {
- switch(mode) {
- case QKeychain::JobPrivate::Binary:
- return "base64";
- default:
- return "plaintext";
- }
- }
- #endif
- bool LibSecretKeyring::isAvailable() {
- #if defined(HAVE_LIBSECRET)
- const LibSecretKeyring& keyring = instance();
- if (!keyring.isLoaded())
- return false;
- if (secret_password_lookup_fn == nullptr)
- return false;
- if (secret_password_lookup_finish_fn == nullptr)
- return false;
- if (secret_password_store_fn == nullptr)
- return false;
- if (secret_password_store_finish_fn == nullptr)
- return false;
- if (secret_password_clear_fn == nullptr)
- return false;
- if (secret_password_clear_finish_fn == nullptr)
- return false;
- if (secret_password_free_fn == nullptr)
- return false;
- if (secret_error_get_quark_fn == nullptr)
- return false;
- return true;
- #else
- return false;
- #endif
- }
- bool LibSecretKeyring::findPassword(const QString &user, const QString &server,
- QKeychain::JobPrivate *self)
- {
- #if defined(HAVE_LIBSECRET)
- if (!isAvailable()) {
- return false;
- }
- self->mode = QKeychain::JobPrivate::Text;
- self->data = QByteArray();
- callbackArg *arg = new callbackArg;
- arg->self = self;
- arg->user = user;
- arg->server = server;
- secret_password_lookup_fn (qtkeychainSchema(), nullptr, on_password_lookup, arg,
- "user", user.toUtf8().constData(),
- "server", server.toUtf8().constData(),
- "type", "plaintext",
- nullptr);
- return true;
- #else
- Q_UNUSED(user)
- Q_UNUSED(server)
- Q_UNUSED(self)
- return false;
- #endif
- }
- bool LibSecretKeyring::writePassword(const QString &display_name,
- const QString &user,
- const QString &server,
- const QKeychain::JobPrivate::Mode mode,
- const QByteArray &password,
- QKeychain::JobPrivate *self)
- {
- #if defined(HAVE_LIBSECRET)
- if (!isAvailable()) {
- return false;
- }
- QString type = modeToString(mode);
- QByteArray pwd;
- switch(mode) {
- case QKeychain::JobPrivate::Binary:
- pwd = password.toBase64();
- break;
- default:
- pwd = password;
- break;
- }
- secret_password_store_fn (qtkeychainSchema(), SECRET_COLLECTION_DEFAULT,
- display_name.toUtf8().constData(),
- pwd.constData(), nullptr, on_password_stored, self,
- "user", user.toUtf8().constData(),
- "server", server.toUtf8().constData(),
- "type", type.toUtf8().constData(),
- nullptr);
- return true;
- #else
- Q_UNUSED(display_name)
- Q_UNUSED(user)
- Q_UNUSED(server)
- Q_UNUSED(mode)
- Q_UNUSED(password)
- Q_UNUSED(self)
- return false;
- #endif
- }
- bool LibSecretKeyring::deletePassword(const QString &key, const QString &service,
- QKeychain::JobPrivate* self)
- {
- #if defined(HAVE_LIBSECRET)
- if (!isAvailable()) {
- return false;
- }
- secret_password_clear_fn (qtkeychainSchema(), nullptr, on_password_cleared, self,
- "user", key.toUtf8().constData(),
- "server", service.toUtf8().constData(),
- nullptr);
- #else
- Q_UNUSED(key)
- Q_UNUSED(service)
- Q_UNUSED(self)
- return false;
- #endif
- }
- LibSecretKeyring::LibSecretKeyring()
- : QLibrary(QLatin1String("secret-1"), 0)
- {
- #ifdef HAVE_LIBSECRET
- if (load()) {
- secret_password_lookup_fn =
- (secret_password_lookup_t)resolve("secret_password_lookup");
- secret_password_lookup_finish_fn =
- (secret_password_lookup_finish_t)resolve("secret_password_lookup_finish");
- secret_password_store_fn =
- (secret_password_store_t)resolve("secret_password_store");
- secret_password_store_finish_fn =
- (secret_password_store_finish_t)resolve("secret_password_store_finish");
- secret_password_clear_fn =
- (secret_password_clear_t)resolve("secret_password_clear");
- secret_password_clear_finish_fn =
- (secret_password_clear_finish_t)resolve("secret_password_clear_finish");
- secret_password_free_fn =
- (secret_password_free_t)resolve("secret_password_free");
- secret_error_get_quark_fn =
- (secret_error_get_quark_t)resolve("secret_error_get_quark");
- }
- #endif
- }
- LibSecretKeyring &LibSecretKeyring::instance() {
- static LibSecretKeyring instance;
- return instance;
- }
|