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 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 95 KeyStoreServer::~KeyStoreServer() 96 { 97 } 98 99 100 void 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 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 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 538 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* 580 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 622 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 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 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* 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 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 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 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 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 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