KWallet

kwalletfreedesktopitem.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2021 Slava Aseev <nullptrnine@basealt.ru>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7#include "kwalletfreedesktopitem.h"
8
9#include "ksecretd.h"
10#include "ksecretd_debug.h"
11#include "kwallet.h"
12#include "kwalletfreedesktopcollection.h"
13#include "kwalletfreedesktopitemadaptor.h"
14
15KWalletFreedesktopItem::KWalletFreedesktopItem(KWalletFreedesktopCollection *collection, FdoUniqueLabel uniqLabel, QDBusObjectPath path)
16 : m_collection(collection)
17 , m_uniqueLabel(std::move(uniqLabel))
18 , m_path(std::move(path))
19{
20 (void)new KWalletFreedesktopItemAdaptor(this);
21 QDBusConnection::sessionBus().registerObject(fdoObjectPath().path(), this);
22}
23
24KWalletFreedesktopItem::~KWalletFreedesktopItem()
25{
26 onPropertiesChanged(QVariantMap());
27
29
30 if (!m_wasDeleted) {
31 m_collection->onItemChanged(fdoObjectPath());
32 }
33}
34
35StrStrMap KWalletFreedesktopItem::attributes() const
36{
37 return fdoCollection()->itemAttributes().getAttributes(m_uniqueLabel);
38}
39
40void KWalletFreedesktopItem::setAttributes(const StrStrMap &value)
41{
42 fdoCollection()->itemAttributes().setAttributes(m_uniqueLabel, value);
43}
44
45qulonglong KWalletFreedesktopItem::created() const
46{
47 return fdoCollection()->itemAttributes().getULongLongParam(m_uniqueLabel, FDO_KEY_CREATED, fdoCollection()->modified());
48}
49
50qulonglong KWalletFreedesktopItem::modified() const
51{
52 return fdoCollection()->itemAttributes().getULongLongParam(m_uniqueLabel, FDO_KEY_MODIFIED, fdoCollection()->modified());
53}
54
55QString KWalletFreedesktopItem::label() const
56{
57 return m_uniqueLabel.label;
58}
59
60void KWalletFreedesktopItem::setLabel(const QString &value)
61{
62 const auto entryLocation = m_uniqueLabel.toEntryLocation();
63 m_uniqueLabel = fdoCollection()->makeUniqueItemLabel(value);
64 const auto newEntryLocation = m_uniqueLabel.toEntryLocation();
65
66 if (newEntryLocation.folder != entryLocation.folder) {
67 const auto data = backend()->readEntry(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, FDO_APPID);
68 backend()->writeEntry(fdoCollection()->walletHandle(), newEntryLocation.folder, newEntryLocation.key, data, FDO_APPID);
69 backend()->removeEntry(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, FDO_APPID);
70 } else if (newEntryLocation.key != entryLocation.key) {
71 backend()->renameEntry(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, newEntryLocation.key, FDO_APPID);
72 }
73
74 fdoCollection()->itemAttributes().setParam(entryLocation, FDO_KEY_MODIFIED, static_cast<qulonglong>(QDateTime::currentSecsSinceEpoch()));
75 fdoCollection()->itemAttributes().renameLabel(entryLocation, newEntryLocation);
76
77 fdoCollection()->onItemChanged(fdoObjectPath());
78}
79
80bool KWalletFreedesktopItem::locked() const
81{
82 return m_collection->locked();
83}
84
85QString KWalletFreedesktopItem::type() const
86{
87 const auto attribs = fdoCollection()->itemAttributes().getAttributes(m_uniqueLabel);
88 const auto found = attribs.find(FDO_KEY_XDG_SCHEMA);
89 if (found != attribs.end()) {
90 return found.value();
91 } else {
92 return QStringLiteral("org.freedesktop.Secret.Generic");
93 }
94}
95
96void KWalletFreedesktopItem::setType(const QString &value)
97{
98 auto attribs = fdoCollection()->itemAttributes().getAttributes(m_uniqueLabel);
99 attribs[FDO_KEY_XDG_SCHEMA] = value;
100 fdoCollection()->itemAttributes().setAttributes(m_uniqueLabel, attribs);
101}
102
103QDBusObjectPath KWalletFreedesktopItem::Delete()
104{
105 const auto entryLocation = m_uniqueLabel.toEntryLocation();
106
107 backend()->removeEntry(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, FDO_APPID);
109
110 m_collection->onItemDeleted(fdoObjectPath());
111
112 return QDBusObjectPath("/");
113}
114
115FreedesktopSecret KWalletFreedesktopItem::getSecret(const QDBusConnection &connection, const QDBusMessage &message, const QDBusObjectPath &session)
116{
117 const auto entryLocation = m_uniqueLabel.toEntryLocation();
118 const auto mimeType = fdoCollection()->itemAttributes().getStringParam(entryLocation, FDO_KEY_MIME, QStringLiteral("application/octet-stream"));
119
120 FreedesktopSecret fdoSecret;
121
122 const auto entryType = backend()->entryType(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, FDO_APPID);
123 if (entryType == KWallet::Wallet::Password) {
124 auto password = backend()->readPassword(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, FDO_APPID);
125 auto bytes = password.toUtf8();
126 fdoSecret = FreedesktopSecret(session, bytes, mimeType);
127 explicit_zero_mem(bytes.data(), bytes.size());
128 explicit_zero_mem(password.data(), password.size() * sizeof(QChar));
129 } else if (entryType == KWallet::Wallet::Map) {
130 auto serializedMap = backend()->readMap(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, FDO_APPID);
131 QMap<QString, QString> map;
132 QDataStream ds(&serializedMap, QIODevice::ReadOnly);
133 ds >> map;
134 QJsonObject obj;
135 for (auto it = map.constBegin(); it != map.constEnd(); it++) {
136 obj.insert(it.key(), it.value());
137 }
138 fdoSecret = FreedesktopSecret(session, QJsonDocument(obj).toJson(QJsonDocument::Compact), mimeType);
139 explicit_zero_mem(serializedMap.data(), serializedMap.size());
140 } else {
141 auto bytes = backend()->readEntry(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, FDO_APPID);
142 fdoSecret = FreedesktopSecret(session, bytes, mimeType);
143 explicit_zero_mem(bytes.data(), bytes.size());
144 }
145
146 if (!fdoService()->ensecret(message, fdoSecret)) {
147 message.setDelayedReply(true);
148 connection.send(message.createErrorReply(QDBusError::ErrorType::UnknownObject, QStringLiteral("Can't find session ") + session.path()));
149 }
150
151 return fdoSecret;
152}
153
154FreedesktopSecret KWalletFreedesktopItem::GetSecret(const QDBusObjectPath &session)
155{
156 return getSecret(connection(), message(), session);
157}
158
159void KWalletFreedesktopItem::SetSecret(const FreedesktopSecret &secret)
160{
161 const auto entryLocation = m_uniqueLabel.toEntryLocation();
162
163 fdoCollection()->itemAttributes().setParam(entryLocation, FDO_KEY_MIME, secret.mimeType);
164 fdoCollection()->itemAttributes().setParam(entryLocation, FDO_KEY_MODIFIED, static_cast<qulonglong>(QDateTime::currentSecsSinceEpoch()));
165
166 auto decrypted = secret;
167 if (!fdoService()->desecret(message(), decrypted)) {
168 sendErrorReply(QDBusError::ErrorType::UnknownObject, QStringLiteral("Can't find session ") + secret.session.path());
169 return;
170 }
171
172 QString xdgSchema = QStringLiteral("org.kde.KWallet.Stream");
173 const auto attribs = fdoCollection()->itemAttributes().getAttributes(entryLocation);
174 const auto found = attribs.find(FDO_KEY_XDG_SCHEMA);
175 if (found != attribs.end()) {
176 xdgSchema = found.value();
177 }
178
179 if (xdgSchema == QStringLiteral("org.kde.KWallet.Password") || secret.mimeType.startsWith(QStringLiteral("text/"))) {
180 auto bytes = decrypted.value.toByteArray();
181 auto str = QString::fromUtf8(bytes);
182 backend()->writePassword(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, str, FDO_APPID);
183 explicit_zero_mem(bytes.data(), bytes.size());
184 explicit_zero_mem(str.data(), str.size() * sizeof(QChar));
185 } else {
186 auto bytes = decrypted.value.toByteArray();
187 backend()->writeEntry(fdoCollection()->walletHandle(), entryLocation.folder, entryLocation.key, bytes, KWallet::Wallet::Stream, FDO_APPID);
188 }
189}
190
191KWalletFreedesktopCollection *KWalletFreedesktopItem::fdoCollection() const
192{
193 return m_collection;
194}
195
196KWalletFreedesktopService *KWalletFreedesktopItem::fdoService() const
197{
198 return fdoCollection()->fdoService();
199}
200
201KSecretD *KWalletFreedesktopItem::backend() const
202{
203 return fdoCollection()->fdoService()->backend();
204}
205
206QDBusObjectPath KWalletFreedesktopItem::fdoObjectPath() const
207{
208 return m_path;
209}
210
211const FdoUniqueLabel &KWalletFreedesktopItem::uniqueLabel() const
212{
213 return m_uniqueLabel;
214}
215
216void KWalletFreedesktopItem::uniqueLabel(const FdoUniqueLabel &uniqueLabel)
217{
218 m_uniqueLabel = uniqueLabel;
219}
220
221void KWalletFreedesktopItem::setDeleted()
222{
223 m_wasDeleted = true;
224 fdoCollection()->itemAttributes().remove(m_uniqueLabel);
225}
226
227void KWalletFreedesktopItem::onPropertiesChanged(const QVariantMap &properties)
228{
229 auto msg = QDBusMessage::createSignal(fdoObjectPath().path(), QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"));
230 auto args = QVariantList();
231 args << QStringLiteral("org.freedesktop.Secret.Item") << properties << QStringList();
232 msg.setArguments(args);
234}
235
236#include "moc_kwalletfreedesktopitem.cpp"
KCALUTILS_EXPORT QString mimeType()
KIOCORE_EXPORT CopyJob * move(const QList< QUrl > &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QString path(const QString &relativePath)
KGuiItem properties()
qint64 currentSecsSinceEpoch()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
bool send(const QDBusMessage &message) const const
QDBusConnection sessionBus()
void unregisterObject(const QString &path, UnregisterMode mode)
QDBusMessage createErrorReply(QDBusError::ErrorType type, const QString &msg) const const
QDBusMessage createSignal(const QString &path, const QString &interface, const QString &name)
void setDelayedReply(bool enable) const const
QString path() const const
iterator insert(QLatin1StringView key, const QJsonValue &value)
QString fromUtf8(QByteArrayView str)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 25 2025 11:53:00 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.