1/*
2 * Copyright 2011, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <KeyStore.h>
8
9#include <KeyStoreDefs.h>
10
11#include <Messenger.h>
12#include <Roster.h>
13
14
15using namespace BPrivate;
16
17
18BKeyStore::BKeyStore()
19{
20}
21
22
23BKeyStore::~BKeyStore()
24{
25}
26
27
28// #pragma mark - Key handling
29
30
31status_t
32BKeyStore::GetKey(BKeyType type, const char* identifier, BKey& key)
33{
34	return GetKey(NULL, type, identifier, NULL, true, key);
35}
36
37
38status_t
39BKeyStore::GetKey(BKeyType type, const char* identifier,
40	const char* secondaryIdentifier, BKey& key)
41{
42	return GetKey(NULL, type, identifier, secondaryIdentifier, false, key);
43}
44
45
46status_t
47BKeyStore::GetKey(BKeyType type, const char* identifier,
48	const char* secondaryIdentifier, bool secondaryIdentifierOptional,
49	BKey& key)
50{
51	return GetKey(NULL, type, identifier, secondaryIdentifier,
52		secondaryIdentifierOptional, key);
53}
54
55
56status_t
57BKeyStore::GetKey(const char* keyring, BKeyType type, const char* identifier,
58	BKey& key)
59{
60	return GetKey(keyring, type, identifier, NULL, true, key);
61}
62
63
64status_t
65BKeyStore::GetKey(const char* keyring, BKeyType type, const char* identifier,
66	const char* secondaryIdentifier, BKey& key)
67{
68	return GetKey(keyring, type, identifier, secondaryIdentifier, false, key);
69}
70
71
72status_t
73BKeyStore::GetKey(const char* keyring, BKeyType type, const char* identifier,
74	const char* secondaryIdentifier, bool secondaryIdentifierOptional,
75	BKey& key)
76{
77	BMessage message(KEY_STORE_GET_KEY);
78	message.AddString("keyring", keyring);
79	message.AddUInt32("type", type);
80	message.AddString("identifier", identifier);
81	message.AddString("secondaryIdentifier", secondaryIdentifier);
82	message.AddBool("secondaryIdentifierOptional", secondaryIdentifierOptional);
83
84	BMessage reply;
85	status_t result = _SendKeyMessage(message, &reply);
86	if (result != B_OK)
87		return result;
88
89	BMessage keyMessage;
90	if (reply.FindMessage("key", &keyMessage) != B_OK)
91		return B_ERROR;
92
93	return key.Unflatten(keyMessage);
94}
95
96
97status_t
98BKeyStore::AddKey(const BKey& key)
99{
100	return AddKey(NULL, key);
101}
102
103
104status_t
105BKeyStore::AddKey(const char* keyring, const BKey& key)
106{
107	BMessage keyMessage;
108	if (key.Flatten(keyMessage) != B_OK)
109		return B_BAD_VALUE;
110
111	BMessage message(KEY_STORE_ADD_KEY);
112	message.AddString("keyring", keyring);
113	message.AddMessage("key", &keyMessage);
114
115	return _SendKeyMessage(message, NULL);
116}
117
118
119status_t
120BKeyStore::RemoveKey(const BKey& key)
121{
122	return RemoveKey(NULL, key);
123}
124
125
126status_t
127BKeyStore::RemoveKey(const char* keyring, const BKey& key)
128{
129	BMessage keyMessage;
130	if (key.Flatten(keyMessage) != B_OK)
131		return B_BAD_VALUE;
132
133	BMessage message(KEY_STORE_REMOVE_KEY);
134	message.AddString("keyring", keyring);
135	message.AddMessage("key", &keyMessage);
136
137	return _SendKeyMessage(message, NULL);
138}
139
140
141status_t
142BKeyStore::GetNextKey(uint32& cookie, BKey& key)
143{
144	return GetNextKey(NULL, cookie, key);
145}
146
147
148status_t
149BKeyStore::GetNextKey(BKeyType type, BKeyPurpose purpose, uint32& cookie,
150	BKey& key)
151{
152	return GetNextKey(NULL, type, purpose, cookie, key);
153}
154
155
156status_t
157BKeyStore::GetNextKey(const char* keyring, uint32& cookie, BKey& key)
158{
159	return GetNextKey(keyring, B_KEY_TYPE_ANY, B_KEY_PURPOSE_ANY, cookie, key);
160}
161
162
163status_t
164BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose,
165	uint32& cookie, BKey& key)
166{
167	BMessage message(KEY_STORE_GET_NEXT_KEY);
168	message.AddString("keyring", keyring);
169	message.AddUInt32("type", type);
170	message.AddUInt32("purpose", purpose);
171	message.AddUInt32("cookie", cookie);
172
173	BMessage reply;
174	status_t result = _SendKeyMessage(message, &reply);
175	if (result != B_OK)
176		return result;
177
178	BMessage keyMessage;
179	if (reply.FindMessage("key", &keyMessage) != B_OK)
180		return B_ERROR;
181
182	reply.FindUInt32("cookie", &cookie);
183	return key.Unflatten(keyMessage);
184}
185
186
187// #pragma mark - Keyrings
188
189
190status_t
191BKeyStore::AddKeyring(const char* keyring)
192{
193	BMessage message(KEY_STORE_ADD_KEYRING);
194	message.AddString("keyring", keyring);
195	return _SendKeyMessage(message, NULL);
196}
197
198
199status_t
200BKeyStore::RemoveKeyring(const char* keyring)
201{
202	BMessage message(KEY_STORE_REMOVE_KEYRING);
203	message.AddString("keyring", keyring);
204	return _SendKeyMessage(message, NULL);
205}
206
207
208status_t
209BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring)
210{
211	BMessage message(KEY_STORE_GET_NEXT_KEYRING);
212	message.AddUInt32("cookie", cookie);
213
214	BMessage reply;
215	status_t result = _SendKeyMessage(message, &reply);
216	if (result != B_OK)
217		return result;
218
219	if (reply.FindString("keyring", &keyring) != B_OK)
220		return B_ERROR;
221
222	reply.FindUInt32("cookie", &cookie);
223	return B_OK;
224}
225
226
227status_t
228BKeyStore::SetUnlockKey(const char* keyring, const BKey& key)
229{
230	BMessage keyMessage;
231	if (key.Flatten(keyMessage) != B_OK)
232		return B_BAD_VALUE;
233
234	BMessage message(KEY_STORE_SET_UNLOCK_KEY);
235	message.AddString("keyring", keyring);
236	message.AddMessage("key", &keyMessage);
237
238	return _SendKeyMessage(message, NULL);
239}
240
241
242status_t
243BKeyStore::RemoveUnlockKey(const char* keyring)
244{
245	BMessage message(KEY_STORE_REMOVE_UNLOCK_KEY);
246	message.AddString("keyring", keyring);
247	return _SendKeyMessage(message, NULL);
248}
249
250
251// #pragma mark - Master key
252
253
254status_t
255BKeyStore::SetMasterUnlockKey(const BKey& key)
256{
257	return SetUnlockKey(NULL, key);
258}
259
260
261status_t
262BKeyStore::RemoveMasterUnlockKey()
263{
264	return RemoveUnlockKey(NULL);
265}
266
267
268status_t
269BKeyStore::AddKeyringToMaster(const char* keyring)
270{
271	BMessage message(KEY_STORE_ADD_KEYRING_TO_MASTER);
272	message.AddString("keyring", keyring);
273	return _SendKeyMessage(message, NULL);
274}
275
276
277status_t
278BKeyStore::RemoveKeyringFromMaster(const char* keyring)
279{
280	BMessage message(KEY_STORE_REMOVE_KEYRING_FROM_MASTER);
281	message.AddString("keyring", keyring);
282	return _SendKeyMessage(message, NULL);
283}
284
285
286status_t
287BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring)
288{
289	BMessage message(KEY_STORE_GET_NEXT_MASTER_KEYRING);
290	message.AddUInt32("cookie", cookie);
291
292	BMessage reply;
293	status_t result = _SendKeyMessage(message, &reply);
294	if (result != B_OK)
295		return result;
296
297	if (reply.FindString("keyring", &keyring) != B_OK)
298		return B_ERROR;
299
300	reply.FindUInt32("cookie", &cookie);
301	return B_OK;
302}
303
304
305// #pragma mark - Locking
306
307
308bool
309BKeyStore::IsKeyringUnlocked(const char* keyring)
310{
311	BMessage message(KEY_STORE_IS_KEYRING_UNLOCKED);
312	message.AddString("keyring", keyring);
313
314	BMessage reply;
315	if (_SendKeyMessage(message, &reply) != B_OK)
316		return false;
317
318	bool unlocked;
319	if (reply.FindBool("unlocked", &unlocked) != B_OK)
320		return false;
321
322	return unlocked;
323}
324
325
326status_t
327BKeyStore::LockKeyring(const char* keyring)
328{
329	BMessage message(KEY_STORE_LOCK_KEYRING);
330	message.AddString("keyring", keyring);
331	return _SendKeyMessage(message, NULL);
332}
333
334
335status_t
336BKeyStore::LockMasterKeyring()
337{
338	return LockKeyring(NULL);
339}
340
341
342
343// #pragma mark - Applications
344
345
346status_t
347BKeyStore::GetNextApplication(uint32& cookie, BString& signature) const
348{
349	return GetNextApplication(NULL, cookie, signature);
350}
351
352
353status_t
354BKeyStore::GetNextApplication(const char* keyring, uint32& cookie,
355	BString& signature) const
356{
357	BMessage message(KEY_STORE_GET_NEXT_APPLICATION);
358	message.AddString("keyring", keyring);
359	message.AddUInt32("cookie", cookie);
360
361	BMessage reply;
362	status_t result = _SendKeyMessage(message, &reply);
363	if (result != B_OK)
364		return result;
365
366	if (reply.FindString("signature", &signature) != B_OK)
367		return B_ERROR;
368
369	reply.FindUInt32("cookie", &cookie);
370	return B_OK;
371}
372
373
374status_t
375BKeyStore::RemoveApplication(const char* signature)
376{
377	return RemoveApplication(NULL, signature);
378}
379
380
381status_t
382BKeyStore::RemoveApplication(const char* keyring, const char* signature)
383{
384	BMessage message(KEY_STORE_REMOVE_APPLICATION);
385	message.AddString("keyring", keyring);
386	message.AddString("signature", signature);
387
388	return _SendKeyMessage(message, NULL);
389}
390
391
392// #pragma mark - Service functions
393
394
395status_t
396BKeyStore::GeneratePassword(BPasswordKey& password, size_t length, uint32 flags)
397{
398	return B_ERROR;
399}
400
401
402float
403BKeyStore::PasswordStrength(const char* password)
404{
405	return 0;
406}
407
408
409// #pragma mark - Private functions
410
411
412status_t
413BKeyStore::_SendKeyMessage(BMessage& message, BMessage* reply) const
414{
415	BMessage localReply;
416	if (reply == NULL)
417		reply = &localReply;
418
419	BMessenger messenger(kKeyStoreServerSignature);
420	if (!messenger.IsValid()) {
421		// Try to start the keystore server.
422		status_t result = be_roster->Launch(kKeyStoreServerSignature);
423		if (result != B_OK && result != B_ALREADY_RUNNING)
424			return B_ERROR;
425
426		// Then re-target the messenger and check again.
427		messenger.SetTo(kKeyStoreServerSignature);
428		if (!messenger.IsValid())
429			return B_ERROR;
430	}
431
432	if (messenger.SendMessage(&message, reply) != B_OK)
433		return B_ERROR;
434
435	if (reply->what != KEY_STORE_SUCCESS) {
436		status_t result = B_ERROR;
437		if (reply->FindInt32("result", &result) != B_OK)
438			return B_ERROR;
439
440		return result;
441	}
442
443	return B_OK;
444}
445