1 /*
2     This file is part of the KDE project
3 
4     SPDX-FileCopyrightText: 2002-2004 George Staikos <staikos@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #ifndef _KWALLET_H
10 #define _KWALLET_H
11 
12 #include <QObject>
13 #include <QStringList>
14 #include <qwindowdefs.h> // krazy:exclude=includes (for WId)
15 
16 #include <kwallet_export.h>
17 
18 /**
19  * NOTE: KSecretsService folder semantics
20  * The KWallet API uses folders for organising items. KSecretsService does not
21  * have this notion. But it uses attributes that can be applied arbitrarily on
22  * all the items. The KWallet code that maps to KSecretsService applies an special
23  * attribute KSS_ATTR_ENTRYFOLDER to all items with the currentFolder() value.
24  * The KWallet folder API's calls will always succeed and they'll only change the
25  * current folder value. The folderList() call will scan all the collection
26  * items and collect the KSS_ATTR_ENTRYFOLDER attributes into a list.
27  */
28 
29 /**
30  * NOTE: KWalet API distinguish KSecretsService collection items by attaching
31  * them some specific attributes, defined below
32  */
33 #define KSS_ATTR_ENTRYFOLDER "kwallet.folderName"
34 #define KSS_ATTR_WALLETTYPE "kwallet.type"
35 
36 namespace KWallet
37 {
38 /**
39  * KDE Wallet
40  *
41  * This class implements a generic system-wide Wallet for KDE.  This is the
42  * ONLY public interface.
43  *
44  * @author George Staikos <staikos@kde.org>
45  * @short KDE Wallet Class
46  */
47 class KWALLET_EXPORT Wallet : public QObject
48 {
49     Q_OBJECT
50 protected:
51     /**
52      *  Construct a KWallet object.
53      *  @internal
54      *  @param handle The handle for the wallet.
55      *  @param name The name of the wallet.
56      */
57     Wallet(int handle, const QString &name);
58     /**
59      *  Copy a KWallet object.
60      *  @internal
61      */
62     Wallet(const Wallet &);
63 
64 public:
65     enum EntryType {
66         Unknown = 0,
67         Password,
68         Stream,
69         Map,
70         Unused = 0xffff,
71     };
72 
73     /**
74      *  Destroy a KWallet object.  Closes the wallet.
75      */
76     ~Wallet() override;
77 
78     /**
79      *  List all the wallets available.
80      *  @return Returns a list of the names of all wallets that are
81      *          open.
82      */
83     static QStringList walletList();
84 
85     /**
86      *  Determine if the KDE wallet is enabled.  Normally you do
87      *  not need to use this because openWallet() will just fail.
88      *  @return Returns true if the wallet enabled, else false.
89      */
90     static bool isEnabled();
91 
92     /**
93      *  Determine if the wallet @p name is open by any application.
94      *  @param name The name of the wallet to check.
95      *  @return Returns true if the wallet is open, else false.
96      */
97     static bool isOpen(const QString &name);
98 
99     /**
100      *  Close the wallet @p name.  The wallet will only be closed
101      *  if it is open but not in use (rare), or if it is forced
102      *  closed.
103      *  @param name The name of the wallet to close.
104      *  @param force Set true to force the wallet closed even if it
105      *               is in use by others.
106      *  @return Returns 0 on success, non-zero on error.
107      */
108     static int closeWallet(const QString &name, bool force);
109 
110     /**
111      *  Delete the wallet @p name.  The wallet will be forced closed
112      *  first.
113      *  @param name The name of the wallet to delete.
114      *  @return Returns 0 on success, non-zero on error.
115      */
116     static int deleteWallet(const QString &name);
117 
118     /**
119      *  Disconnect the application @p app from @p wallet.
120      *  @param wallet The name of the wallet to disconnect.
121      *  @param app The name of the application to disconnect.
122      *  @return Returns true on success, false on error.
123      */
124     static bool disconnectApplication(const QString &wallet, const QString &app);
125 
126     enum OpenType {
127         Synchronous = 0,
128         Asynchronous,
129         Path,
130         OpenTypeUnused = 0xff,
131     };
132 
133     /**
134      *  Open the wallet @p name.  The user will be prompted to
135      *  allow your application to open the wallet, and may be
136      *  prompted for a password.  You are responsible for deleting
137      *  this object when you are done with it.
138      *  @param name The name of the wallet to open.
139      *  @param ot    If Asynchronous, the call will return
140      *               immediately with a non-null pointer to an
141      *               invalid wallet.  You must immediately connect
142      *               the walletOpened() signal to a slot so that
143      *               you will know when it is opened, or when it
144      *               fails.
145      *  @param w The window id to associate any dialogs with. You can pass
146      *           0 if you don't have a window the password dialog should
147      *           associate with.
148      *  @return Returns a pointer to the wallet if successful,
149      *          or a null pointer on error or if rejected.
150      *          A null pointer can also be returned if user choose to
151      *          deactivate the wallet system.
152      */
153     static Wallet *openWallet(const QString &name, WId w, OpenType ot = Synchronous);
154 
155     /**
156      *  List the applications that are using the wallet @p wallet.
157      *  @param wallet The wallet to query.
158      *  @return Returns a list of all DCOP application IDs using
159      *          the wallet.
160      */
161     static QStringList users(const QString &wallet);
162 
163     /**
164      *  The name of the wallet used to store local passwords.
165      */
166     static const QString LocalWallet();
167 
168     /**
169      *  The name of the wallet used to store network passwords.
170      */
171     static const QString NetworkWallet();
172 
173     /**
174      *  The standardized name of the password folder.
175      *  It is automatically created when a wallet is created, but
176      *  the user may still delete it so you should check for its
177      *  existence and recreate it if necessary and desired.
178      */
179     static const QString PasswordFolder();
180 
181     /**
182      *  The standardized name of the form data folder.
183      *  It is automatically created when a wallet is created, but
184      *  the user may still delete it so you should check for its
185      *  existence and recreate it if necessary and desired.
186      */
187     static const QString FormDataFolder();
188 
189     /**
190      *  Request to the wallet service to change the password of
191      *  the wallet @p name.
192      *  @param name The wallet to change the password of.
193      *  @param w The window id to associate any dialogs with. You can pass
194      *           0 if you don't have a window the password dialog should
195      *           associate with.
196      */
197     static void changePassword(const QString &name, WId w);
198 
199     /**
200      *  This syncs the wallet file on disk with what is in memory.
201      *  You don't normally need to use this.  It happens
202      *  automatically on close.
203      *  @return Returns 0 on success, non-zero on error.
204      */
205     virtual int sync();
206 
207     /**
208      *  This closes and locks the current wallet.  It will
209      *  disconnect all applications using the wallet.
210      *  @return Returns 0 on success, non-zero on error.
211      */
212     virtual int lockWallet();
213 
214     /**
215      *  The name of the current wallet.
216      */
217     virtual const QString &walletName() const;
218 
219     /**
220      *  Determine if the current wallet is open, and is a valid
221      *  wallet handle.
222      *  @return Returns true if the wallet handle is valid and open.
223      */
224     virtual bool isOpen() const;
225 
226     /**
227      *  Request to the wallet service to change the password of
228      *  the current wallet.
229      *  @param w The window id to associate any dialogs with. You can pass
230      *           0 if you don't have a window the password dialog should
231      *           associate with.
232      */
233     virtual void requestChangePassword(WId w);
234 
235     /**
236      *  Obtain the list of all folders contained in the wallet.
237      *  @return Returns an empty list if the wallet is not open.
238      */
239     virtual QStringList folderList();
240 
241     /**
242      *  Determine if the folder @p f exists in the wallet.
243      *  @param f the name of the folder to check for
244      *  @return Returns true if the folder exists in the wallet.
245      */
246     virtual bool hasFolder(const QString &f);
247 
248     /**
249      *  Set the current working folder to @p f.  The folder must
250      *  exist, or this call will fail.  Create a folder with
251      *  createFolder().
252      *  @param f the name of the folder to make the working folder
253      *  @return Returns true if the folder was successfully set.
254      */
255     virtual bool setFolder(const QString &f);
256 
257     /**
258      *  Remove the folder @p f and all its entries from the wallet.
259      *  @param f the name of the folder to remove
260      *  @return Returns true if the folder was successfully removed.
261      */
262     virtual bool removeFolder(const QString &f);
263 
264     /**
265      *  Created the folder @p f.
266      *  @param f the name of the folder to create
267      *  @return Returns true if the folder was successfully created.
268      */
269     virtual bool createFolder(const QString &f);
270 
271     /**
272      *  Determine the current working folder in the wallet.
273      *  If the folder name is empty, it is working in the global
274      *  folder, which is valid but discouraged.
275      *  @return Returns the current working folder.
276      */
277     virtual const QString &currentFolder() const;
278 
279     /**
280      *  Return the list of keys of all entries in this folder.
281      *  @return Returns an empty list if the wallet is not open, or
282      *          if the folder is empty.
283      */
284     virtual QStringList entryList();
285 
286     // TODO KDE5: a entryList(folder) so that kwalletmanager can list a folder without
287     // having to call setFolder before and after (which calls contains() in each)
288 
289     /**
290      *  Rename the entry @p oldName to @p newName.
291      *  @param oldName The original key of the entry.
292      *  @param newName The new key of the entry.
293      *  @return Returns 0 on success, non-zero on error.
294      */
295     virtual int renameEntry(const QString &oldName, const QString &newName);
296 
297     /**
298      *  Read the entry @p key from the current folder.
299      *  The entry format is unknown except that it is either a
300      *  QByteArray or a QDataStream, which effectively means that
301      *  it is anything.
302      *  @param key The key of the entry to read.
303      *  @param value A buffer to fill with the value.
304      *  @return Returns 0 on success, non-zero on error.
305      */
306     virtual int readEntry(const QString &key, QByteArray &value);
307 
308     /**
309      *  Read the map entry @p key from the current folder.
310      *  @param key The key of the entry to read.
311      *  @param value A map buffer to fill with the value.
312      *  @return Returns 0 on success, non-zero on error.  Will
313      *          return an error if the key was not originally
314      *          written as a map.
315      */
316     virtual int readMap(const QString &key, QMap<QString, QString> &value);
317 
318     /**
319      *  Read the password entry @p key from the current folder.
320      *  @param key The key of the entry to read.
321      *  @param value A password buffer to fill with the value.
322      *  @return Returns 0 on success, non-zero on error.  Will
323      *          return an error if the key was not originally
324      *          written as a password.
325      */
326     virtual int readPassword(const QString &key, QString &value);
327 
328 #if KWALLET_ENABLE_DEPRECATED_SINCE(5, 72)
329     /**
330      *  Read the entries matching @p key from the current folder.
331      *  The entry format is unknown except that it is either a
332      *  QByteArray or a QDataStream, which effectively means that
333      *  it is anything.
334      *  @param key The key of the entry to read.  Wildcards
335      *             are supported.
336      *  @param value A buffer to fill with the value.  The key in
337      *               the map is the entry key.
338      *  @return Returns 0 on success, non-zero on error.
339      *
340      *  @deprecated Since 5.72, use entriesList(bool *)
341      */
342     KWALLET_DEPRECATED_VERSION(5, 72, "Use entriesList(bool *)")
343     int readEntryList(const QString &key, QMap<QString, QByteArray> &value);
344 #endif
345 
346 #if KWALLET_ENABLE_DEPRECATED_SINCE(5, 72)
347     /**
348      *  Read the map entry @p key from the current folder.
349      *  @param key The key of the entry to read.  Wildcards
350      *             are supported.
351      *  @param value A buffer to fill with the value.  The key in
352      *               the map is the entry key.
353      *  @return Returns 0 on success, non-zero on error.  Will
354      *          return an error if the key was not originally
355      *          written as a map.
356      *
357      *  @deprecated Since 5.72, use mapList(bool *)
358      */
359     KWALLET_DEPRECATED_VERSION(5, 72, "Use mapList(bool *)")
360     int readMapList(const QString &key, QMap<QString, QMap<QString, QString>> &value);
361 #endif
362 
363 #if KWALLET_ENABLE_DEPRECATED_SINCE(5, 72)
364     /**
365      *  Read the password entry @p key from the current folder.
366      *  @param key The key of the entry to read.  Wildcards
367      *             are supported.
368      *  @param value A buffer to fill with the value.  The key in
369      *               the map is the entry key.
370      *  @return Returns 0 on success, non-zero on error.  Will
371      *          return an error if the key was not originally
372      *          written as a password.
373      *
374      *  @deprecated Since 5.72, use passwordList(bool *)
375      */
376     KWALLET_DEPRECATED_VERSION(5, 72, "Use passwordList(bool *)")
377     int readPasswordList(const QString &key, QMap<QString, QString> &value);
378 #endif
379 
380     /**
381      *  Get a list of all the entries in the current folder. The entry
382      *  format is unknown except that it is either a QByteArray or a
383      *  QDataStream, which effectively means that it could be anything.
384      *
385      *  @param ok if not nullptr, the object this parameter points to will be set
386      *            to true to indicate success or false otherwise
387      *  @return a map of key/value pairs where the key in the map is the entry key
388      *
389      *  @since 5.72
390      */
391     QMap<QString, QByteArray> entriesList(bool *ok) const;
392 
393     /**
394      *  Get a list of all the maps in the current folder.
395      *
396      *  @param ok if not nullptr, the object this parameter points to will be set
397      *            to true to indicate success or false otherwise. Note that if any
398      *            of the keys was not originally written as a map, the object will
399      *            be set to false
400      *
401      *  @return a map of key/value pairs where the key in the map is the entry key
402      *
403      *  @since 5.72
404      */
405     QMap<QString, QMap<QString, QString>> mapList(bool *ok) const;
406 
407     /**
408      *  Get a list of all the passwords in the current folder, which can
409      *  be used to populate a list view in a password manager.
410      *
411      *  @param ok if not nullptr, the object this parameter points to will be
412      *            set to true to indicate success or false otherwise. Note that
413      *            the object will be set to false if any of the keys was not
414      *            originally written as a password
415      *
416      *  @return a map of key/value pairs, where the key in the map is the entry key
417      *
418      *  @since 5.72
419      */
420     QMap<QString, QString> passwordList(bool *ok) const;
421 
422     /**
423      *  Write @p key = @p value as a binary entry to the current
424      *  folder.  Be careful with this, it could cause inconsistency
425      *  in the future since you can put an arbitrary entry type in
426      *  place.
427      *  @param key The key of the new entry.
428      *  @param value The value of the entry.
429      *  @param entryType The type of the entry.
430      *  @return Returns 0 on success, non-zero on error.
431      */
432     virtual int writeEntry(const QString &key, const QByteArray &value, EntryType entryType);
433 
434     /**
435      *  Write @p key = @p value as a binary entry to the current
436      *  folder.
437      *  @param key The key of the new entry.
438      *  @param value The value of the entry.
439      *  @return Returns 0 on success, non-zero on error.
440      */
441     virtual int writeEntry(const QString &key, const QByteArray &value);
442 
443     /**
444      *  Write @p key = @p value as a map to the current folder.
445      *  @param key The key of the new entry.
446      *  @param value The value of the map.
447      *  @return Returns 0 on success, non-zero on error.
448      */
449     virtual int writeMap(const QString &key, const QMap<QString, QString> &value);
450 
451     /**
452      *  Write @p key = @p value as a password to the current folder.
453      *  @param key The key of the new entry.
454      *  @param value The value of the password.
455      *  @return Returns 0 on success, non-zero on error.
456      */
457     virtual int writePassword(const QString &key, const QString &value);
458 
459     /**
460      *  Determine if the current folder has they entry @p key.
461      *  @param key The key to search for.
462      *  @return Returns true if the folder contains @p key.
463      */
464     virtual bool hasEntry(const QString &key);
465 
466     /**
467      *  Remove the entry @p key from the current folder.
468      *  @param key The key to remove.
469      *  @return Returns 0 on success, non-zero on error.
470      */
471     virtual int removeEntry(const QString &key);
472 
473     /**
474      *  Determine the type of the entry @p key in this folder.
475      *  @param key The key to look up.
476      *  @return Returns an enumerated type representing the type
477      *          of the entry.
478      */
479     virtual EntryType entryType(const QString &key);
480 
481     /**
482      *  Determine if a folder does not exist in a wallet.  This
483      *  does not require decryption of the wallet.
484      *  This is a handy optimization to avoid prompting the user
485      *  if your data is certainly not in the wallet.
486      *  @param wallet The wallet to look in.
487      *  @param folder The folder to look up.
488      *  @return Returns true if the folder does NOT exist in the
489      *  wallet, or the wallet does not exist.
490      */
491     static bool folderDoesNotExist(const QString &wallet, const QString &folder);
492 
493     /**
494      *  Determine if an entry in a folder does not exist in a
495      *  wallet.  This does not require decryption of the wallet.
496      *  This is a handy optimization to avoid prompting the user
497      *  if your data is certainly not in the wallet.
498      *  @param wallet The wallet to look in.
499      *  @param folder The folder to look in.
500      *  @param key The key to look up.
501      *  @return Returns true if the key does NOT exist in the
502      *  wallet, or the folder or wallet does not exist.
503      */
504     static bool keyDoesNotExist(const QString &wallet, const QString &folder, const QString &key);
505 
506     /**
507      * Determine if the KWallet API is using the KSecretsService infrastructure
508      * This can ben changed in system settings
509      * @return Returns true if the KSecretsService infrastructure is active
510      */
511     static bool isUsingKSecretsService();
512 
513 Q_SIGNALS:
514     /**
515      *  Emitted when this wallet is closed.
516      */
517     void walletClosed();
518 
519     /**
520      *  Emitted when a folder in this wallet is updated.
521      *  @param folder The folder that was updated.
522      */
523     void folderUpdated(const QString &folder);
524 
525     /**
526      *  Emitted when the folder list is changed in this wallet.
527      */
528     void folderListUpdated();
529 
530     /**
531      *  Emitted when a folder in this wallet is removed.
532      *  @param folder The folder that was removed.
533      */
534     void folderRemoved(const QString &folder);
535 
536     /**
537      *  Emitted when a wallet is opened in asynchronous mode.
538      *  @param success True if the wallet was opened successfully.
539      */
540     void walletOpened(bool success);
541 
542 private Q_SLOTS:
543     /**
544      *  @internal
545      *  D-Bus slot for signals emitted by the wallet service.
546      */
547     void slotWalletClosed(int handle);
548 
549     /**
550      *  @internal
551      *  D-Bus slot for signals emitted by the wallet service.
552      */
553     void slotFolderUpdated(const QString &wallet, const QString &folder);
554 
555     /**
556      *  @internal
557      *  D-Bus slot for signals emitted by the wallet service.
558      */
559     void slotFolderListUpdated(const QString &wallet);
560 
561     /**
562      *  @internal
563      *  D-Bus slot for signals emitted by the wallet service.
564      */
565     void slotApplicationDisconnected(const QString &wallet, const QString &application);
566 
567     /**
568      *  @internal
569      *  Callback for kwalletd
570      *  @param tId identifier for the open transaction
571      *  @param handle the wallet's handle
572      */
573     void walletAsyncOpened(int tId, int handle);
574 
575     /**
576      *  @internal
577      *  D-Bus error slot.
578      */
579     void emitWalletAsyncOpenError();
580 
581     /**
582      *  @internal
583      *  Emits wallet opening success.
584      */
585     void emitWalletOpened();
586 
587     /**
588      * @internal
589      * Receives status changed notifications from KSecretsService infrastructure
590      */
591     void slotCollectionStatusChanged(int);
592     /**
593      * @internal
594      * Received delete notification from KSecretsService infrastructure
595      */
596     void slotCollectionDeleted();
597 
598 private:
599     class WalletPrivate;
600     WalletPrivate *const d;
601     Q_PRIVATE_SLOT(d, void walletServiceUnregistered())
602 
603 protected:
604     /**
605      *  @internal
606      */
607     virtual void virtual_hook(int id, void *data);
608 };
609 
610 }
611 
612 #endif //_KWALLET_H
613