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 30f16fef70SMichael Lotz static const char* kKeyringKeysIdentifier = "Keyrings"; 31f16fef70SMichael Lotz 3297b3abf1SMichael Lotz static const uint32 kFlagGetKey = 0x0001; 3397b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeys = 0x0002; 3497b3abf1SMichael Lotz static const uint32 kFlagAddKey = 0x0004; 3597b3abf1SMichael Lotz static const uint32 kFlagRemoveKey = 0x0008; 3697b3abf1SMichael Lotz static const uint32 kFlagAddKeyring = 0x0010; 3797b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyring = 0x0020; 3897b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeyrings = 0x0040; 3997b3abf1SMichael Lotz static const uint32 kFlagSetMasterKey = 0x0080; 4097b3abf1SMichael Lotz static const uint32 kFlagRemoveMasterKey = 0x0100; 4197b3abf1SMichael Lotz static const uint32 kFlagAddKeyringsToMaster = 0x0200; 4297b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyringsFromMaster = 0x0400; 4397b3abf1SMichael Lotz static const uint32 kFlagEnumerateMasterKeyrings = 0x0800; 44*c8ae843fSMichael Lotz static const uint32 kFlagQueryLockState = 0x1000; 45*c8ae843fSMichael Lotz static const uint32 kFlagLockKeyring = 0x2000; 4697b3abf1SMichael Lotz static const uint32 kFlagEnumerateApplications = 0x4000; 4797b3abf1SMichael Lotz static const uint32 kFlagRemoveApplications = 0x8000; 4897b3abf1SMichael Lotz 4997b3abf1SMichael Lotz static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys 5097b3abf1SMichael Lotz | kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring 5197b3abf1SMichael Lotz | kFlagEnumerateKeyrings | kFlagSetMasterKey | kFlagRemoveMasterKey 5297b3abf1SMichael Lotz | kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster 53*c8ae843fSMichael Lotz | kFlagEnumerateMasterKeyrings | kFlagQueryLockState | kFlagLockKeyring 54*c8ae843fSMichael Lotz | kFlagEnumerateApplications | kFlagRemoveApplications; 5597b3abf1SMichael Lotz 56f16fef70SMichael Lotz 578d9bc9e0SMichael Lotz KeyStoreServer::KeyStoreServer() 588d9bc9e0SMichael Lotz : 5995eee1a3SMichael Lotz BApplication(kKeyStoreServerSignature), 6095eee1a3SMichael Lotz fDefaultKeyring(NULL), 6195eee1a3SMichael Lotz fKeyrings(20, true) 628d9bc9e0SMichael Lotz { 630dfaf59dSMichael Lotz BPath path; 640dfaf59dSMichael Lotz if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 650dfaf59dSMichael Lotz return; 660dfaf59dSMichael Lotz 670dfaf59dSMichael Lotz BDirectory settingsDir(path.Path()); 680dfaf59dSMichael Lotz path.Append("system"); 690dfaf59dSMichael Lotz if (!settingsDir.Contains(path.Path())) 700dfaf59dSMichael Lotz settingsDir.CreateDirectory(path.Path(), NULL); 710dfaf59dSMichael Lotz 720dfaf59dSMichael Lotz settingsDir.SetTo(path.Path()); 730dfaf59dSMichael Lotz path.Append("keystore"); 740dfaf59dSMichael Lotz if (!settingsDir.Contains(path.Path())) 750dfaf59dSMichael Lotz settingsDir.CreateDirectory(path.Path(), NULL); 760dfaf59dSMichael Lotz 770dfaf59dSMichael Lotz settingsDir.SetTo(path.Path()); 780dfaf59dSMichael Lotz path.Append("keystore_database"); 790dfaf59dSMichael Lotz 800dfaf59dSMichael Lotz fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE 810dfaf59dSMichael Lotz | (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE)); 820dfaf59dSMichael Lotz 830dfaf59dSMichael Lotz _ReadKeyStoreDatabase(); 8495eee1a3SMichael Lotz 8595eee1a3SMichael Lotz if (fDefaultKeyring == NULL) 861b3bb46aSMichael Lotz fDefaultKeyring = new(std::nothrow) Keyring(""); 878d9bc9e0SMichael Lotz } 888d9bc9e0SMichael Lotz 898d9bc9e0SMichael Lotz 908d9bc9e0SMichael Lotz KeyStoreServer::~KeyStoreServer() 918d9bc9e0SMichael Lotz { 928d9bc9e0SMichael Lotz } 938d9bc9e0SMichael Lotz 948d9bc9e0SMichael Lotz 958d9bc9e0SMichael Lotz void 968d9bc9e0SMichael Lotz KeyStoreServer::MessageReceived(BMessage* message) 978d9bc9e0SMichael Lotz { 980dfaf59dSMichael Lotz BMessage reply; 9995eee1a3SMichael Lotz status_t result = B_UNSUPPORTED; 100cfa81315SMichael Lotz app_info callingAppInfo; 101cfa81315SMichael Lotz 102cfa81315SMichael Lotz uint32 accessFlags = _AccessFlagsFor(message->what); 103cfa81315SMichael Lotz if (accessFlags == 0) 104cfa81315SMichael Lotz message->what = 0; 105cfa81315SMichael Lotz 106cfa81315SMichael Lotz if (message->what != 0) { 107cfa81315SMichael Lotz result = _ResolveCallingApp(*message, callingAppInfo); 108cfa81315SMichael Lotz if (result != B_OK) 109cfa81315SMichael Lotz message->what = 0; 110cfa81315SMichael Lotz } 11195eee1a3SMichael Lotz 11295eee1a3SMichael Lotz // Resolve the keyring for the relevant messages. 11395eee1a3SMichael Lotz Keyring* keyring = NULL; 11495eee1a3SMichael Lotz switch (message->what) { 11595eee1a3SMichael Lotz case KEY_STORE_GET_KEY: 11695eee1a3SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 11795eee1a3SMichael Lotz case KEY_STORE_ADD_KEY: 11895eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEY: 119*c8ae843fSMichael Lotz case KEY_STORE_IS_KEYRING_UNLOCKED: 120*c8ae843fSMichael Lotz case KEY_STORE_LOCK_KEYRING: 121f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 122f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 123b31a707aSMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 124b31a707aSMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 12595eee1a3SMichael Lotz { 12695eee1a3SMichael Lotz BString keyringName; 12795eee1a3SMichael Lotz if (message->FindString("keyring", &keyringName) != B_OK) 12895eee1a3SMichael Lotz keyringName = ""; 12995eee1a3SMichael Lotz 13095eee1a3SMichael Lotz keyring = _FindKeyring(keyringName); 13195eee1a3SMichael Lotz if (keyring == NULL) { 13295eee1a3SMichael Lotz result = B_BAD_VALUE; 13395eee1a3SMichael Lotz message->what = 0; 13495eee1a3SMichael Lotz // So that we don't do anything in the second switch. 13595eee1a3SMichael Lotz break; 13695eee1a3SMichael Lotz } 13795eee1a3SMichael Lotz 138ac9b28f0SMichael Lotz switch (message->what) { 139ac9b28f0SMichael Lotz case KEY_STORE_GET_KEY: 140ac9b28f0SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 141ac9b28f0SMichael Lotz case KEY_STORE_ADD_KEY: 142ac9b28f0SMichael Lotz case KEY_STORE_REMOVE_KEY: 143f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 144b31a707aSMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 145b31a707aSMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 146ac9b28f0SMichael Lotz { 147ac9b28f0SMichael Lotz // These need keyring access to do anything. 148*c8ae843fSMichael Lotz while (!keyring->IsUnlocked()) { 149*c8ae843fSMichael Lotz status_t unlockResult = _UnlockKeyring(*keyring); 150*c8ae843fSMichael Lotz if (unlockResult != B_OK) { 151*c8ae843fSMichael Lotz result = unlockResult; 152ac9b28f0SMichael Lotz message->what = 0; 153ac9b28f0SMichael Lotz break; 154ac9b28f0SMichael Lotz } 155ac9b28f0SMichael Lotz } 156cfa81315SMichael Lotz 157cfa81315SMichael Lotz status_t validateResult = _ValidateAppAccess(*keyring, 158cfa81315SMichael Lotz callingAppInfo, accessFlags); 159cfa81315SMichael Lotz if (validateResult != B_OK) { 160cfa81315SMichael Lotz result = validateResult; 161cfa81315SMichael Lotz message->what = 0; 162cfa81315SMichael Lotz break; 163cfa81315SMichael Lotz } 164cfa81315SMichael Lotz 165cfa81315SMichael Lotz break; 166ac9b28f0SMichael Lotz } 167ac9b28f0SMichael Lotz } 168ac9b28f0SMichael Lotz 16995eee1a3SMichael Lotz break; 17095eee1a3SMichael Lotz } 17195eee1a3SMichael Lotz } 1720dfaf59dSMichael Lotz 1738d9bc9e0SMichael Lotz switch (message->what) { 1748d9bc9e0SMichael Lotz case KEY_STORE_GET_KEY: 1758d9bc9e0SMichael Lotz { 17695eee1a3SMichael Lotz BString identifier; 17795eee1a3SMichael Lotz if (message->FindString("identifier", &identifier) != B_OK) { 17895eee1a3SMichael Lotz result = B_BAD_VALUE; 17995eee1a3SMichael Lotz break; 18095eee1a3SMichael Lotz } 18195eee1a3SMichael Lotz 18295eee1a3SMichael Lotz bool secondaryIdentifierOptional; 18395eee1a3SMichael Lotz if (message->FindBool("secondaryIdentifierOptional", 18495eee1a3SMichael Lotz &secondaryIdentifierOptional) != B_OK) { 18595eee1a3SMichael Lotz secondaryIdentifierOptional = false; 18695eee1a3SMichael Lotz } 18795eee1a3SMichael Lotz 18895eee1a3SMichael Lotz BString secondaryIdentifier; 18995eee1a3SMichael Lotz if (message->FindString("secondaryIdentifier", 19095eee1a3SMichael Lotz &secondaryIdentifier) != B_OK) { 19195eee1a3SMichael Lotz secondaryIdentifier = ""; 19295eee1a3SMichael Lotz secondaryIdentifierOptional = true; 19395eee1a3SMichael Lotz } 19495eee1a3SMichael Lotz 19595eee1a3SMichael Lotz BMessage keyMessage; 19695eee1a3SMichael Lotz result = keyring->FindKey(identifier, secondaryIdentifier, 19795eee1a3SMichael Lotz secondaryIdentifierOptional, &keyMessage); 19895eee1a3SMichael Lotz if (result == B_OK) 19995eee1a3SMichael Lotz reply.AddMessage("key", &keyMessage); 200f16fef70SMichael Lotz 2018d9bc9e0SMichael Lotz break; 2028d9bc9e0SMichael Lotz } 2038d9bc9e0SMichael Lotz 2048d9bc9e0SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 2058d9bc9e0SMichael Lotz { 2060dfaf59dSMichael Lotz BKeyType type; 2070dfaf59dSMichael Lotz BKeyPurpose purpose; 2080dfaf59dSMichael Lotz uint32 cookie; 2090dfaf59dSMichael Lotz if (message->FindUInt32("type", (uint32*)&type) != B_OK 2100dfaf59dSMichael Lotz || message->FindUInt32("purpose", (uint32*)&purpose) != B_OK 2110dfaf59dSMichael Lotz || message->FindUInt32("cookie", &cookie) != B_OK) { 2120dfaf59dSMichael Lotz result = B_BAD_VALUE; 2130dfaf59dSMichael Lotz break; 2140dfaf59dSMichael Lotz } 2150dfaf59dSMichael Lotz 2160dfaf59dSMichael Lotz BMessage keyMessage; 21795eee1a3SMichael Lotz result = keyring->FindKey(type, purpose, cookie, keyMessage); 2180dfaf59dSMichael Lotz if (result == B_OK) { 2190dfaf59dSMichael Lotz cookie++; 2200dfaf59dSMichael Lotz reply.AddUInt32("cookie", cookie); 2210dfaf59dSMichael Lotz reply.AddMessage("key", &keyMessage); 2220dfaf59dSMichael Lotz } 2230dfaf59dSMichael Lotz 2240dfaf59dSMichael Lotz break; 2250dfaf59dSMichael Lotz } 2260dfaf59dSMichael Lotz 2270dfaf59dSMichael Lotz case KEY_STORE_ADD_KEY: 2280dfaf59dSMichael Lotz { 2290dfaf59dSMichael Lotz BMessage keyMessage; 2300dfaf59dSMichael Lotz BString identifier; 2310dfaf59dSMichael Lotz if (message->FindMessage("key", &keyMessage) != B_OK 2320dfaf59dSMichael Lotz || keyMessage.FindString("identifier", &identifier) != B_OK) { 2330dfaf59dSMichael Lotz result = B_BAD_VALUE; 2340dfaf59dSMichael Lotz break; 2350dfaf59dSMichael Lotz } 2360dfaf59dSMichael Lotz 2370dfaf59dSMichael Lotz BString secondaryIdentifier; 2380dfaf59dSMichael Lotz if (keyMessage.FindString("secondaryIdentifier", 2390dfaf59dSMichael Lotz &secondaryIdentifier) != B_OK) { 2400dfaf59dSMichael Lotz secondaryIdentifier = ""; 2410dfaf59dSMichael Lotz } 2420dfaf59dSMichael Lotz 24395eee1a3SMichael Lotz result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage); 24495eee1a3SMichael Lotz if (result == B_OK) 24595eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 24695eee1a3SMichael Lotz 24795eee1a3SMichael Lotz break; 24895eee1a3SMichael Lotz } 24995eee1a3SMichael Lotz 25095eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEY: 25195eee1a3SMichael Lotz { 25295eee1a3SMichael Lotz BMessage keyMessage; 25395eee1a3SMichael Lotz BString identifier; 25495eee1a3SMichael Lotz if (message->FindMessage("key", &keyMessage) != B_OK 25595eee1a3SMichael Lotz || keyMessage.FindString("identifier", &identifier) != B_OK) { 25695eee1a3SMichael Lotz result = B_BAD_VALUE; 25795eee1a3SMichael Lotz break; 25895eee1a3SMichael Lotz } 25995eee1a3SMichael Lotz 26095eee1a3SMichael Lotz result = keyring->RemoveKey(identifier, keyMessage); 26195eee1a3SMichael Lotz if (result == B_OK) 26295eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 26395eee1a3SMichael Lotz 26495eee1a3SMichael Lotz break; 26595eee1a3SMichael Lotz } 26695eee1a3SMichael Lotz 26795eee1a3SMichael Lotz case KEY_STORE_ADD_KEYRING: 26895eee1a3SMichael Lotz { 26995eee1a3SMichael Lotz BMessage keyMessage; 27095eee1a3SMichael Lotz BString keyring; 27195eee1a3SMichael Lotz if (message->FindString("keyring", &keyring) != B_OK 27295eee1a3SMichael Lotz || message->FindMessage("key", &keyMessage) != B_OK) { 27395eee1a3SMichael Lotz result = B_BAD_VALUE; 27495eee1a3SMichael Lotz break; 27595eee1a3SMichael Lotz } 27695eee1a3SMichael Lotz 27795eee1a3SMichael Lotz result = _AddKeyring(keyring, keyMessage); 27895eee1a3SMichael Lotz if (result == B_OK) 27995eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 28095eee1a3SMichael Lotz 28195eee1a3SMichael Lotz break; 28295eee1a3SMichael Lotz } 28395eee1a3SMichael Lotz 28495eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEYRING: 28595eee1a3SMichael Lotz { 28695eee1a3SMichael Lotz BString keyringName; 28795eee1a3SMichael Lotz if (message->FindString("keyring", &keyringName) != B_OK) 28895eee1a3SMichael Lotz keyringName = ""; 28995eee1a3SMichael Lotz 29095eee1a3SMichael Lotz result = _RemoveKeyring(keyringName); 29195eee1a3SMichael Lotz if (result == B_OK) 29295eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 29395eee1a3SMichael Lotz 29495eee1a3SMichael Lotz break; 29595eee1a3SMichael Lotz } 29695eee1a3SMichael Lotz 29795eee1a3SMichael Lotz case KEY_STORE_GET_NEXT_KEYRING: 29895eee1a3SMichael Lotz { 29995eee1a3SMichael Lotz uint32 cookie; 30095eee1a3SMichael Lotz if (message->FindUInt32("cookie", &cookie) != B_OK) { 30195eee1a3SMichael Lotz result = B_BAD_VALUE; 30295eee1a3SMichael Lotz break; 30395eee1a3SMichael Lotz } 30495eee1a3SMichael Lotz 30595eee1a3SMichael Lotz if (cookie == 0) 30695eee1a3SMichael Lotz keyring = fDefaultKeyring; 30795eee1a3SMichael Lotz else 30895eee1a3SMichael Lotz keyring = fKeyrings.ItemAt(cookie - 1); 30995eee1a3SMichael Lotz 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 322*c8ae843fSMichael Lotz case KEY_STORE_IS_KEYRING_UNLOCKED: 32395eee1a3SMichael Lotz { 324*c8ae843fSMichael Lotz reply.AddBool("unlocked", keyring->IsUnlocked()); 32595eee1a3SMichael Lotz result = B_OK; 326f16fef70SMichael Lotz break; 32795eee1a3SMichael Lotz } 32895eee1a3SMichael Lotz 329*c8ae843fSMichael Lotz case KEY_STORE_LOCK_KEYRING: 330ac9b28f0SMichael Lotz { 331*c8ae843fSMichael 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 { 339f16fef70SMichael Lotz // We also need access to the default keyring. 340*c8ae843fSMichael Lotz while (!fDefaultKeyring->IsUnlocked()) { 341*c8ae843fSMichael Lotz status_t unlockResult = _UnlockKeyring(*fDefaultKeyring); 342*c8ae843fSMichael Lotz if (unlockResult != B_OK) { 343*c8ae843fSMichael 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: 361f16fef70SMichael Lotz result = fDefaultKeyring->AddKey(kKeyringKeysIdentifier, 362f16fef70SMichael Lotz secondaryIdentifier, keyMessage); 363f16fef70SMichael Lotz break; 364f16fef70SMichael Lotz 365f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 366f16fef70SMichael Lotz result = fDefaultKeyring->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 { 44595eee1a3SMichael Lotz BMessage keyrings; 44695eee1a3SMichael Lotz status_t result = keyrings.Unflatten(&fKeyStoreFile); 4470dfaf59dSMichael Lotz if (result != B_OK) { 4480dfaf59dSMichael Lotz printf("failed to read keystore database\n"); 4490dfaf59dSMichael Lotz _WriteKeyStoreDatabase(); 4500dfaf59dSMichael Lotz return result; 4510dfaf59dSMichael Lotz } 4520dfaf59dSMichael Lotz 45395eee1a3SMichael Lotz int32 index = 0; 45495eee1a3SMichael Lotz char* keyringName = NULL; 4551b3bb46aSMichael Lotz while (keyrings.GetInfo(B_RAW_TYPE, index++, &keyringName, NULL) == B_OK) { 4561b3bb46aSMichael Lotz Keyring* keyring = new(std::nothrow) Keyring(keyringName); 4571b3bb46aSMichael Lotz if (keyring == NULL) { 4581b3bb46aSMichael Lotz printf("no memory for allocating keyring \"%s\"\n", keyringName); 45995eee1a3SMichael Lotz continue; 46095eee1a3SMichael Lotz } 46195eee1a3SMichael Lotz 4621b3bb46aSMichael Lotz status_t result = keyring->ReadFromMessage(keyrings); 4631b3bb46aSMichael Lotz if (result != B_OK) { 4641b3bb46aSMichael Lotz printf("failed to read keyring \"%s\" from data\n", keyringName); 4651b3bb46aSMichael Lotz delete keyring; 46695eee1a3SMichael Lotz continue; 46795eee1a3SMichael Lotz } 46895eee1a3SMichael Lotz 46995eee1a3SMichael Lotz if (strlen(keyringName) == 0) 47095eee1a3SMichael Lotz fDefaultKeyring = keyring; 47195eee1a3SMichael Lotz else 47295eee1a3SMichael Lotz fKeyrings.BinaryInsert(keyring, &Keyring::Compare); 47395eee1a3SMichael Lotz } 47495eee1a3SMichael Lotz 4750dfaf59dSMichael Lotz return B_OK; 4760dfaf59dSMichael Lotz } 4770dfaf59dSMichael Lotz 4780dfaf59dSMichael Lotz 4790dfaf59dSMichael Lotz status_t 4800dfaf59dSMichael Lotz KeyStoreServer::_WriteKeyStoreDatabase() 4810dfaf59dSMichael Lotz { 48295eee1a3SMichael Lotz BMessage keyrings; 48395eee1a3SMichael Lotz if (fDefaultKeyring != NULL) 4841b3bb46aSMichael Lotz fDefaultKeyring->WriteToMessage(keyrings); 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 4911b3bb46aSMichael Lotz status_t result = keyring->WriteToMessage(keyrings); 4921b3bb46aSMichael Lotz if (result != B_OK) 4931b3bb46aSMichael Lotz return result; 4940dfaf59dSMichael Lotz } 4950dfaf59dSMichael Lotz 496aef629f2SMichael Lotz fKeyStoreFile.SetSize(0); 497aef629f2SMichael Lotz fKeyStoreFile.Seek(0, SEEK_SET); 49895eee1a3SMichael Lotz return keyrings.Flatten(&fKeyStoreFile); 4990dfaf59dSMichael Lotz } 5000dfaf59dSMichael Lotz 5010dfaf59dSMichael Lotz 50297b3abf1SMichael Lotz uint32 50397b3abf1SMichael Lotz KeyStoreServer::_AccessFlagsFor(uint32 command) const 50497b3abf1SMichael Lotz { 50597b3abf1SMichael Lotz switch (command) { 50697b3abf1SMichael Lotz case KEY_STORE_GET_KEY: 50797b3abf1SMichael Lotz return kFlagGetKey; 50897b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 50997b3abf1SMichael Lotz return kFlagEnumerateKeys; 51097b3abf1SMichael Lotz case KEY_STORE_ADD_KEY: 51197b3abf1SMichael Lotz return kFlagAddKey; 51297b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEY: 51397b3abf1SMichael Lotz return kFlagRemoveKey; 51497b3abf1SMichael Lotz case KEY_STORE_ADD_KEYRING: 51597b3abf1SMichael Lotz return kFlagAddKeyring; 51697b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEYRING: 51797b3abf1SMichael Lotz return kFlagRemoveKeyring; 51897b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_KEYRING: 51997b3abf1SMichael Lotz return kFlagEnumerateKeyrings; 52097b3abf1SMichael Lotz case KEY_STORE_SET_MASTER_KEY: 52197b3abf1SMichael Lotz return kFlagSetMasterKey; 52297b3abf1SMichael Lotz case KEY_STORE_REMOVE_MASTER_KEY: 52397b3abf1SMichael Lotz return kFlagRemoveMasterKey; 52497b3abf1SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 52597b3abf1SMichael Lotz return kFlagAddKeyringsToMaster; 52697b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 52797b3abf1SMichael Lotz return kFlagRemoveKeyringsFromMaster; 52897b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_MASTER_KEYRING: 52997b3abf1SMichael Lotz return kFlagEnumerateMasterKeyrings; 530*c8ae843fSMichael Lotz case KEY_STORE_IS_KEYRING_UNLOCKED: 531*c8ae843fSMichael Lotz return kFlagQueryLockState; 532*c8ae843fSMichael Lotz case KEY_STORE_LOCK_KEYRING: 533*c8ae843fSMichael Lotz return kFlagLockKeyring; 53497b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 53597b3abf1SMichael Lotz return kFlagEnumerateApplications; 53697b3abf1SMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 53797b3abf1SMichael Lotz return kFlagRemoveApplications; 53897b3abf1SMichael Lotz } 53997b3abf1SMichael Lotz 54097b3abf1SMichael Lotz return 0; 54197b3abf1SMichael Lotz } 54297b3abf1SMichael Lotz 54397b3abf1SMichael Lotz 54476df966eSMichael Lotz status_t 54576df966eSMichael Lotz KeyStoreServer::_ResolveCallingApp(const BMessage& message, 54676df966eSMichael Lotz app_info& callingAppInfo) const 54776df966eSMichael Lotz { 54876df966eSMichael Lotz team_id callingTeam = message.ReturnAddress().Team(); 54976df966eSMichael Lotz status_t result = be_roster->GetRunningAppInfo(callingTeam, 55076df966eSMichael Lotz &callingAppInfo); 55176df966eSMichael Lotz if (result != B_OK) 55276df966eSMichael Lotz return result; 55376df966eSMichael Lotz 55476df966eSMichael Lotz // Do some sanity checks. 55576df966eSMichael Lotz if (callingAppInfo.team != callingTeam) 55676df966eSMichael Lotz return B_ERROR; 55776df966eSMichael Lotz 55876df966eSMichael Lotz return B_OK; 55976df966eSMichael Lotz } 56076df966eSMichael Lotz 56176df966eSMichael Lotz 562cfa81315SMichael Lotz status_t 563cfa81315SMichael Lotz KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo, 564cfa81315SMichael Lotz uint32 accessFlags) 565cfa81315SMichael Lotz { 566cfa81315SMichael Lotz BMessage appMessage; 567cfa81315SMichael Lotz BPath path(&appInfo.ref); 568cfa81315SMichael Lotz status_t result = keyring.FindApplication(appInfo.signature, 569cfa81315SMichael Lotz path.Path(), appMessage); 570cfa81315SMichael Lotz if (result != B_OK && result != B_ENTRY_NOT_FOUND) 571cfa81315SMichael Lotz return result; 572cfa81315SMichael Lotz 573cfa81315SMichael Lotz // TODO: Implement running image checksum mechanism. 574cfa81315SMichael Lotz BString checksum = "dummy"; 575cfa81315SMichael Lotz 576cfa81315SMichael Lotz bool appIsNew = false; 577cfa81315SMichael Lotz bool appWasUpdated = false; 578cfa81315SMichael Lotz uint32 appFlags = 0; 579cfa81315SMichael Lotz BString appSum = ""; 580cfa81315SMichael Lotz if (result == B_OK) { 581cfa81315SMichael Lotz if (appMessage.FindUInt32("flags", &appFlags) != B_OK 582cfa81315SMichael Lotz || appMessage.FindString("checksum", &appSum) != B_OK) { 583cfa81315SMichael Lotz appIsNew = true; 584cfa81315SMichael Lotz appFlags = 0; 585cfa81315SMichael Lotz } else if (appSum != checksum) { 586cfa81315SMichael Lotz appWasUpdated = true; 587cfa81315SMichael Lotz appFlags = 0; 588cfa81315SMichael Lotz } 589cfa81315SMichael Lotz } else 590cfa81315SMichael Lotz appIsNew = true; 591cfa81315SMichael Lotz 592cfa81315SMichael Lotz if ((accessFlags & appFlags) == accessFlags) 593cfa81315SMichael Lotz return B_OK; 594cfa81315SMichael Lotz 595cfa81315SMichael Lotz bool allowAlways = false; 596cfa81315SMichael Lotz result = _RequestAppAccess(keyring.Name(), appInfo.signature, path.Path(), 597cfa81315SMichael Lotz appIsNew, appWasUpdated, accessFlags, allowAlways); 598cfa81315SMichael Lotz if (result != B_OK || !allowAlways) 599cfa81315SMichael Lotz return result; 600cfa81315SMichael Lotz 601cfa81315SMichael Lotz appMessage.MakeEmpty(); 602cfa81315SMichael Lotz appMessage.AddString("path", path.Path()); 603cfa81315SMichael Lotz appMessage.AddUInt32("flags", accessFlags); 604cfa81315SMichael Lotz appMessage.AddString("checksum", checksum); 605cfa81315SMichael Lotz 606cfa81315SMichael Lotz keyring.RemoveApplication(appInfo.signature, path.Path()); 607cfa81315SMichael Lotz if (keyring.AddApplication(appInfo.signature, appMessage) == B_OK) 608cfa81315SMichael Lotz _WriteKeyStoreDatabase(); 609cfa81315SMichael Lotz 610cfa81315SMichael Lotz return B_OK; 611cfa81315SMichael Lotz } 612cfa81315SMichael Lotz 613cfa81315SMichael Lotz 614cfa81315SMichael Lotz status_t 615cfa81315SMichael Lotz KeyStoreServer::_RequestAppAccess(const BString& keyringName, 616cfa81315SMichael Lotz const char* signature, const char* path, bool appIsNew, bool appWasUpdated, 617cfa81315SMichael Lotz uint32 accessFlags, bool& allowAlways) 618cfa81315SMichael Lotz { 619cfa81315SMichael Lotz AppAccessRequestWindow* requestWindow 620cfa81315SMichael Lotz = new(std::nothrow) AppAccessRequestWindow(keyringName, signature, path, 621cfa81315SMichael Lotz appIsNew, appWasUpdated); 622cfa81315SMichael Lotz if (requestWindow == NULL) 623cfa81315SMichael Lotz return B_NO_MEMORY; 624cfa81315SMichael Lotz 625cfa81315SMichael Lotz return requestWindow->RequestAppAccess(allowAlways); 626cfa81315SMichael Lotz } 627cfa81315SMichael Lotz 628cfa81315SMichael Lotz 62995eee1a3SMichael Lotz Keyring* 63095eee1a3SMichael Lotz KeyStoreServer::_FindKeyring(const BString& name) 63195eee1a3SMichael Lotz { 63295eee1a3SMichael Lotz if (name.IsEmpty()) 63395eee1a3SMichael Lotz return fDefaultKeyring; 6340dfaf59dSMichael Lotz 63595eee1a3SMichael Lotz return fKeyrings.BinarySearchByKey(name, &Keyring::Compare); 6360dfaf59dSMichael Lotz } 6370dfaf59dSMichael Lotz 6380dfaf59dSMichael Lotz 6390dfaf59dSMichael Lotz status_t 64095eee1a3SMichael Lotz KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage) 6410dfaf59dSMichael Lotz { 64295eee1a3SMichael Lotz if (_FindKeyring(name) != NULL) 6430dfaf59dSMichael Lotz return B_NAME_IN_USE; 6440dfaf59dSMichael Lotz 6451b3bb46aSMichael Lotz Keyring* keyring = new(std::nothrow) Keyring(name, &keyMessage); 64695eee1a3SMichael Lotz if (keyring == NULL) 64795eee1a3SMichael Lotz return B_NO_MEMORY; 64895eee1a3SMichael Lotz 64995eee1a3SMichael Lotz if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) { 65095eee1a3SMichael Lotz delete keyring; 65195eee1a3SMichael Lotz return B_ERROR; 65295eee1a3SMichael Lotz } 65395eee1a3SMichael Lotz 65495eee1a3SMichael Lotz return B_OK; 65595eee1a3SMichael Lotz } 65695eee1a3SMichael Lotz 65795eee1a3SMichael Lotz 65895eee1a3SMichael Lotz status_t 65995eee1a3SMichael Lotz KeyStoreServer::_RemoveKeyring(const BString& name) 66095eee1a3SMichael Lotz { 66195eee1a3SMichael Lotz Keyring* keyring = _FindKeyring(name); 66295eee1a3SMichael Lotz if (keyring == NULL) 66395eee1a3SMichael Lotz return B_ENTRY_NOT_FOUND; 66495eee1a3SMichael Lotz 66595eee1a3SMichael Lotz if (keyring == fDefaultKeyring) { 66695eee1a3SMichael Lotz // The default keyring can't be removed. 66795eee1a3SMichael Lotz return B_NOT_ALLOWED; 66895eee1a3SMichael Lotz } 66995eee1a3SMichael Lotz 67095eee1a3SMichael Lotz return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR; 6718d9bc9e0SMichael Lotz } 6728d9bc9e0SMichael Lotz 6738d9bc9e0SMichael Lotz 674ac9b28f0SMichael Lotz status_t 675*c8ae843fSMichael Lotz KeyStoreServer::_UnlockKeyring(Keyring& keyring) 676ac9b28f0SMichael Lotz { 677ac9b28f0SMichael Lotz // If we are accessing a keyring that has been added to master access we 678ac9b28f0SMichael Lotz // get the key from the default keyring and unlock with that. 679ac9b28f0SMichael Lotz BMessage keyMessage; 680*c8ae843fSMichael Lotz if (&keyring != fDefaultKeyring && fDefaultKeyring->IsUnlocked()) { 681f16fef70SMichael Lotz if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), 682f16fef70SMichael Lotz false, &keyMessage) == B_OK) { 683*c8ae843fSMichael Lotz // We found a key for this keyring, try to unlock with it. 684*c8ae843fSMichael Lotz if (keyring.Unlock(keyMessage) == B_OK) 685ac9b28f0SMichael Lotz return B_OK; 686ac9b28f0SMichael Lotz } 687ac9b28f0SMichael Lotz } 688ac9b28f0SMichael Lotz 689ac9b28f0SMichael Lotz // No key, we need to request one from the user. 69090013c82SMichael Lotz status_t result = _RequestKey(keyring.Name(), keyMessage); 691ac9b28f0SMichael Lotz if (result != B_OK) 692ac9b28f0SMichael Lotz return result; 693ac9b28f0SMichael Lotz 694*c8ae843fSMichael Lotz return keyring.Unlock(keyMessage); 695ac9b28f0SMichael Lotz } 696ac9b28f0SMichael Lotz 697ac9b28f0SMichael Lotz 698ac9b28f0SMichael Lotz status_t 69990013c82SMichael Lotz KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage) 700ac9b28f0SMichael Lotz { 701ac9b28f0SMichael Lotz KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow(); 702ac9b28f0SMichael Lotz if (requestWindow == NULL) 703ac9b28f0SMichael Lotz return B_NO_MEMORY; 704ac9b28f0SMichael Lotz 70590013c82SMichael Lotz return requestWindow->RequestKey(keyringName, keyMessage); 706ac9b28f0SMichael Lotz } 707ac9b28f0SMichael Lotz 708ac9b28f0SMichael Lotz 7098d9bc9e0SMichael Lotz int 7108d9bc9e0SMichael Lotz main(int argc, char* argv[]) 7118d9bc9e0SMichael Lotz { 7128d9bc9e0SMichael Lotz KeyStoreServer* app = new(std::nothrow) KeyStoreServer(); 7138d9bc9e0SMichael Lotz if (app == NULL) 7148d9bc9e0SMichael Lotz return 1; 7158d9bc9e0SMichael Lotz 7168d9bc9e0SMichael Lotz app->Run(); 7178d9bc9e0SMichael Lotz delete app; 7188d9bc9e0SMichael Lotz return 0; 7198d9bc9e0SMichael Lotz } 720