1 /*
2 * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "KeyStoreServer.h"
8
9 #include "AppAccessRequestWindow.h"
10 #include "KeyRequestWindow.h"
11 #include "Keyring.h"
12
13 #include <KeyStoreDefs.h>
14
15 #include <Directory.h>
16 #include <Entry.h>
17 #include <FindDirectory.h>
18 #include <Path.h>
19 #include <Roster.h>
20 #include <String.h>
21
22 #include <new>
23
24 #include <stdio.h>
25
26
27 using namespace BPrivate;
28
29
30 static const char* kMasterKeyringName = "Master";
31 static const char* kKeyringKeysIdentifier = "Keyrings";
32
33 static const uint32 kKeyStoreFormatVersion = 1;
34
35 static const uint32 kFlagGetKey = 0x0001;
36 static const uint32 kFlagEnumerateKeys = 0x0002;
37 static const uint32 kFlagAddKey = 0x0004;
38 static const uint32 kFlagRemoveKey = 0x0008;
39 static const uint32 kFlagAddKeyring = 0x0010;
40 static const uint32 kFlagRemoveKeyring = 0x0020;
41 static const uint32 kFlagEnumerateKeyrings = 0x0040;
42 static const uint32 kFlagSetUnlockKey = 0x0080;
43 static const uint32 kFlagRemoveUnlockKey = 0x0100;
44 static const uint32 kFlagAddKeyringsToMaster = 0x0200;
45 static const uint32 kFlagRemoveKeyringsFromMaster = 0x0400;
46 static const uint32 kFlagEnumerateMasterKeyrings = 0x0800;
47 static const uint32 kFlagQueryLockState = 0x1000;
48 static const uint32 kFlagLockKeyring = 0x2000;
49 static const uint32 kFlagEnumerateApplications = 0x4000;
50 static const uint32 kFlagRemoveApplications = 0x8000;
51
52 static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys
53 | kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring
54 | kFlagEnumerateKeyrings | kFlagSetUnlockKey | kFlagRemoveUnlockKey
55 | kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster
56 | kFlagEnumerateMasterKeyrings | kFlagQueryLockState | kFlagLockKeyring
57 | kFlagEnumerateApplications | kFlagRemoveApplications;
58
59
KeyStoreServer()60 KeyStoreServer::KeyStoreServer()
61 :
62 BApplication(kKeyStoreServerSignature),
63 fMasterKeyring(NULL),
64 fKeyrings(20, true)
65 {
66 BPath path;
67 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
68 return;
69
70 BDirectory settingsDir(path.Path());
71 path.Append("system");
72 if (!settingsDir.Contains(path.Path()))
73 settingsDir.CreateDirectory(path.Path(), NULL);
74
75 settingsDir.SetTo(path.Path());
76 path.Append("keystore");
77 if (!settingsDir.Contains(path.Path()))
78 settingsDir.CreateDirectory(path.Path(), NULL);
79
80 settingsDir.SetTo(path.Path());
81 path.Append("keystore_database");
82
83 fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE
84 | (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE));
85
86 _ReadKeyStoreDatabase();
87
88 if (fMasterKeyring == NULL) {
89 fMasterKeyring = new(std::nothrow) Keyring(kMasterKeyringName);
90 fKeyrings.BinaryInsert(fMasterKeyring, &Keyring::Compare);
91 }
92 }
93
94
~KeyStoreServer()95 KeyStoreServer::~KeyStoreServer()
96 {
97 }
98
99
100 void
MessageReceived(BMessage * message)101 KeyStoreServer::MessageReceived(BMessage* message)
102 {
103 BMessage reply;
104 status_t result = B_UNSUPPORTED;
105 app_info callingAppInfo;
106
107 uint32 accessFlags = _AccessFlagsFor(message->what);
108 if (accessFlags == 0)
109 message->what = 0;
110
111 if (message->what != 0) {
112 result = _ResolveCallingApp(*message, callingAppInfo);
113 if (result != B_OK)
114 message->what = 0;
115 }
116
117 // Resolve the keyring for the relevant messages.
118 Keyring* keyring = NULL;
119 switch (message->what) {
120 case KEY_STORE_GET_KEY:
121 case KEY_STORE_GET_NEXT_KEY:
122 case KEY_STORE_ADD_KEY:
123 case KEY_STORE_REMOVE_KEY:
124 case KEY_STORE_IS_KEYRING_UNLOCKED:
125 case KEY_STORE_LOCK_KEYRING:
126 case KEY_STORE_SET_UNLOCK_KEY:
127 case KEY_STORE_REMOVE_UNLOCK_KEY:
128 case KEY_STORE_ADD_KEYRING_TO_MASTER:
129 case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
130 case KEY_STORE_GET_NEXT_APPLICATION:
131 case KEY_STORE_REMOVE_APPLICATION:
132 {
133 BString keyringName;
134 if (message->FindString("keyring", &keyringName) != B_OK)
135 keyringName = "";
136
137 keyring = _FindKeyring(keyringName);
138 if (keyring == NULL) {
139 result = B_BAD_VALUE;
140 message->what = 0;
141 // So that we don't do anything in the second switch.
142 break;
143 }
144
145 switch (message->what) {
146 case KEY_STORE_GET_KEY:
147 case KEY_STORE_GET_NEXT_KEY:
148 case KEY_STORE_ADD_KEY:
149 case KEY_STORE_REMOVE_KEY:
150 case KEY_STORE_SET_UNLOCK_KEY:
151 case KEY_STORE_REMOVE_UNLOCK_KEY:
152 case KEY_STORE_ADD_KEYRING_TO_MASTER:
153 case KEY_STORE_GET_NEXT_APPLICATION:
154 case KEY_STORE_REMOVE_APPLICATION:
155 {
156 // These need keyring access to do anything.
157 while (!keyring->IsUnlocked()) {
158 status_t unlockResult = _UnlockKeyring(*keyring);
159 if (unlockResult != B_OK) {
160 result = unlockResult;
161 message->what = 0;
162 break;
163 }
164 }
165
166 status_t validateResult = _ValidateAppAccess(*keyring,
167 callingAppInfo, accessFlags);
168 if (validateResult != B_OK) {
169 result = validateResult;
170 message->what = 0;
171 break;
172 }
173
174 break;
175 }
176 }
177
178 break;
179 }
180 }
181
182 switch (message->what) {
183 case KEY_STORE_GET_KEY:
184 {
185 BString identifier;
186 if (message->FindString("identifier", &identifier) != B_OK) {
187 result = B_BAD_VALUE;
188 break;
189 }
190
191 bool secondaryIdentifierOptional;
192 if (message->FindBool("secondaryIdentifierOptional",
193 &secondaryIdentifierOptional) != B_OK) {
194 secondaryIdentifierOptional = false;
195 }
196
197 BString secondaryIdentifier;
198 if (message->FindString("secondaryIdentifier",
199 &secondaryIdentifier) != B_OK) {
200 secondaryIdentifier = "";
201 secondaryIdentifierOptional = true;
202 }
203
204 BMessage keyMessage;
205 result = keyring->FindKey(identifier, secondaryIdentifier,
206 secondaryIdentifierOptional, &keyMessage);
207 if (result == B_OK)
208 reply.AddMessage("key", &keyMessage);
209
210 break;
211 }
212
213 case KEY_STORE_GET_NEXT_KEY:
214 {
215 BKeyType type;
216 BKeyPurpose purpose;
217 uint32 cookie;
218 if (message->FindUInt32("type", (uint32*)&type) != B_OK
219 || message->FindUInt32("purpose", (uint32*)&purpose) != B_OK
220 || message->FindUInt32("cookie", &cookie) != B_OK) {
221 result = B_BAD_VALUE;
222 break;
223 }
224
225 BMessage keyMessage;
226 result = keyring->FindKey(type, purpose, cookie, keyMessage);
227 if (result == B_OK) {
228 cookie++;
229 reply.AddUInt32("cookie", cookie);
230 reply.AddMessage("key", &keyMessage);
231 }
232
233 break;
234 }
235
236 case KEY_STORE_ADD_KEY:
237 {
238 BMessage keyMessage;
239 BString identifier;
240 if (message->FindMessage("key", &keyMessage) != B_OK
241 || keyMessage.FindString("identifier", &identifier) != B_OK) {
242 result = B_BAD_VALUE;
243 break;
244 }
245
246 BString secondaryIdentifier;
247 if (keyMessage.FindString("secondaryIdentifier",
248 &secondaryIdentifier) != B_OK) {
249 secondaryIdentifier = "";
250 }
251
252 result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage);
253 if (result == B_OK)
254 _WriteKeyStoreDatabase();
255
256 break;
257 }
258
259 case KEY_STORE_REMOVE_KEY:
260 {
261 BMessage keyMessage;
262 BString identifier;
263 if (message->FindMessage("key", &keyMessage) != B_OK
264 || keyMessage.FindString("identifier", &identifier) != B_OK) {
265 result = B_BAD_VALUE;
266 break;
267 }
268
269 result = keyring->RemoveKey(identifier, keyMessage);
270 if (result == B_OK)
271 _WriteKeyStoreDatabase();
272
273 break;
274 }
275
276 case KEY_STORE_ADD_KEYRING:
277 {
278 BMessage keyMessage;
279 BString keyring;
280 if (message->FindString("keyring", &keyring) != B_OK) {
281 result = B_BAD_VALUE;
282 break;
283 }
284
285 result = _AddKeyring(keyring);
286 if (result == B_OK)
287 _WriteKeyStoreDatabase();
288
289 break;
290 }
291
292 case KEY_STORE_REMOVE_KEYRING:
293 {
294 BString keyringName;
295 if (message->FindString("keyring", &keyringName) != B_OK)
296 keyringName = "";
297
298 result = _RemoveKeyring(keyringName);
299 if (result == B_OK)
300 _WriteKeyStoreDatabase();
301
302 break;
303 }
304
305 case KEY_STORE_GET_NEXT_KEYRING:
306 {
307 uint32 cookie;
308 if (message->FindUInt32("cookie", &cookie) != B_OK) {
309 result = B_BAD_VALUE;
310 break;
311 }
312
313 keyring = fKeyrings.ItemAt(cookie);
314 if (keyring == NULL) {
315 result = B_ENTRY_NOT_FOUND;
316 break;
317 }
318
319 cookie++;
320 reply.AddUInt32("cookie", cookie);
321 reply.AddString("keyring", keyring->Name());
322 result = B_OK;
323 break;
324 }
325
326 case KEY_STORE_IS_KEYRING_UNLOCKED:
327 {
328 reply.AddBool("unlocked", keyring->IsUnlocked());
329 result = B_OK;
330 break;
331 }
332
333 case KEY_STORE_LOCK_KEYRING:
334 {
335 keyring->Lock();
336 result = B_OK;
337 break;
338 }
339
340 case KEY_STORE_SET_UNLOCK_KEY:
341 {
342 BMessage keyMessage;
343 if (message->FindMessage("key", &keyMessage) != B_OK) {
344 result = B_BAD_VALUE;
345 break;
346 }
347
348 result = keyring->SetUnlockKey(keyMessage);
349 if (result == B_OK)
350 _WriteKeyStoreDatabase();
351
352 // TODO: Update the key in the master if this keyring was added.
353 break;
354 }
355
356 case KEY_STORE_REMOVE_UNLOCK_KEY:
357 {
358 result = keyring->RemoveUnlockKey();
359 if (result == B_OK)
360 _WriteKeyStoreDatabase();
361
362 break;
363 }
364
365 case KEY_STORE_ADD_KEYRING_TO_MASTER:
366 case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
367 {
368 // We also need access to the master keyring.
369 while (!fMasterKeyring->IsUnlocked()) {
370 status_t unlockResult = _UnlockKeyring(*fMasterKeyring);
371 if (unlockResult != B_OK) {
372 result = unlockResult;
373 message->what = 0;
374 break;
375 }
376 }
377
378 if (message->what == 0)
379 break;
380
381 BString secondaryIdentifier = keyring->Name();
382 BMessage keyMessage = keyring->UnlockKey();
383 keyMessage.RemoveName("identifier");
384 keyMessage.AddString("identifier", kKeyringKeysIdentifier);
385 keyMessage.RemoveName("secondaryIdentifier");
386 keyMessage.AddString("secondaryIdentifier", secondaryIdentifier);
387
388 switch (message->what) {
389 case KEY_STORE_ADD_KEYRING_TO_MASTER:
390 result = fMasterKeyring->AddKey(kKeyringKeysIdentifier,
391 secondaryIdentifier, keyMessage);
392 break;
393
394 case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
395 result = fMasterKeyring->RemoveKey(kKeyringKeysIdentifier,
396 keyMessage);
397 break;
398 }
399
400 if (result == B_OK)
401 _WriteKeyStoreDatabase();
402
403 break;
404 }
405
406 case KEY_STORE_GET_NEXT_APPLICATION:
407 {
408 uint32 cookie;
409 if (message->FindUInt32("cookie", &cookie) != B_OK) {
410 result = B_BAD_VALUE;
411 break;
412 }
413
414 BString signature;
415 BString path;
416 result = keyring->GetNextApplication(cookie, signature, path);
417 if (result != B_OK)
418 break;
419
420 reply.AddUInt32("cookie", cookie);
421 reply.AddString("signature", signature);
422 reply.AddString("path", path);
423 result = B_OK;
424 break;
425 }
426
427 case KEY_STORE_REMOVE_APPLICATION:
428 {
429 const char* signature = NULL;
430 const char* path = NULL;
431
432 if (message->FindString("signature", &signature) != B_OK) {
433 result = B_BAD_VALUE;
434 break;
435 }
436
437 if (message->FindString("path", &path) != B_OK)
438 path = NULL;
439
440 result = keyring->RemoveApplication(signature, path);
441 if (result == B_OK)
442 _WriteKeyStoreDatabase();
443
444 break;
445 }
446
447 case 0:
448 {
449 // Just the error case from above.
450 break;
451 }
452
453 default:
454 {
455 printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n",
456 message->what, (const char*)&message->what);
457 break;
458 }
459 }
460
461 if (message->IsSourceWaiting()) {
462 if (result == B_OK)
463 reply.what = KEY_STORE_SUCCESS;
464 else {
465 reply.what = KEY_STORE_RESULT;
466 reply.AddInt32("result", result);
467 }
468
469 message->SendReply(&reply);
470 }
471 }
472
473
474 status_t
_ReadKeyStoreDatabase()475 KeyStoreServer::_ReadKeyStoreDatabase()
476 {
477 BMessage keystore;
478 status_t result = keystore.Unflatten(&fKeyStoreFile);
479 if (result != B_OK) {
480 printf("failed to read keystore database\n");
481 _WriteKeyStoreDatabase();
482 // Reinitializes the database.
483 return result;
484 }
485
486 int32 index = 0;
487 BMessage keyringData;
488 while (keystore.FindMessage("keyrings", index++, &keyringData) == B_OK) {
489 Keyring* keyring = new(std::nothrow) Keyring();
490 if (keyring == NULL) {
491 printf("no memory for allocating keyring\n");
492 break;
493 }
494
495 status_t result = keyring->ReadFromMessage(keyringData);
496 if (result != B_OK) {
497 printf("failed to read keyring from data\n");
498 delete keyring;
499 continue;
500 }
501
502 if (strcmp(keyring->Name(), kMasterKeyringName) == 0)
503 fMasterKeyring = keyring;
504
505 fKeyrings.BinaryInsert(keyring, &Keyring::Compare);
506 }
507
508 return B_OK;
509 }
510
511
512 status_t
_WriteKeyStoreDatabase()513 KeyStoreServer::_WriteKeyStoreDatabase()
514 {
515 BMessage keystore;
516 keystore.AddUInt32("format", kKeyStoreFormatVersion);
517
518 for (int32 i = 0; i < fKeyrings.CountItems(); i++) {
519 Keyring* keyring = fKeyrings.ItemAt(i);
520 if (keyring == NULL)
521 continue;
522
523 BMessage keyringData;
524 status_t result = keyring->WriteToMessage(keyringData);
525 if (result != B_OK)
526 return result;
527
528 keystore.AddMessage("keyrings", &keyringData);
529 }
530
531 fKeyStoreFile.SetSize(0);
532 fKeyStoreFile.Seek(0, SEEK_SET);
533 return keystore.Flatten(&fKeyStoreFile);
534 }
535
536
537 uint32
_AccessFlagsFor(uint32 command) const538 KeyStoreServer::_AccessFlagsFor(uint32 command) const
539 {
540 switch (command) {
541 case KEY_STORE_GET_KEY:
542 return kFlagGetKey;
543 case KEY_STORE_GET_NEXT_KEY:
544 return kFlagEnumerateKeys;
545 case KEY_STORE_ADD_KEY:
546 return kFlagAddKey;
547 case KEY_STORE_REMOVE_KEY:
548 return kFlagRemoveKey;
549 case KEY_STORE_ADD_KEYRING:
550 return kFlagAddKeyring;
551 case KEY_STORE_REMOVE_KEYRING:
552 return kFlagRemoveKeyring;
553 case KEY_STORE_GET_NEXT_KEYRING:
554 return kFlagEnumerateKeyrings;
555 case KEY_STORE_SET_UNLOCK_KEY:
556 return kFlagSetUnlockKey;
557 case KEY_STORE_REMOVE_UNLOCK_KEY:
558 return kFlagRemoveUnlockKey;
559 case KEY_STORE_ADD_KEYRING_TO_MASTER:
560 return kFlagAddKeyringsToMaster;
561 case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
562 return kFlagRemoveKeyringsFromMaster;
563 case KEY_STORE_GET_NEXT_MASTER_KEYRING:
564 return kFlagEnumerateMasterKeyrings;
565 case KEY_STORE_IS_KEYRING_UNLOCKED:
566 return kFlagQueryLockState;
567 case KEY_STORE_LOCK_KEYRING:
568 return kFlagLockKeyring;
569 case KEY_STORE_GET_NEXT_APPLICATION:
570 return kFlagEnumerateApplications;
571 case KEY_STORE_REMOVE_APPLICATION:
572 return kFlagRemoveApplications;
573 }
574
575 return 0;
576 }
577
578
579 const char*
_AccessStringFor(uint32 accessFlag) const580 KeyStoreServer::_AccessStringFor(uint32 accessFlag) const
581 {
582 switch (accessFlag) {
583 case kFlagGetKey:
584 return "Get keys from the keyring.";
585 case kFlagEnumerateKeys:
586 return "Enumerate and get keys from the keyring.";
587 case kFlagAddKey:
588 return "Add keys to the keyring.";
589 case kFlagRemoveKey:
590 return "Remove keys from the keyring.";
591 case kFlagAddKeyring:
592 return "Add new keyrings.";
593 case kFlagRemoveKeyring:
594 return "Remove keyrings.";
595 case kFlagEnumerateKeyrings:
596 return "Enumerate the available keyrings.";
597 case kFlagSetUnlockKey:
598 return "Set the unlock key of the keyring.";
599 case kFlagRemoveUnlockKey:
600 return "Remove the unlock key of the keyring.";
601 case kFlagAddKeyringsToMaster:
602 return "Add the keyring key to the master keyring.";
603 case kFlagRemoveKeyringsFromMaster:
604 return "Remove the keyring key from the master keyring.";
605 case kFlagEnumerateMasterKeyrings:
606 return "Enumerate keyrings added to the master keyring.";
607 case kFlagQueryLockState:
608 return "Query the lock state of the keyring.";
609 case kFlagLockKeyring:
610 return "Lock the keyring.";
611 case kFlagEnumerateApplications:
612 return "Enumerate the applications of the keyring.";
613 case kFlagRemoveApplications:
614 return "Remove applications from the keyring.";
615 }
616
617 return NULL;
618 }
619
620
621 status_t
_ResolveCallingApp(const BMessage & message,app_info & callingAppInfo) const622 KeyStoreServer::_ResolveCallingApp(const BMessage& message,
623 app_info& callingAppInfo) const
624 {
625 team_id callingTeam = message.ReturnAddress().Team();
626 status_t result = be_roster->GetRunningAppInfo(callingTeam,
627 &callingAppInfo);
628 if (result != B_OK)
629 return result;
630
631 // Do some sanity checks.
632 if (callingAppInfo.team != callingTeam)
633 return B_ERROR;
634
635 return B_OK;
636 }
637
638
639 status_t
_ValidateAppAccess(Keyring & keyring,const app_info & appInfo,uint32 accessFlags)640 KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo,
641 uint32 accessFlags)
642 {
643 BMessage appMessage;
644 BPath path(&appInfo.ref);
645 status_t result = keyring.FindApplication(appInfo.signature,
646 path.Path(), appMessage);
647 if (result != B_OK && result != B_ENTRY_NOT_FOUND)
648 return result;
649
650 // TODO: Implement running image checksum mechanism.
651 BString checksum = path.Path();
652
653 bool appIsNew = false;
654 bool appWasUpdated = false;
655 uint32 appFlags = 0;
656 BString appSum = "";
657 if (result == B_OK) {
658 if (appMessage.FindUInt32("flags", &appFlags) != B_OK
659 || appMessage.FindString("checksum", &appSum) != B_OK) {
660 appIsNew = true;
661 appFlags = 0;
662 } else if (appSum != checksum) {
663 appWasUpdated = true;
664 appFlags = 0;
665 }
666 } else
667 appIsNew = true;
668
669 if ((accessFlags & appFlags) == accessFlags)
670 return B_OK;
671
672 const char* accessString = _AccessStringFor(accessFlags);
673 bool allowAlways = false;
674 result = _RequestAppAccess(keyring.Name(), appInfo.signature, path.Path(),
675 accessString, appIsNew, appWasUpdated, accessFlags, allowAlways);
676 if (result != B_OK || !allowAlways)
677 return result;
678
679 appMessage.MakeEmpty();
680 appMessage.AddString("path", path.Path());
681 appMessage.AddUInt32("flags", appFlags | accessFlags);
682 appMessage.AddString("checksum", checksum);
683
684 keyring.RemoveApplication(appInfo.signature, path.Path());
685 if (keyring.AddApplication(appInfo.signature, appMessage) == B_OK)
686 _WriteKeyStoreDatabase();
687
688 return B_OK;
689 }
690
691
692 status_t
_RequestAppAccess(const BString & keyringName,const char * signature,const char * path,const char * accessString,bool appIsNew,bool appWasUpdated,uint32 accessFlags,bool & allowAlways)693 KeyStoreServer::_RequestAppAccess(const BString& keyringName,
694 const char* signature, const char* path, const char* accessString,
695 bool appIsNew, bool appWasUpdated, uint32 accessFlags, bool& allowAlways)
696 {
697 AppAccessRequestWindow* requestWindow
698 = new(std::nothrow) AppAccessRequestWindow(keyringName, signature, path,
699 accessString, appIsNew, appWasUpdated);
700 if (requestWindow == NULL)
701 return B_NO_MEMORY;
702
703 return requestWindow->RequestAppAccess(allowAlways);
704 }
705
706
707 Keyring*
_FindKeyring(const BString & name)708 KeyStoreServer::_FindKeyring(const BString& name)
709 {
710 if (name.IsEmpty() || name == kMasterKeyringName)
711 return fMasterKeyring;
712
713 return fKeyrings.BinarySearchByKey(name, &Keyring::Compare);
714 }
715
716
717 status_t
_AddKeyring(const BString & name)718 KeyStoreServer::_AddKeyring(const BString& name)
719 {
720 if (_FindKeyring(name) != NULL)
721 return B_NAME_IN_USE;
722
723 Keyring* keyring = new(std::nothrow) Keyring(name);
724 if (keyring == NULL)
725 return B_NO_MEMORY;
726
727 if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) {
728 delete keyring;
729 return B_ERROR;
730 }
731
732 return B_OK;
733 }
734
735
736 status_t
_RemoveKeyring(const BString & name)737 KeyStoreServer::_RemoveKeyring(const BString& name)
738 {
739 Keyring* keyring = _FindKeyring(name);
740 if (keyring == NULL)
741 return B_ENTRY_NOT_FOUND;
742
743 if (keyring == fMasterKeyring) {
744 // The master keyring can't be removed.
745 return B_NOT_ALLOWED;
746 }
747
748 return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR;
749 }
750
751
752 status_t
_UnlockKeyring(Keyring & keyring)753 KeyStoreServer::_UnlockKeyring(Keyring& keyring)
754 {
755 if (!keyring.HasUnlockKey())
756 return keyring.Unlock(NULL);
757
758 // If we are accessing a keyring that has been added to master access we
759 // get the key from the master keyring and unlock with that.
760 BMessage keyMessage;
761 if (&keyring != fMasterKeyring && fMasterKeyring->IsUnlocked()) {
762 if (fMasterKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(),
763 false, &keyMessage) == B_OK) {
764 // We found a key for this keyring, try to unlock with it.
765 if (keyring.Unlock(&keyMessage) == B_OK)
766 return B_OK;
767 }
768 }
769
770 // No key, we need to request one from the user.
771 status_t result = _RequestKey(keyring.Name(), keyMessage);
772 if (result != B_OK)
773 return result;
774
775 return keyring.Unlock(&keyMessage);
776 }
777
778
779 status_t
_RequestKey(const BString & keyringName,BMessage & keyMessage)780 KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage)
781 {
782 KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow();
783 if (requestWindow == NULL)
784 return B_NO_MEMORY;
785
786 return requestWindow->RequestKey(keyringName, keyMessage);
787 }
788
789
790 int
main(int argc,char * argv[])791 main(int argc, char* argv[])
792 {
793 KeyStoreServer* app = new(std::nothrow) KeyStoreServer();
794 if (app == NULL)
795 return 1;
796
797 app->Run();
798 delete app;
799 return 0;
800 }
801