1 | /****************************************************************************** |
2 | * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * |
3 | * * |
4 | * This program is distributed in the hope that it will be useful, but * |
5 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * |
6 | * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * |
7 | * details, check the accompanying file 'COPYING'. * |
8 | *****************************************************************************/ |
9 | #ifndef KEYCHAIN_H |
10 | #define KEYCHAIN_H |
11 | |
12 | #if !defined(QTKEYCHAIN_NO_EXPORT) |
13 | #include "qkeychain_export.h" |
14 | #else |
15 | #define QKEYCHAIN_EXPORT |
16 | #endif |
17 | |
18 | #include <QtCore/QObject> |
19 | #include <QtCore/QString> |
20 | |
21 | class QSettings; |
22 | |
23 | #define QTKEYCHAIN_VERSION 0x000100 |
24 | |
25 | namespace QKeychain { |
26 | |
27 | /** |
28 | * Error codes |
29 | */ |
30 | enum Error { |
31 | NoError=0, /**< No error occurred, operation was successful */ |
32 | EntryNotFound, /**< For the given key no data was found */ |
33 | CouldNotDeleteEntry, /**< Could not delete existing secret data */ |
34 | AccessDeniedByUser, /**< User denied access to keychain */ |
35 | AccessDenied, /**< Access denied for other reasons */ |
36 | NoBackendAvailable, /**< No platform-specific keychain service available */ |
37 | NotImplemented, /**< Not implemented on platform */ |
38 | OtherError /**< Something else went wrong (errorString() might provide details) */ |
39 | }; |
40 | |
41 | class JobExecutor; |
42 | class JobPrivate; |
43 | |
44 | /** |
45 | * @brief Abstract base class for all QKeychain jobs. |
46 | */ |
47 | class QKEYCHAIN_EXPORT Job : public QObject { |
48 | Q_OBJECT |
49 | public: |
50 | ~Job() override; |
51 | |
52 | /** |
53 | * @return The QSettings instance used as plaintext storage if insecureFallback() is true. |
54 | * @see setSettings() |
55 | * @see insecureFallback() |
56 | */ |
57 | QSettings* settings() const; |
58 | |
59 | /** |
60 | * @return Set the QSettings instance that will be used as plaintext storage if insecureFallback() is true. |
61 | * @see settings() |
62 | * @see insecureFallback() |
63 | */ |
64 | void setSettings( QSettings* settings ); |
65 | |
66 | /** |
67 | * Call this method to start the job. |
68 | * Typically you want to connect some slot to the finished() signal first: |
69 | * |
70 | * \code |
71 | * SomeClass::startJob() |
72 | * { |
73 | * connect(job, &Job::finished, this, &SomeClass::slotJobFinished); |
74 | * job->start(); |
75 | * } |
76 | * |
77 | * SomeClass::slotJobFinished(Job *job) |
78 | * { |
79 | * if (job->error()) { |
80 | * // handle error |
81 | * } else { |
82 | * // do job-specific stuff |
83 | * } |
84 | * } |
85 | * \endcode |
86 | * |
87 | * @see finished() |
88 | */ |
89 | void start(); |
90 | |
91 | QString service() const; |
92 | |
93 | /** |
94 | * @note Call this method only after finished() has been emitted. |
95 | * @return The error code of the job (0 if no error). |
96 | */ |
97 | Error error() const; |
98 | |
99 | /** |
100 | * @return An error message that might provide details if error() returns OtherError. |
101 | */ |
102 | QString errorString() const; |
103 | |
104 | /** |
105 | * @return Whether this job autodeletes itself once finished() has been emitted. Default is true. |
106 | * @see setAutoDelete() |
107 | */ |
108 | bool autoDelete() const; |
109 | |
110 | /** |
111 | * Set whether this job should autodelete itself once finished() has been emitted. |
112 | * @see autoDelete() |
113 | */ |
114 | void setAutoDelete( bool autoDelete ); |
115 | |
116 | /** |
117 | * @return Whether this job will use plaintext storage on unsupported platforms. Default is false. |
118 | * @see setInsecureFallback() |
119 | */ |
120 | bool insecureFallback() const; |
121 | |
122 | /** |
123 | * Set whether this job should use plaintext storage on unsupported platforms. |
124 | * @see insecureFallback() |
125 | */ |
126 | void setInsecureFallback( bool insecureFallback ); |
127 | |
128 | /** |
129 | * @return The string used as key by this job. |
130 | * @see setKey() |
131 | */ |
132 | QString key() const; |
133 | |
134 | /** |
135 | * Set the @p key that this job will use to read or write data from/to the keychain. |
136 | * The key can be an empty string. |
137 | * @see key() |
138 | */ |
139 | void setKey( const QString& key ); |
140 | |
141 | void emitFinished(); |
142 | void emitFinishedWithError(Error, const QString& errorString); |
143 | |
144 | Q_SIGNALS: |
145 | /** |
146 | * Emitted when this job is finished. |
147 | * You can connect to this signal to be notified about the job's completion. |
148 | * @see start() |
149 | */ |
150 | void finished( QKeychain::Job* ); |
151 | |
152 | protected: |
153 | explicit Job( JobPrivate *q, QObject* parent=nullptr ); |
154 | Q_INVOKABLE void doStart(); |
155 | |
156 | private: |
157 | void setError( Error error ); |
158 | void setErrorString( const QString& errorString ); |
159 | |
160 | void scheduledStart(); |
161 | |
162 | protected: |
163 | JobPrivate* const d; |
164 | |
165 | friend class JobExecutor; |
166 | friend class JobPrivate; |
167 | friend class ReadPasswordJobPrivate; |
168 | friend class WritePasswordJobPrivate; |
169 | friend class DeletePasswordJobPrivate; |
170 | }; |
171 | |
172 | class ReadPasswordJobPrivate; |
173 | |
174 | /** |
175 | * @brief Job for reading secrets from the keychain. |
176 | * You can use a ReadPasswordJob to read passwords or binary data from the keychain. |
177 | * This job requires a "service" string, which is basically a namespace of keys within the keychain. |
178 | * This means that you can read all the pairs <key, secret> stored in the same service string. |
179 | */ |
180 | class QKEYCHAIN_EXPORT ReadPasswordJob : public Job { |
181 | Q_OBJECT |
182 | public: |
183 | /** |
184 | * Create a new ReadPasswordJob. |
185 | * @param service The service string used by this job (can be empty). |
186 | * @param parent The parent of this job. |
187 | */ |
188 | explicit ReadPasswordJob( const QString& service, QObject* parent=nullptr ); |
189 | ~ReadPasswordJob() override; |
190 | |
191 | /** |
192 | * @return The binary data stored as value of this job's key(). |
193 | * @see Job::key() |
194 | */ |
195 | QByteArray binaryData() const; |
196 | |
197 | /** |
198 | * @return The string stored as value of this job's key(). |
199 | * @see Job::key() |
200 | * @warning Returns meaningless data if the data was stored as binary data. |
201 | * @see WritePasswordJob::setTextData() |
202 | */ |
203 | QString textData() const; |
204 | |
205 | private: |
206 | friend class QKeychain::ReadPasswordJobPrivate; |
207 | }; |
208 | |
209 | class WritePasswordJobPrivate; |
210 | |
211 | /** |
212 | * @brief Job for writing secrets to the keychain. |
213 | * You can use a WritePasswordJob to store passwords or binary data in the keychain. |
214 | * This job requires a "service" string, which is basically a namespace of keys within the keychain. |
215 | * This means that you can store different pairs <key, secret> under the same service string. |
216 | */ |
217 | class QKEYCHAIN_EXPORT WritePasswordJob : public Job { |
218 | Q_OBJECT |
219 | public: |
220 | /** |
221 | * Create a new WritePasswordJob. |
222 | * @param service The service string used by this job (can be empty). |
223 | * @param parent The parent of this job. |
224 | */ |
225 | explicit WritePasswordJob( const QString& service, QObject* parent=nullptr ); |
226 | ~WritePasswordJob() override; |
227 | |
228 | /** |
229 | * Set the @p data that the job will store in the keychain as binary data. |
230 | * @warning setBinaryData() and setTextData() are mutually exclusive. |
231 | */ |
232 | void setBinaryData( const QByteArray& data ); |
233 | |
234 | /** |
235 | * Set the @p data that the job will store in the keychain as string. |
236 | * Typically @p data is a password. |
237 | * @warning setBinaryData() and setTextData() are mutually exclusive. |
238 | */ |
239 | void setTextData( const QString& data ); |
240 | |
241 | private: |
242 | |
243 | friend class QKeychain::WritePasswordJobPrivate; |
244 | }; |
245 | |
246 | class DeletePasswordJobPrivate; |
247 | |
248 | /** |
249 | * @brief Job for deleting secrets from the keychain. |
250 | * You can use a DeletePasswordJob to delete passwords or binary data from the keychain. |
251 | * This job requires a "service" string, which is basically a namespace of keys within the keychain. |
252 | * This means that you can delete all the pairs <key, secret> stored in the same service string. |
253 | */ |
254 | class QKEYCHAIN_EXPORT DeletePasswordJob : public Job { |
255 | Q_OBJECT |
256 | public: |
257 | /** |
258 | * Create a new DeletePasswordJob. |
259 | * @param service The service string used by this job (can be empty). |
260 | * @param parent The parent of this job. |
261 | */ |
262 | explicit DeletePasswordJob( const QString& service, QObject* parent=nullptr ); |
263 | ~DeletePasswordJob() override; |
264 | |
265 | private: |
266 | friend class QKeychain::DeletePasswordJobPrivate; |
267 | }; |
268 | |
269 | /** |
270 | * Checks whether there is a viable secure backend available. |
271 | * This particularly matters on UNIX platforms where multiple different backends |
272 | * exist and none might be available. |
273 | * |
274 | * Note that using the insecure fallback will work even if no secure backend is available. |
275 | * |
276 | * @since 0.14.0 |
277 | */ |
278 | QKEYCHAIN_EXPORT bool isAvailable(); |
279 | |
280 | } // namespace QtKeychain |
281 | |
282 | #endif |
283 | |