18d9bc9e0SMichael Lotz /* 28d9bc9e0SMichael Lotz * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. 38d9bc9e0SMichael Lotz * Distributed under the terms of the MIT License. 48d9bc9e0SMichael Lotz */ 58d9bc9e0SMichael Lotz 68d9bc9e0SMichael Lotz 78d9bc9e0SMichael Lotz #include "KeyStoreServer.h" 8ac9b28f0SMichael Lotz 9cfa81315SMichael Lotz #include "AppAccessRequestWindow.h" 10ac9b28f0SMichael Lotz #include "KeyRequestWindow.h" 1195eee1a3SMichael Lotz #include "Keyring.h" 128d9bc9e0SMichael Lotz 138d9bc9e0SMichael Lotz #include <KeyStoreDefs.h> 148d9bc9e0SMichael Lotz 150dfaf59dSMichael Lotz #include <Directory.h> 160dfaf59dSMichael Lotz #include <Entry.h> 170dfaf59dSMichael Lotz #include <FindDirectory.h> 180dfaf59dSMichael Lotz #include <Path.h> 1976df966eSMichael Lotz #include <Roster.h> 200dfaf59dSMichael Lotz #include <String.h> 210dfaf59dSMichael Lotz 228d9bc9e0SMichael Lotz #include <new> 238d9bc9e0SMichael Lotz 248d9bc9e0SMichael Lotz #include <stdio.h> 258d9bc9e0SMichael Lotz 268d9bc9e0SMichael Lotz 278d9bc9e0SMichael Lotz using namespace BPrivate; 288d9bc9e0SMichael Lotz 298d9bc9e0SMichael Lotz 30a5a5f4caSMichael Lotz static const char* kMasterKeyringName = "Master"; 31f16fef70SMichael Lotz static const char* kKeyringKeysIdentifier = "Keyrings"; 32f16fef70SMichael Lotz 33*bec02d0cSMichael Lotz static const uint32 kKeyStoreFormatVersion = 1; 34*bec02d0cSMichael Lotz 3597b3abf1SMichael Lotz static const uint32 kFlagGetKey = 0x0001; 3697b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeys = 0x0002; 3797b3abf1SMichael Lotz static const uint32 kFlagAddKey = 0x0004; 3897b3abf1SMichael Lotz static const uint32 kFlagRemoveKey = 0x0008; 3997b3abf1SMichael Lotz static const uint32 kFlagAddKeyring = 0x0010; 4097b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyring = 0x0020; 4197b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeyrings = 0x0040; 4297b3abf1SMichael Lotz static const uint32 kFlagSetMasterKey = 0x0080; 4397b3abf1SMichael Lotz static const uint32 kFlagRemoveMasterKey = 0x0100; 4497b3abf1SMichael Lotz static const uint32 kFlagAddKeyringsToMaster = 0x0200; 4597b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyringsFromMaster = 0x0400; 4697b3abf1SMichael Lotz static const uint32 kFlagEnumerateMasterKeyrings = 0x0800; 47c8ae843fSMichael Lotz static const uint32 kFlagQueryLockState = 0x1000; 48c8ae843fSMichael Lotz static const uint32 kFlagLockKeyring = 0x2000; 4997b3abf1SMichael Lotz static const uint32 kFlagEnumerateApplications = 0x4000; 5097b3abf1SMichael Lotz static const uint32 kFlagRemoveApplications = 0x8000; 5197b3abf1SMichael Lotz 5297b3abf1SMichael Lotz static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys 5397b3abf1SMichael Lotz | kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring 5497b3abf1SMichael Lotz | kFlagEnumerateKeyrings | kFlagSetMasterKey | kFlagRemoveMasterKey 5597b3abf1SMichael Lotz | kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster 56c8ae843fSMichael Lotz | kFlagEnumerateMasterKeyrings | kFlagQueryLockState | kFlagLockKeyring 57c8ae843fSMichael Lotz | kFlagEnumerateApplications | kFlagRemoveApplications; 5897b3abf1SMichael Lotz 59f16fef70SMichael Lotz 608d9bc9e0SMichael Lotz KeyStoreServer::KeyStoreServer() 618d9bc9e0SMichael Lotz : 6295eee1a3SMichael Lotz BApplication(kKeyStoreServerSignature), 63a5a5f4caSMichael Lotz fMasterKeyring(NULL), 6495eee1a3SMichael Lotz fKeyrings(20, true) 658d9bc9e0SMichael Lotz { 660dfaf59dSMichael Lotz BPath path; 670dfaf59dSMichael Lotz if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 680dfaf59dSMichael Lotz return; 690dfaf59dSMichael Lotz 700dfaf59dSMichael Lotz BDirectory settingsDir(path.Path()); 710dfaf59dSMichael Lotz path.Append("system"); 720dfaf59dSMichael Lotz if (!settingsDir.Contains(path.Path())) 730dfaf59dSMichael Lotz settingsDir.CreateDirectory(path.Path(), NULL); 740dfaf59dSMichael Lotz 750dfaf59dSMichael Lotz settingsDir.SetTo(path.Path()); 760dfaf59dSMichael Lotz path.Append("keystore"); 770dfaf59dSMichael Lotz if (!settingsDir.Contains(path.Path())) 780dfaf59dSMichael Lotz settingsDir.CreateDirectory(path.Path(), NULL); 790dfaf59dSMichael Lotz 800dfaf59dSMichael Lotz settingsDir.SetTo(path.Path()); 810dfaf59dSMichael Lotz path.Append("keystore_database"); 820dfaf59dSMichael Lotz 830dfaf59dSMichael Lotz fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE 840dfaf59dSMichael Lotz | (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE)); 850dfaf59dSMichael Lotz 860dfaf59dSMichael Lotz _ReadKeyStoreDatabase(); 8795eee1a3SMichael Lotz 88*bec02d0cSMichael Lotz if (fMasterKeyring == NULL) { 89a5a5f4caSMichael Lotz fMasterKeyring = new(std::nothrow) Keyring(kMasterKeyringName); 90*bec02d0cSMichael Lotz fKeyrings.BinaryInsert(fMasterKeyring, &Keyring::Compare); 91*bec02d0cSMichael Lotz } 928d9bc9e0SMichael Lotz } 938d9bc9e0SMichael Lotz 948d9bc9e0SMichael Lotz 958d9bc9e0SMichael Lotz KeyStoreServer::~KeyStoreServer() 968d9bc9e0SMichael Lotz { 978d9bc9e0SMichael Lotz } 988d9bc9e0SMichael Lotz 998d9bc9e0SMichael Lotz 1008d9bc9e0SMichael Lotz void 1018d9bc9e0SMichael Lotz KeyStoreServer::MessageReceived(BMessage* message) 1028d9bc9e0SMichael Lotz { 1030dfaf59dSMichael Lotz BMessage reply; 10495eee1a3SMichael Lotz status_t result = B_UNSUPPORTED; 105cfa81315SMichael Lotz app_info callingAppInfo; 106cfa81315SMichael Lotz 107cfa81315SMichael Lotz uint32 accessFlags = _AccessFlagsFor(message->what); 108cfa81315SMichael Lotz if (accessFlags == 0) 109cfa81315SMichael Lotz message->what = 0; 110cfa81315SMichael Lotz 111cfa81315SMichael Lotz if (message->what != 0) { 112cfa81315SMichael Lotz result = _ResolveCallingApp(*message, callingAppInfo); 113cfa81315SMichael Lotz if (result != B_OK) 114cfa81315SMichael Lotz message->what = 0; 115cfa81315SMichael Lotz } 11695eee1a3SMichael Lotz 11795eee1a3SMichael Lotz // Resolve the keyring for the relevant messages. 11895eee1a3SMichael Lotz Keyring* keyring = NULL; 11995eee1a3SMichael Lotz switch (message->what) { 12095eee1a3SMichael Lotz case KEY_STORE_GET_KEY: 12195eee1a3SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 12295eee1a3SMichael Lotz case KEY_STORE_ADD_KEY: 12395eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEY: 124c8ae843fSMichael Lotz case KEY_STORE_IS_KEYRING_UNLOCKED: 125c8ae843fSMichael Lotz case KEY_STORE_LOCK_KEYRING: 126f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 127f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 128b31a707aSMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 129b31a707aSMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 13095eee1a3SMichael Lotz { 13195eee1a3SMichael Lotz BString keyringName; 13295eee1a3SMichael Lotz if (message->FindString("keyring", &keyringName) != B_OK) 13395eee1a3SMichael Lotz keyringName = ""; 13495eee1a3SMichael Lotz 13595eee1a3SMichael Lotz keyring = _FindKeyring(keyringName); 13695eee1a3SMichael Lotz if (keyring == NULL) { 13795eee1a3SMichael Lotz result = B_BAD_VALUE; 13895eee1a3SMichael Lotz message->what = 0; 13995eee1a3SMichael Lotz // So that we don't do anything in the second switch. 14095eee1a3SMichael Lotz break; 14195eee1a3SMichael Lotz } 14295eee1a3SMichael Lotz 143ac9b28f0SMichael Lotz switch (message->what) { 144ac9b28f0SMichael Lotz case KEY_STORE_GET_KEY: 145ac9b28f0SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 146ac9b28f0SMichael Lotz case KEY_STORE_ADD_KEY: 147ac9b28f0SMichael Lotz case KEY_STORE_REMOVE_KEY: 148f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 149b31a707aSMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 150b31a707aSMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 151ac9b28f0SMichael Lotz { 152ac9b28f0SMichael Lotz // These need keyring access to do anything. 153c8ae843fSMichael Lotz while (!keyring->IsUnlocked()) { 154c8ae843fSMichael Lotz status_t unlockResult = _UnlockKeyring(*keyring); 155c8ae843fSMichael Lotz if (unlockResult != B_OK) { 156c8ae843fSMichael Lotz result = unlockResult; 157ac9b28f0SMichael Lotz message->what = 0; 158ac9b28f0SMichael Lotz break; 159ac9b28f0SMichael Lotz } 160ac9b28f0SMichael Lotz } 161cfa81315SMichael Lotz 162cfa81315SMichael Lotz status_t validateResult = _ValidateAppAccess(*keyring, 163cfa81315SMichael Lotz callingAppInfo, accessFlags); 164cfa81315SMichael Lotz if (validateResult != B_OK) { 165cfa81315SMichael Lotz result = validateResult; 166cfa81315SMichael Lotz message->what = 0; 167cfa81315SMichael Lotz break; 168cfa81315SMichael Lotz } 169cfa81315SMichael Lotz 170cfa81315SMichael Lotz break; 171ac9b28f0SMichael Lotz } 172ac9b28f0SMichael Lotz } 173ac9b28f0SMichael Lotz 17495eee1a3SMichael Lotz break; 17595eee1a3SMichael Lotz } 17695eee1a3SMichael Lotz } 1770dfaf59dSMichael Lotz 1788d9bc9e0SMichael Lotz switch (message->what) { 1798d9bc9e0SMichael Lotz case KEY_STORE_GET_KEY: 1808d9bc9e0SMichael Lotz { 18195eee1a3SMichael Lotz BString identifier; 18295eee1a3SMichael Lotz if (message->FindString("identifier", &identifier) != B_OK) { 18395eee1a3SMichael Lotz result = B_BAD_VALUE; 18495eee1a3SMichael Lotz break; 18595eee1a3SMichael Lotz } 18695eee1a3SMichael Lotz 18795eee1a3SMichael Lotz bool secondaryIdentifierOptional; 18895eee1a3SMichael Lotz if (message->FindBool("secondaryIdentifierOptional", 18995eee1a3SMichael Lotz &secondaryIdentifierOptional) != B_OK) { 19095eee1a3SMichael Lotz secondaryIdentifierOptional = false; 19195eee1a3SMichael Lotz } 19295eee1a3SMichael Lotz 19395eee1a3SMichael Lotz BString secondaryIdentifier; 19495eee1a3SMichael Lotz if (message->FindString("secondaryIdentifier", 19595eee1a3SMichael Lotz &secondaryIdentifier) != B_OK) { 19695eee1a3SMichael Lotz secondaryIdentifier = ""; 19795eee1a3SMichael Lotz secondaryIdentifierOptional = true; 19895eee1a3SMichael Lotz } 19995eee1a3SMichael Lotz 20095eee1a3SMichael Lotz BMessage keyMessage; 20195eee1a3SMichael Lotz result = keyring->FindKey(identifier, secondaryIdentifier, 20295eee1a3SMichael Lotz secondaryIdentifierOptional, &keyMessage); 20395eee1a3SMichael Lotz if (result == B_OK) 20495eee1a3SMichael Lotz reply.AddMessage("key", &keyMessage); 205f16fef70SMichael Lotz 2068d9bc9e0SMichael Lotz break; 2078d9bc9e0SMichael Lotz } 2088d9bc9e0SMichael Lotz 2098d9bc9e0SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 2108d9bc9e0SMichael Lotz { 2110dfaf59dSMichael Lotz BKeyType type; 2120dfaf59dSMichael Lotz BKeyPurpose purpose; 2130dfaf59dSMichael Lotz uint32 cookie; 2140dfaf59dSMichael Lotz if (message->FindUInt32("type", (uint32*)&type) != B_OK 2150dfaf59dSMichael Lotz || message->FindUInt32("purpose", (uint32*)&purpose) != B_OK 2160dfaf59dSMichael Lotz || message->FindUInt32("cookie", &cookie) != B_OK) { 2170dfaf59dSMichael Lotz result = B_BAD_VALUE; 2180dfaf59dSMichael Lotz break; 2190dfaf59dSMichael Lotz } 2200dfaf59dSMichael Lotz 2210dfaf59dSMichael Lotz BMessage keyMessage; 22295eee1a3SMichael Lotz result = keyring->FindKey(type, purpose, cookie, keyMessage); 2230dfaf59dSMichael Lotz if (result == B_OK) { 2240dfaf59dSMichael Lotz cookie++; 2250dfaf59dSMichael Lotz reply.AddUInt32("cookie", cookie); 2260dfaf59dSMichael Lotz reply.AddMessage("key", &keyMessage); 2270dfaf59dSMichael Lotz } 2280dfaf59dSMichael Lotz 2290dfaf59dSMichael Lotz break; 2300dfaf59dSMichael Lotz } 2310dfaf59dSMichael Lotz 2320dfaf59dSMichael Lotz case KEY_STORE_ADD_KEY: 2330dfaf59dSMichael Lotz { 2340dfaf59dSMichael Lotz BMessage keyMessage; 2350dfaf59dSMichael Lotz BString identifier; 2360dfaf59dSMichael Lotz if (message->FindMessage("key", &keyMessage) != B_OK 2370dfaf59dSMichael Lotz || keyMessage.FindString("identifier", &identifier) != B_OK) { 2380dfaf59dSMichael Lotz result = B_BAD_VALUE; 2390dfaf59dSMichael Lotz break; 2400dfaf59dSMichael Lotz } 2410dfaf59dSMichael Lotz 2420dfaf59dSMichael Lotz BString secondaryIdentifier; 2430dfaf59dSMichael Lotz if (keyMessage.FindString("secondaryIdentifier", 2440dfaf59dSMichael Lotz &secondaryIdentifier) != B_OK) { 2450dfaf59dSMichael Lotz secondaryIdentifier = ""; 2460dfaf59dSMichael Lotz } 2470dfaf59dSMichael Lotz 24895eee1a3SMichael Lotz result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage); 24995eee1a3SMichael Lotz if (result == B_OK) 25095eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 25195eee1a3SMichael Lotz 25295eee1a3SMichael Lotz break; 25395eee1a3SMichael Lotz } 25495eee1a3SMichael Lotz 25595eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEY: 25695eee1a3SMichael Lotz { 25795eee1a3SMichael Lotz BMessage keyMessage; 25895eee1a3SMichael Lotz BString identifier; 25995eee1a3SMichael Lotz if (message->FindMessage("key", &keyMessage) != B_OK 26095eee1a3SMichael Lotz || keyMessage.FindString("identifier", &identifier) != B_OK) { 26195eee1a3SMichael Lotz result = B_BAD_VALUE; 26295eee1a3SMichael Lotz break; 26395eee1a3SMichael Lotz } 26495eee1a3SMichael Lotz 26595eee1a3SMichael Lotz result = keyring->RemoveKey(identifier, keyMessage); 26695eee1a3SMichael Lotz if (result == B_OK) 26795eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 26895eee1a3SMichael Lotz 26995eee1a3SMichael Lotz break; 27095eee1a3SMichael Lotz } 27195eee1a3SMichael Lotz 27295eee1a3SMichael Lotz case KEY_STORE_ADD_KEYRING: 27395eee1a3SMichael Lotz { 27495eee1a3SMichael Lotz BMessage keyMessage; 27595eee1a3SMichael Lotz BString keyring; 276d4d6d123SMichael Lotz if (message->FindString("keyring", &keyring) != B_OK) { 27795eee1a3SMichael Lotz result = B_BAD_VALUE; 27895eee1a3SMichael Lotz break; 27995eee1a3SMichael Lotz } 28095eee1a3SMichael Lotz 281d4d6d123SMichael Lotz result = _AddKeyring(keyring); 28295eee1a3SMichael Lotz if (result == B_OK) 28395eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 28495eee1a3SMichael Lotz 28595eee1a3SMichael Lotz break; 28695eee1a3SMichael Lotz } 28795eee1a3SMichael Lotz 28895eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEYRING: 28995eee1a3SMichael Lotz { 29095eee1a3SMichael Lotz BString keyringName; 29195eee1a3SMichael Lotz if (message->FindString("keyring", &keyringName) != B_OK) 29295eee1a3SMichael Lotz keyringName = ""; 29395eee1a3SMichael Lotz 29495eee1a3SMichael Lotz result = _RemoveKeyring(keyringName); 29595eee1a3SMichael Lotz if (result == B_OK) 29695eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 29795eee1a3SMichael Lotz 29895eee1a3SMichael Lotz break; 29995eee1a3SMichael Lotz } 30095eee1a3SMichael Lotz 30195eee1a3SMichael Lotz case KEY_STORE_GET_NEXT_KEYRING: 30295eee1a3SMichael Lotz { 30395eee1a3SMichael Lotz uint32 cookie; 30495eee1a3SMichael Lotz if (message->FindUInt32("cookie", &cookie) != B_OK) { 30595eee1a3SMichael Lotz result = B_BAD_VALUE; 30695eee1a3SMichael Lotz break; 30795eee1a3SMichael Lotz } 30895eee1a3SMichael Lotz 309*bec02d0cSMichael Lotz keyring = fKeyrings.ItemAt(cookie); 31095eee1a3SMichael Lotz if (keyring == NULL) { 31195eee1a3SMichael Lotz result = B_ENTRY_NOT_FOUND; 31295eee1a3SMichael Lotz break; 31395eee1a3SMichael Lotz } 31495eee1a3SMichael Lotz 31595eee1a3SMichael Lotz cookie++; 31695eee1a3SMichael Lotz reply.AddUInt32("cookie", cookie); 31795eee1a3SMichael Lotz reply.AddString("keyring", keyring->Name()); 31895eee1a3SMichael Lotz result = B_OK; 31995eee1a3SMichael Lotz break; 32095eee1a3SMichael Lotz } 32195eee1a3SMichael Lotz 322c8ae843fSMichael Lotz case KEY_STORE_IS_KEYRING_UNLOCKED: 32395eee1a3SMichael Lotz { 324c8ae843fSMichael Lotz reply.AddBool("unlocked", keyring->IsUnlocked()); 32595eee1a3SMichael Lotz result = B_OK; 326f16fef70SMichael Lotz break; 32795eee1a3SMichael Lotz } 32895eee1a3SMichael Lotz 329c8ae843fSMichael Lotz case KEY_STORE_LOCK_KEYRING: 330ac9b28f0SMichael Lotz { 331c8ae843fSMichael Lotz keyring->Lock(); 332ac9b28f0SMichael Lotz result = B_OK; 333f16fef70SMichael Lotz break; 334f16fef70SMichael Lotz } 335f16fef70SMichael Lotz 336f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 337f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 338f16fef70SMichael Lotz { 339a5a5f4caSMichael Lotz // We also need access to the master keyring. 340a5a5f4caSMichael Lotz while (!fMasterKeyring->IsUnlocked()) { 341a5a5f4caSMichael Lotz status_t unlockResult = _UnlockKeyring(*fMasterKeyring); 342c8ae843fSMichael Lotz if (unlockResult != B_OK) { 343c8ae843fSMichael Lotz result = unlockResult; 344f16fef70SMichael Lotz message->what = 0; 345f16fef70SMichael Lotz break; 346f16fef70SMichael Lotz } 347f16fef70SMichael Lotz } 348f16fef70SMichael Lotz 349f16fef70SMichael Lotz if (message->what == 0) 350f16fef70SMichael Lotz break; 351f16fef70SMichael Lotz 352f16fef70SMichael Lotz BString secondaryIdentifier = keyring->Name(); 353f16fef70SMichael Lotz BMessage keyMessage = keyring->KeyMessage(); 354f16fef70SMichael Lotz keyMessage.RemoveName("identifier"); 355f16fef70SMichael Lotz keyMessage.AddString("identifier", kKeyringKeysIdentifier); 356f16fef70SMichael Lotz keyMessage.RemoveName("secondaryIdentifier"); 357f16fef70SMichael Lotz keyMessage.AddString("secondaryIdentifier", secondaryIdentifier); 358f16fef70SMichael Lotz 359f16fef70SMichael Lotz switch (message->what) { 360f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 361a5a5f4caSMichael Lotz result = fMasterKeyring->AddKey(kKeyringKeysIdentifier, 362f16fef70SMichael Lotz secondaryIdentifier, keyMessage); 363f16fef70SMichael Lotz break; 364f16fef70SMichael Lotz 365f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 366a5a5f4caSMichael Lotz result = fMasterKeyring->RemoveKey(kKeyringKeysIdentifier, 367f16fef70SMichael Lotz keyMessage); 368f16fef70SMichael Lotz break; 369f16fef70SMichael Lotz } 370f16fef70SMichael Lotz 371f16fef70SMichael Lotz if (result == B_OK) 372f16fef70SMichael Lotz _WriteKeyStoreDatabase(); 373f16fef70SMichael Lotz 374f16fef70SMichael Lotz break; 375ac9b28f0SMichael Lotz } 376ac9b28f0SMichael Lotz 377b31a707aSMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 378b31a707aSMichael Lotz { 379b31a707aSMichael Lotz uint32 cookie; 380b31a707aSMichael Lotz if (message->FindUInt32("cookie", &cookie) != B_OK) { 381b31a707aSMichael Lotz result = B_BAD_VALUE; 382b31a707aSMichael Lotz break; 383b31a707aSMichael Lotz } 384b31a707aSMichael Lotz 385b31a707aSMichael Lotz BString signature; 386b31a707aSMichael Lotz BString path; 387b31a707aSMichael Lotz result = keyring->GetNextApplication(cookie, signature, path); 388b31a707aSMichael Lotz if (result != B_OK) 389b31a707aSMichael Lotz break; 390b31a707aSMichael Lotz 391b31a707aSMichael Lotz reply.AddUInt32("cookie", cookie); 392b31a707aSMichael Lotz reply.AddString("signature", signature); 393b31a707aSMichael Lotz reply.AddString("path", path); 394b31a707aSMichael Lotz result = B_OK; 395b31a707aSMichael Lotz break; 396b31a707aSMichael Lotz } 397b31a707aSMichael Lotz 398b31a707aSMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 399b31a707aSMichael Lotz { 400b31a707aSMichael Lotz const char* signature = NULL; 401b31a707aSMichael Lotz const char* path = NULL; 402b31a707aSMichael Lotz 403b31a707aSMichael Lotz if (message->FindString("signature", &signature) != B_OK) { 404b31a707aSMichael Lotz result = B_BAD_VALUE; 405b31a707aSMichael Lotz break; 406b31a707aSMichael Lotz } 407b31a707aSMichael Lotz 408b31a707aSMichael Lotz if (message->FindString("path", &path) != B_OK) 409b31a707aSMichael Lotz path = NULL; 410b31a707aSMichael Lotz 411b31a707aSMichael Lotz result = keyring->RemoveApplication(signature, path); 412b31a707aSMichael Lotz break; 413b31a707aSMichael Lotz } 414b31a707aSMichael Lotz 41595eee1a3SMichael Lotz case 0: 41695eee1a3SMichael Lotz { 41795eee1a3SMichael Lotz // Just the error case from above. 4188d9bc9e0SMichael Lotz break; 4198d9bc9e0SMichael Lotz } 4208d9bc9e0SMichael Lotz 4218d9bc9e0SMichael Lotz default: 4228d9bc9e0SMichael Lotz { 4238d9bc9e0SMichael Lotz printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n", 4248d9bc9e0SMichael Lotz message->what, (const char*)&message->what); 4258d9bc9e0SMichael Lotz break; 4268d9bc9e0SMichael Lotz } 4278d9bc9e0SMichael Lotz } 4288d9bc9e0SMichael Lotz 4290dfaf59dSMichael Lotz if (message->IsSourceWaiting()) { 4300dfaf59dSMichael Lotz if (result == B_OK) 4310dfaf59dSMichael Lotz reply.what = KEY_STORE_SUCCESS; 4320dfaf59dSMichael Lotz else { 4330dfaf59dSMichael Lotz reply.what = KEY_STORE_RESULT; 4340dfaf59dSMichael Lotz reply.AddInt32("result", result); 4350dfaf59dSMichael Lotz } 4360dfaf59dSMichael Lotz 4370dfaf59dSMichael Lotz message->SendReply(&reply); 4380dfaf59dSMichael Lotz } 4398d9bc9e0SMichael Lotz } 4408d9bc9e0SMichael Lotz 4418d9bc9e0SMichael Lotz 4428d9bc9e0SMichael Lotz status_t 4430dfaf59dSMichael Lotz KeyStoreServer::_ReadKeyStoreDatabase() 4448d9bc9e0SMichael Lotz { 445*bec02d0cSMichael Lotz BMessage keystore; 446*bec02d0cSMichael Lotz status_t result = keystore.Unflatten(&fKeyStoreFile); 4470dfaf59dSMichael Lotz if (result != B_OK) { 4480dfaf59dSMichael Lotz printf("failed to read keystore database\n"); 4490dfaf59dSMichael Lotz _WriteKeyStoreDatabase(); 450*bec02d0cSMichael Lotz // Reinitializes the database. 4510dfaf59dSMichael Lotz return result; 4520dfaf59dSMichael Lotz } 4530dfaf59dSMichael Lotz 45495eee1a3SMichael Lotz int32 index = 0; 455*bec02d0cSMichael Lotz BMessage keyringData; 456*bec02d0cSMichael Lotz while (keystore.FindMessage("keyrings", index++, &keyringData) == B_OK) { 457*bec02d0cSMichael Lotz Keyring* keyring = new(std::nothrow) Keyring(); 4581b3bb46aSMichael Lotz if (keyring == NULL) { 459*bec02d0cSMichael Lotz printf("no memory for allocating keyring\n"); 460*bec02d0cSMichael Lotz break; 46195eee1a3SMichael Lotz } 46295eee1a3SMichael Lotz 463*bec02d0cSMichael Lotz status_t result = keyring->ReadFromMessage(keyringData); 4641b3bb46aSMichael Lotz if (result != B_OK) { 465*bec02d0cSMichael Lotz printf("failed to read keyring from data\n"); 4661b3bb46aSMichael Lotz delete keyring; 46795eee1a3SMichael Lotz continue; 46895eee1a3SMichael Lotz } 46995eee1a3SMichael Lotz 470*bec02d0cSMichael Lotz if (strcmp(keyring->Name(), kMasterKeyringName) == 0) 471a5a5f4caSMichael Lotz fMasterKeyring = keyring; 472*bec02d0cSMichael Lotz 47395eee1a3SMichael Lotz fKeyrings.BinaryInsert(keyring, &Keyring::Compare); 47495eee1a3SMichael Lotz } 47595eee1a3SMichael Lotz 4760dfaf59dSMichael Lotz return B_OK; 4770dfaf59dSMichael Lotz } 4780dfaf59dSMichael Lotz 4790dfaf59dSMichael Lotz 4800dfaf59dSMichael Lotz status_t 4810dfaf59dSMichael Lotz KeyStoreServer::_WriteKeyStoreDatabase() 4820dfaf59dSMichael Lotz { 483*bec02d0cSMichael Lotz BMessage keystore; 484*bec02d0cSMichael Lotz keystore.AddUInt32("format", kKeyStoreFormatVersion); 4850dfaf59dSMichael Lotz 48695eee1a3SMichael Lotz for (int32 i = 0; i < fKeyrings.CountItems(); i++) { 48795eee1a3SMichael Lotz Keyring* keyring = fKeyrings.ItemAt(i); 48895eee1a3SMichael Lotz if (keyring == NULL) 4890dfaf59dSMichael Lotz continue; 49095eee1a3SMichael Lotz 491*bec02d0cSMichael Lotz BMessage keyringData; 492*bec02d0cSMichael Lotz status_t result = keyring->WriteToMessage(keyringData); 4931b3bb46aSMichael Lotz if (result != B_OK) 4941b3bb46aSMichael Lotz return result; 495*bec02d0cSMichael Lotz 496*bec02d0cSMichael Lotz keystore.AddMessage("keyrings", &keyringData); 4970dfaf59dSMichael Lotz } 4980dfaf59dSMichael Lotz 499aef629f2SMichael Lotz fKeyStoreFile.SetSize(0); 500aef629f2SMichael Lotz fKeyStoreFile.Seek(0, SEEK_SET); 501*bec02d0cSMichael Lotz return keystore.Flatten(&fKeyStoreFile); 5020dfaf59dSMichael Lotz } 5030dfaf59dSMichael Lotz 5040dfaf59dSMichael Lotz 50597b3abf1SMichael Lotz uint32 50697b3abf1SMichael Lotz KeyStoreServer::_AccessFlagsFor(uint32 command) const 50797b3abf1SMichael Lotz { 50897b3abf1SMichael Lotz switch (command) { 50997b3abf1SMichael Lotz case KEY_STORE_GET_KEY: 51097b3abf1SMichael Lotz return kFlagGetKey; 51197b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 51297b3abf1SMichael Lotz return kFlagEnumerateKeys; 51397b3abf1SMichael Lotz case KEY_STORE_ADD_KEY: 51497b3abf1SMichael Lotz return kFlagAddKey; 51597b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEY: 51697b3abf1SMichael Lotz return kFlagRemoveKey; 51797b3abf1SMichael Lotz case KEY_STORE_ADD_KEYRING: 51897b3abf1SMichael Lotz return kFlagAddKeyring; 51997b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEYRING: 52097b3abf1SMichael Lotz return kFlagRemoveKeyring; 52197b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_KEYRING: 52297b3abf1SMichael Lotz return kFlagEnumerateKeyrings; 52397b3abf1SMichael Lotz case KEY_STORE_SET_MASTER_KEY: 52497b3abf1SMichael Lotz return kFlagSetMasterKey; 52597b3abf1SMichael Lotz case KEY_STORE_REMOVE_MASTER_KEY: 52697b3abf1SMichael Lotz return kFlagRemoveMasterKey; 52797b3abf1SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 52897b3abf1SMichael Lotz return kFlagAddKeyringsToMaster; 52997b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 53097b3abf1SMichael Lotz return kFlagRemoveKeyringsFromMaster; 53197b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_MASTER_KEYRING: 53297b3abf1SMichael Lotz return kFlagEnumerateMasterKeyrings; 533c8ae843fSMichael Lotz case KEY_STORE_IS_KEYRING_UNLOCKED: 534c8ae843fSMichael Lotz return kFlagQueryLockState; 535c8ae843fSMichael Lotz case KEY_STORE_LOCK_KEYRING: 536c8ae843fSMichael Lotz return kFlagLockKeyring; 53797b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 53897b3abf1SMichael Lotz return kFlagEnumerateApplications; 53997b3abf1SMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 54097b3abf1SMichael Lotz return kFlagRemoveApplications; 54197b3abf1SMichael Lotz } 54297b3abf1SMichael Lotz 54397b3abf1SMichael Lotz return 0; 54497b3abf1SMichael Lotz } 54597b3abf1SMichael Lotz 54697b3abf1SMichael Lotz 547a2f27987SMichael Lotz const char* 548a2f27987SMichael Lotz KeyStoreServer::_AccessStringFor(uint32 accessFlag) const 549a2f27987SMichael Lotz { 550a2f27987SMichael Lotz switch (accessFlag) { 551a2f27987SMichael Lotz case kFlagGetKey: 552a2f27987SMichael Lotz return "Get keys from the keyring."; 553a2f27987SMichael Lotz case kFlagEnumerateKeys: 554a2f27987SMichael Lotz return "Enumerate and get keys from the keyring."; 555a2f27987SMichael Lotz case kFlagAddKey: 556a2f27987SMichael Lotz return "Add keys to the keyring."; 557a2f27987SMichael Lotz case kFlagRemoveKey: 558a2f27987SMichael Lotz return "Remove keys from the keyring."; 559a2f27987SMichael Lotz case kFlagAddKeyring: 560a2f27987SMichael Lotz return "Add new keyrings."; 561a2f27987SMichael Lotz case kFlagRemoveKeyring: 562a2f27987SMichael Lotz return "Remove keyrings."; 563a2f27987SMichael Lotz case kFlagEnumerateKeyrings: 564a2f27987SMichael Lotz return "Enumerate the available keyrings."; 565a2f27987SMichael Lotz case kFlagSetMasterKey: 566a2f27987SMichael Lotz return "Set the master key."; 567a2f27987SMichael Lotz case kFlagRemoveMasterKey: 568a2f27987SMichael Lotz return "Remove the master key."; 569a2f27987SMichael Lotz case kFlagAddKeyringsToMaster: 570a2f27987SMichael Lotz return "Add the keyring key to the master keyring."; 571a2f27987SMichael Lotz case kFlagRemoveKeyringsFromMaster: 572a2f27987SMichael Lotz return "Remove the keyring key from the master keyring."; 573a2f27987SMichael Lotz case kFlagEnumerateMasterKeyrings: 574a2f27987SMichael Lotz return "Enumerate keyrings added to the master keyring."; 575a2f27987SMichael Lotz case kFlagQueryLockState: 576a2f27987SMichael Lotz return "Query the lock state of the keyring."; 577a2f27987SMichael Lotz case kFlagLockKeyring: 578a2f27987SMichael Lotz return "Lock the keyring."; 579a2f27987SMichael Lotz case kFlagEnumerateApplications: 580a2f27987SMichael Lotz return "Enumerate the applications of the keyring."; 581a2f27987SMichael Lotz case kFlagRemoveApplications: 582a2f27987SMichael Lotz return "Remove applications from the keyring."; 583a2f27987SMichael Lotz } 584a2f27987SMichael Lotz 585a2f27987SMichael Lotz return NULL; 586a2f27987SMichael Lotz } 587a2f27987SMichael Lotz 588a2f27987SMichael Lotz 58976df966eSMichael Lotz status_t 59076df966eSMichael Lotz KeyStoreServer::_ResolveCallingApp(const BMessage& message, 59176df966eSMichael Lotz app_info& callingAppInfo) const 59276df966eSMichael Lotz { 59376df966eSMichael Lotz team_id callingTeam = message.ReturnAddress().Team(); 59476df966eSMichael Lotz status_t result = be_roster->GetRunningAppInfo(callingTeam, 59576df966eSMichael Lotz &callingAppInfo); 59676df966eSMichael Lotz if (result != B_OK) 59776df966eSMichael Lotz return result; 59876df966eSMichael Lotz 59976df966eSMichael Lotz // Do some sanity checks. 60076df966eSMichael Lotz if (callingAppInfo.team != callingTeam) 60176df966eSMichael Lotz return B_ERROR; 60276df966eSMichael Lotz 60376df966eSMichael Lotz return B_OK; 60476df966eSMichael Lotz } 60576df966eSMichael Lotz 60676df966eSMichael Lotz 607cfa81315SMichael Lotz status_t 608cfa81315SMichael Lotz KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo, 609cfa81315SMichael Lotz uint32 accessFlags) 610cfa81315SMichael Lotz { 611cfa81315SMichael Lotz BMessage appMessage; 612cfa81315SMichael Lotz BPath path(&appInfo.ref); 613cfa81315SMichael Lotz status_t result = keyring.FindApplication(appInfo.signature, 614cfa81315SMichael Lotz path.Path(), appMessage); 615cfa81315SMichael Lotz if (result != B_OK && result != B_ENTRY_NOT_FOUND) 616cfa81315SMichael Lotz return result; 617cfa81315SMichael Lotz 618cfa81315SMichael Lotz // TODO: Implement running image checksum mechanism. 619cfa81315SMichael Lotz BString checksum = "dummy"; 620cfa81315SMichael Lotz 621cfa81315SMichael Lotz bool appIsNew = false; 622cfa81315SMichael Lotz bool appWasUpdated = false; 623cfa81315SMichael Lotz uint32 appFlags = 0; 624cfa81315SMichael Lotz BString appSum = ""; 625cfa81315SMichael Lotz if (result == B_OK) { 626cfa81315SMichael Lotz if (appMessage.FindUInt32("flags", &appFlags) != B_OK 627cfa81315SMichael Lotz || appMessage.FindString("checksum", &appSum) != B_OK) { 628cfa81315SMichael Lotz appIsNew = true; 629cfa81315SMichael Lotz appFlags = 0; 630cfa81315SMichael Lotz } else if (appSum != checksum) { 631cfa81315SMichael Lotz appWasUpdated = true; 632cfa81315SMichael Lotz appFlags = 0; 633cfa81315SMichael Lotz } 634cfa81315SMichael Lotz } else 635cfa81315SMichael Lotz appIsNew = true; 636cfa81315SMichael Lotz 637cfa81315SMichael Lotz if ((accessFlags & appFlags) == accessFlags) 638cfa81315SMichael Lotz return B_OK; 639cfa81315SMichael Lotz 640a59169deSMichael Lotz const char* accessString = _AccessStringFor(accessFlags); 641cfa81315SMichael Lotz bool allowAlways = false; 642cfa81315SMichael Lotz result = _RequestAppAccess(keyring.Name(), appInfo.signature, path.Path(), 643a59169deSMichael Lotz accessString, appIsNew, appWasUpdated, accessFlags, allowAlways); 644cfa81315SMichael Lotz if (result != B_OK || !allowAlways) 645cfa81315SMichael Lotz return result; 646cfa81315SMichael Lotz 647cfa81315SMichael Lotz appMessage.MakeEmpty(); 648cfa81315SMichael Lotz appMessage.AddString("path", path.Path()); 649ee834720SMichael Lotz appMessage.AddUInt32("flags", appFlags | accessFlags); 650cfa81315SMichael Lotz appMessage.AddString("checksum", checksum); 651cfa81315SMichael Lotz 652cfa81315SMichael Lotz keyring.RemoveApplication(appInfo.signature, path.Path()); 653cfa81315SMichael Lotz if (keyring.AddApplication(appInfo.signature, appMessage) == B_OK) 654cfa81315SMichael Lotz _WriteKeyStoreDatabase(); 655cfa81315SMichael Lotz 656cfa81315SMichael Lotz return B_OK; 657cfa81315SMichael Lotz } 658cfa81315SMichael Lotz 659cfa81315SMichael Lotz 660cfa81315SMichael Lotz status_t 661cfa81315SMichael Lotz KeyStoreServer::_RequestAppAccess(const BString& keyringName, 662a59169deSMichael Lotz const char* signature, const char* path, const char* accessString, 663a59169deSMichael Lotz bool appIsNew, bool appWasUpdated, uint32 accessFlags, bool& allowAlways) 664cfa81315SMichael Lotz { 665cfa81315SMichael Lotz AppAccessRequestWindow* requestWindow 666cfa81315SMichael Lotz = new(std::nothrow) AppAccessRequestWindow(keyringName, signature, path, 667a59169deSMichael Lotz accessString, appIsNew, appWasUpdated); 668cfa81315SMichael Lotz if (requestWindow == NULL) 669cfa81315SMichael Lotz return B_NO_MEMORY; 670cfa81315SMichael Lotz 671cfa81315SMichael Lotz return requestWindow->RequestAppAccess(allowAlways); 672cfa81315SMichael Lotz } 673cfa81315SMichael Lotz 674cfa81315SMichael Lotz 67595eee1a3SMichael Lotz Keyring* 67695eee1a3SMichael Lotz KeyStoreServer::_FindKeyring(const BString& name) 67795eee1a3SMichael Lotz { 678a5a5f4caSMichael Lotz if (name.IsEmpty() || name == kMasterKeyringName) 679a5a5f4caSMichael Lotz return fMasterKeyring; 6800dfaf59dSMichael Lotz 68195eee1a3SMichael Lotz return fKeyrings.BinarySearchByKey(name, &Keyring::Compare); 6820dfaf59dSMichael Lotz } 6830dfaf59dSMichael Lotz 6840dfaf59dSMichael Lotz 6850dfaf59dSMichael Lotz status_t 686d4d6d123SMichael Lotz KeyStoreServer::_AddKeyring(const BString& name) 6870dfaf59dSMichael Lotz { 68895eee1a3SMichael Lotz if (_FindKeyring(name) != NULL) 6890dfaf59dSMichael Lotz return B_NAME_IN_USE; 6900dfaf59dSMichael Lotz 691d4d6d123SMichael Lotz Keyring* keyring = new(std::nothrow) Keyring(name); 69295eee1a3SMichael Lotz if (keyring == NULL) 69395eee1a3SMichael Lotz return B_NO_MEMORY; 69495eee1a3SMichael Lotz 69595eee1a3SMichael Lotz if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) { 69695eee1a3SMichael Lotz delete keyring; 69795eee1a3SMichael Lotz return B_ERROR; 69895eee1a3SMichael Lotz } 69995eee1a3SMichael Lotz 70095eee1a3SMichael Lotz return B_OK; 70195eee1a3SMichael Lotz } 70295eee1a3SMichael Lotz 70395eee1a3SMichael Lotz 70495eee1a3SMichael Lotz status_t 70595eee1a3SMichael Lotz KeyStoreServer::_RemoveKeyring(const BString& name) 70695eee1a3SMichael Lotz { 70795eee1a3SMichael Lotz Keyring* keyring = _FindKeyring(name); 70895eee1a3SMichael Lotz if (keyring == NULL) 70995eee1a3SMichael Lotz return B_ENTRY_NOT_FOUND; 71095eee1a3SMichael Lotz 711a5a5f4caSMichael Lotz if (keyring == fMasterKeyring) { 712a5a5f4caSMichael Lotz // The master keyring can't be removed. 71395eee1a3SMichael Lotz return B_NOT_ALLOWED; 71495eee1a3SMichael Lotz } 71595eee1a3SMichael Lotz 71695eee1a3SMichael Lotz return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR; 7178d9bc9e0SMichael Lotz } 7188d9bc9e0SMichael Lotz 7198d9bc9e0SMichael Lotz 720ac9b28f0SMichael Lotz status_t 721c8ae843fSMichael Lotz KeyStoreServer::_UnlockKeyring(Keyring& keyring) 722ac9b28f0SMichael Lotz { 723ac9b28f0SMichael Lotz // If we are accessing a keyring that has been added to master access we 724a5a5f4caSMichael Lotz // get the key from the master keyring and unlock with that. 725ac9b28f0SMichael Lotz BMessage keyMessage; 726a5a5f4caSMichael Lotz if (&keyring != fMasterKeyring && fMasterKeyring->IsUnlocked()) { 727a5a5f4caSMichael Lotz if (fMasterKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), 728f16fef70SMichael Lotz false, &keyMessage) == B_OK) { 729c8ae843fSMichael Lotz // We found a key for this keyring, try to unlock with it. 730c8ae843fSMichael Lotz if (keyring.Unlock(keyMessage) == B_OK) 731ac9b28f0SMichael Lotz return B_OK; 732ac9b28f0SMichael Lotz } 733ac9b28f0SMichael Lotz } 734ac9b28f0SMichael Lotz 735ac9b28f0SMichael Lotz // No key, we need to request one from the user. 73690013c82SMichael Lotz status_t result = _RequestKey(keyring.Name(), keyMessage); 737ac9b28f0SMichael Lotz if (result != B_OK) 738ac9b28f0SMichael Lotz return result; 739ac9b28f0SMichael Lotz 740c8ae843fSMichael Lotz return keyring.Unlock(keyMessage); 741ac9b28f0SMichael Lotz } 742ac9b28f0SMichael Lotz 743ac9b28f0SMichael Lotz 744ac9b28f0SMichael Lotz status_t 74590013c82SMichael Lotz KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage) 746ac9b28f0SMichael Lotz { 747ac9b28f0SMichael Lotz KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow(); 748ac9b28f0SMichael Lotz if (requestWindow == NULL) 749ac9b28f0SMichael Lotz return B_NO_MEMORY; 750ac9b28f0SMichael Lotz 75190013c82SMichael Lotz return requestWindow->RequestKey(keyringName, keyMessage); 752ac9b28f0SMichael Lotz } 753ac9b28f0SMichael Lotz 754ac9b28f0SMichael Lotz 7558d9bc9e0SMichael Lotz int 7568d9bc9e0SMichael Lotz main(int argc, char* argv[]) 7578d9bc9e0SMichael Lotz { 7588d9bc9e0SMichael Lotz KeyStoreServer* app = new(std::nothrow) KeyStoreServer(); 7598d9bc9e0SMichael Lotz if (app == NULL) 7608d9bc9e0SMichael Lotz return 1; 7618d9bc9e0SMichael Lotz 7628d9bc9e0SMichael Lotz app->Run(); 7638d9bc9e0SMichael Lotz delete app; 7648d9bc9e0SMichael Lotz return 0; 7658d9bc9e0SMichael Lotz } 766