File indexing completed on 2024-11-24 03:41:07

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2021 Slava Aseev <nullptrnine@basealt.ru>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 #ifndef _KWALLETFREEDESKTOPSERVICE_H_
0008 #define _KWALLETFREEDESKTOPSERVICE_H_
0009 
0010 #include <KConfig>
0011 #include <QDBusArgument>
0012 #include <QDBusServiceWatcher>
0013 #include <QHash>
0014 #include <QPointer>
0015 #include <QString>
0016 #include <QtCrypto>
0017 #include <QtDBus>
0018 
0019 #include "kwalletdbuscontext.h"
0020 
0021 #define FDO_APPID QString()
0022 #define FDO_SECRETS_SERVICE_OBJECT "/org/freedesktop/secrets"
0023 #define FDO_ALIAS_PATH "/org/freedesktop/secrets/aliases/"
0024 
0025 static inline constexpr size_t FDO_SECRETS_CIPHER_KEY_SIZE = 16;
0026 static inline constexpr int FDO_DH_PUBLIC_KEY_SIZE = 128;
0027 
0028 class KWalletD;
0029 
0030 class FreedesktopSecret
0031 {
0032 public:
0033     FreedesktopSecret() = default;
0034 
0035     FreedesktopSecret(QDBusObjectPath iSession, const QCA::SecureArray &iValue, QString iMimeType)
0036         : session(std::move(iSession))
0037         , value(iValue)
0038         , mimeType(std::move(iMimeType))
0039     {
0040     }
0041 
0042     friend QDBusArgument &operator<<(QDBusArgument &arg, const FreedesktopSecret &secret);
0043     friend const QDBusArgument &operator>>(const QDBusArgument &arg, FreedesktopSecret &secret);
0044 
0045     QDBusObjectPath session;
0046     QCA::SecureArray parameters;
0047     QCA::SecureArray value;
0048     QString mimeType;
0049 };
0050 
0051 struct PropertiesMap {
0052     QVariantMap map;
0053 };
0054 
0055 struct EntryLocation {
0056     static EntryLocation fromUniqueLabel(const struct FdoUniqueLabel &uniqLabel);
0057     struct FdoUniqueLabel toUniqueLabel() const;
0058 
0059     bool operator==(const EntryLocation &rhs) const
0060     {
0061         return folder == rhs.folder && key == rhs.key;
0062     }
0063 
0064     bool operator!=(const EntryLocation &rhs) const
0065     {
0066         return !(*this == rhs);
0067     }
0068 
0069     QString folder;
0070     QString key;
0071 };
0072 
0073 struct FdoUniqueLabel {
0074     static FdoUniqueLabel fromEntryLocation(const EntryLocation &entryLocation);
0075     static FdoUniqueLabel fromName(const QString &name);
0076     static QString makeName(const QString &label, int copyId);
0077 
0078     bool operator==(const FdoUniqueLabel &rhs) const
0079     {
0080         return copyId == rhs.copyId && label == rhs.label;
0081     }
0082 
0083     bool operator!=(const FdoUniqueLabel &rhs) const
0084     {
0085         return !(*this == rhs);
0086     }
0087 
0088     QString toName() const;
0089     EntryLocation toEntryLocation() const;
0090 
0091     QString label;
0092     int copyId = -1;
0093 };
0094 
0095 typedef QMap<QDBusObjectPath, FreedesktopSecret> FreedesktopSecretMap;
0096 typedef QMap<QString, QString> StrStrMap;
0097 
0098 Q_DECLARE_METATYPE(FreedesktopSecret)
0099 Q_DECLARE_METATYPE(FreedesktopSecretMap)
0100 Q_DECLARE_METATYPE(PropertiesMap)
0101 Q_DECLARE_METATYPE(StrStrMap)
0102 Q_DECLARE_METATYPE(QCA::SecureArray)
0103 
0104 class KWalletFreedesktopSession;
0105 class KWalletFreedesktopSessionAlgorithm;
0106 class KWalletFreedesktopCollection;
0107 class KWalletFreedesktopPrompt;
0108 class KWalletFreedesktopItem;
0109 
0110 class KWalletFreedesktopService : public QObject, protected FDO_DBUS_CONTEXT
0111 {
0112     /* org.freedesktop.Secret.Service properties */
0113 public:
0114     Q_PROPERTY(QList<QDBusObjectPath> Collections READ collections)
0115     QList<QDBusObjectPath> collections() const;
0116 
0117     Q_OBJECT
0118 
0119 public:
0120     explicit KWalletFreedesktopService(KWalletD *parent);
0121     ~KWalletFreedesktopService();
0122 
0123     KWalletFreedesktopService(const KWalletFreedesktopService &) = delete;
0124     KWalletFreedesktopService &operator=(const KWalletFreedesktopService &) = delete;
0125 
0126     KWalletFreedesktopService(KWalletFreedesktopService &&) = delete;
0127     KWalletFreedesktopService &operator=(KWalletFreedesktopService &&) = delete;
0128 
0129     static QString wrapToCollectionPath(const QString &itemPath);
0130 
0131     static QDBusObjectPath nextPromptPath();
0132     KWalletD *backend() const;
0133     QDBusObjectPath fdoObjectPath() const;
0134 
0135     bool desecret(const QDBusMessage &message, FreedesktopSecret &secret);
0136     bool ensecret(const QDBusMessage &message, FreedesktopSecret &secret);
0137     KWalletFreedesktopItem *getItemByObjectPath(const QDBusObjectPath &path) const;
0138     KWalletFreedesktopCollection *getCollectionByWalletName(const QString &walletName) const;
0139     KWalletFreedesktopPrompt *getPromptByObjectPath(const QDBusObjectPath &path) const;
0140 
0141     FdoUniqueLabel makeUniqueCollectionLabel(const QString &label);
0142     QString makeUniqueWalletName(const QString &labelPrefix);
0143     QDBusObjectPath makeUniqueObjectPath(const QString &walletName) const;
0144 
0145     QString resolveIfAlias(QString alias);
0146     QStringList readAliasesFor(const QString &walletName);
0147     void createCollectionAlias(const QString &alias, KWalletFreedesktopCollection *collection);
0148     void createCollectionAlias(const QString &alias, const QString &walletName);
0149     void updateCollectionAlias(const QString &alias, const QString &walletName);
0150     void removeAlias(const QString &alias);
0151 
0152     void deletePrompt(const QString &objectPath);
0153     void deleteSession(const QString &objectPath);
0154     QDBusObjectPath promptUnlockCollection(const QString &walletName, int handle);
0155 
0156     /* Emitters */
0157     void onCollectionCreated(const QDBusObjectPath &path);
0158     void onCollectionChanged(const QDBusObjectPath &path);
0159     void onCollectionDeleted(const QDBusObjectPath &path);
0160     void onPropertiesChanged(const QVariantMap &properties);
0161 
0162 private Q_SLOTS:
0163     void lockCollection(const QString &name);
0164     void entryUpdated(const QString &walletName, const QString &folder, const QString &entryName);
0165     void entryDeleted(const QString &walletName, const QString &folder, const QString &entryName);
0166     void entryRenamed(const QString &walletName, const QString &folder, const QString &oldName, const QString &newName);
0167     void walletDeleted(const QString &walletName);
0168     void walletCreated(const QString &walletCreated);
0169     /*
0170     void slotServiceOwnerChanged(const QString &name, const QString &oldOwner,
0171                                  const QString &newOwner);
0172     */
0173 
0174 private:
0175     std::unique_ptr<KWalletFreedesktopSessionAlgorithm> createSessionAlgorithmPlain() const;
0176     std::unique_ptr<KWalletFreedesktopSessionAlgorithm> createSessionAlgorithmDhAes(const QByteArray &clientKey) const;
0177     QString createSession(std::unique_ptr<KWalletFreedesktopSessionAlgorithm> algorithm);
0178     QString defaultWalletName(KConfigGroup &cfg);
0179 
0180 private:
0181     std::map<QString, std::unique_ptr<KWalletFreedesktopSession>> m_sessions;
0182     std::map<QString, std::unique_ptr<KWalletFreedesktopCollection>> m_collections;
0183     std::map<QString, std::unique_ptr<KWalletFreedesktopPrompt>> m_prompts;
0184 
0185     uint64_t m_session_counter = 0;
0186 
0187     /*
0188     QDBusServiceWatcher _serviceWatcher;
0189     */
0190     KWalletD *m_parent;
0191     QCA::Initializer m_init;
0192     KConfig m_kwalletrc;
0193 
0194     /* Freedesktop API */
0195 
0196     /* org.freedesktop.Secret.Service methods */
0197 public Q_SLOTS:
0198     QDBusObjectPath CreateCollection(const QVariantMap &properties, const QString &alias, QDBusObjectPath &prompt);
0199     FreedesktopSecretMap GetSecrets(const QList<QDBusObjectPath> &items, const QDBusObjectPath &session);
0200     QList<QDBusObjectPath> Lock(const QList<QDBusObjectPath> &objects, QDBusObjectPath &Prompt);
0201     QDBusVariant OpenSession(const QString &algorithm, const QDBusVariant &input, QDBusObjectPath &result);
0202     QDBusObjectPath ReadAlias(const QString &name);
0203     QList<QDBusObjectPath> SearchItems(const StrStrMap &attributes, QList<QDBusObjectPath> &locked);
0204     void SetAlias(const QString &name, const QDBusObjectPath &collection);
0205     QList<QDBusObjectPath> Unlock(const QList<QDBusObjectPath> &objects, QDBusObjectPath &prompt);
0206 
0207     /* org.freedesktop.Secret.Service signals */
0208 Q_SIGNALS:
0209     void CollectionChanged(const QDBusObjectPath &collection);
0210     void CollectionCreated(const QDBusObjectPath &collection);
0211     void CollectionDeleted(const QDBusObjectPath &collection);
0212 };
0213 
0214 QDataStream &operator<<(QDataStream &stream, const QDBusObjectPath &value);
0215 QDataStream &operator>>(QDataStream &stream, QDBusObjectPath &value);
0216 
0217 const QDBusArgument &operator>>(const QDBusArgument &arg, PropertiesMap &value);
0218 QDBusArgument &operator<<(QDBusArgument &arg, const PropertiesMap &value);
0219 
0220 QDataStream &operator<<(QDataStream &stream, const QCA::SecureArray &value);
0221 QDataStream &operator>>(QDataStream &stream, QCA::SecureArray &value);
0222 QDBusArgument &operator<<(QDBusArgument &arg, const QCA::SecureArray &value);
0223 const QDBusArgument &operator>>(const QDBusArgument &arg, QCA::SecureArray &buf);
0224 
0225 void explicit_zero_mem(void *data, size_t size);
0226 
0227 #endif