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 9*cfa81315SMichael 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; 4497b3abf1SMichael Lotz static const uint32 kFlagQueryAccessibility = 0x1000; 4597b3abf1SMichael Lotz static const uint32 kFlagRevokeAccess = 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 5397b3abf1SMichael Lotz | kFlagEnumerateMasterKeyrings | kFlagQueryAccessibility 5497b3abf1SMichael Lotz | kFlagQueryAccessibility | kFlagRevokeAccess | kFlagEnumerateApplications 5597b3abf1SMichael Lotz | kFlagRemoveApplications; 5697b3abf1SMichael Lotz 57f16fef70SMichael Lotz 588d9bc9e0SMichael Lotz KeyStoreServer::KeyStoreServer() 598d9bc9e0SMichael Lotz : 6095eee1a3SMichael Lotz BApplication(kKeyStoreServerSignature), 6195eee1a3SMichael Lotz fDefaultKeyring(NULL), 6295eee1a3SMichael Lotz fKeyrings(20, true) 638d9bc9e0SMichael Lotz { 640dfaf59dSMichael Lotz BPath path; 650dfaf59dSMichael Lotz if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 660dfaf59dSMichael Lotz return; 670dfaf59dSMichael Lotz 680dfaf59dSMichael Lotz BDirectory settingsDir(path.Path()); 690dfaf59dSMichael Lotz path.Append("system"); 700dfaf59dSMichael Lotz if (!settingsDir.Contains(path.Path())) 710dfaf59dSMichael Lotz settingsDir.CreateDirectory(path.Path(), NULL); 720dfaf59dSMichael Lotz 730dfaf59dSMichael Lotz settingsDir.SetTo(path.Path()); 740dfaf59dSMichael Lotz path.Append("keystore"); 750dfaf59dSMichael Lotz if (!settingsDir.Contains(path.Path())) 760dfaf59dSMichael Lotz settingsDir.CreateDirectory(path.Path(), NULL); 770dfaf59dSMichael Lotz 780dfaf59dSMichael Lotz settingsDir.SetTo(path.Path()); 790dfaf59dSMichael Lotz path.Append("keystore_database"); 800dfaf59dSMichael Lotz 810dfaf59dSMichael Lotz fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE 820dfaf59dSMichael Lotz | (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE)); 830dfaf59dSMichael Lotz 840dfaf59dSMichael Lotz _ReadKeyStoreDatabase(); 8595eee1a3SMichael Lotz 8695eee1a3SMichael Lotz if (fDefaultKeyring == NULL) 871b3bb46aSMichael Lotz fDefaultKeyring = new(std::nothrow) Keyring(""); 888d9bc9e0SMichael Lotz } 898d9bc9e0SMichael Lotz 908d9bc9e0SMichael Lotz 918d9bc9e0SMichael Lotz KeyStoreServer::~KeyStoreServer() 928d9bc9e0SMichael Lotz { 938d9bc9e0SMichael Lotz } 948d9bc9e0SMichael Lotz 958d9bc9e0SMichael Lotz 968d9bc9e0SMichael Lotz void 978d9bc9e0SMichael Lotz KeyStoreServer::MessageReceived(BMessage* message) 988d9bc9e0SMichael Lotz { 990dfaf59dSMichael Lotz BMessage reply; 10095eee1a3SMichael Lotz status_t result = B_UNSUPPORTED; 101*cfa81315SMichael Lotz app_info callingAppInfo; 102*cfa81315SMichael Lotz 103*cfa81315SMichael Lotz uint32 accessFlags = _AccessFlagsFor(message->what); 104*cfa81315SMichael Lotz if (accessFlags == 0) 105*cfa81315SMichael Lotz message->what = 0; 106*cfa81315SMichael Lotz 107*cfa81315SMichael Lotz if (message->what != 0) { 108*cfa81315SMichael Lotz result = _ResolveCallingApp(*message, callingAppInfo); 109*cfa81315SMichael Lotz if (result != B_OK) 110*cfa81315SMichael Lotz message->what = 0; 111*cfa81315SMichael Lotz } 11295eee1a3SMichael Lotz 11395eee1a3SMichael Lotz // Resolve the keyring for the relevant messages. 11495eee1a3SMichael Lotz Keyring* keyring = NULL; 11595eee1a3SMichael Lotz switch (message->what) { 11695eee1a3SMichael Lotz case KEY_STORE_GET_KEY: 11795eee1a3SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 11895eee1a3SMichael Lotz case KEY_STORE_ADD_KEY: 11995eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEY: 12095eee1a3SMichael Lotz case KEY_STORE_IS_KEYRING_ACCESSIBLE: 12195eee1a3SMichael Lotz case KEY_STORE_REVOKE_ACCESS: 122f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 123f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 12495eee1a3SMichael Lotz { 12595eee1a3SMichael Lotz BString keyringName; 12695eee1a3SMichael Lotz if (message->FindString("keyring", &keyringName) != B_OK) 12795eee1a3SMichael Lotz keyringName = ""; 12895eee1a3SMichael Lotz 12995eee1a3SMichael Lotz keyring = _FindKeyring(keyringName); 13095eee1a3SMichael Lotz if (keyring == NULL) { 13195eee1a3SMichael Lotz result = B_BAD_VALUE; 13295eee1a3SMichael Lotz message->what = 0; 13395eee1a3SMichael Lotz // So that we don't do anything in the second switch. 13495eee1a3SMichael Lotz break; 13595eee1a3SMichael Lotz } 13695eee1a3SMichael Lotz 137ac9b28f0SMichael Lotz switch (message->what) { 138ac9b28f0SMichael Lotz case KEY_STORE_GET_KEY: 139ac9b28f0SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 140ac9b28f0SMichael Lotz case KEY_STORE_ADD_KEY: 141ac9b28f0SMichael Lotz case KEY_STORE_REMOVE_KEY: 142f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 143ac9b28f0SMichael Lotz { 144ac9b28f0SMichael Lotz // These need keyring access to do anything. 145ac9b28f0SMichael Lotz while (!keyring->IsAccessible()) { 146ac9b28f0SMichael Lotz status_t accessResult = _AccessKeyring(*keyring); 147ac9b28f0SMichael Lotz if (accessResult != B_OK) { 148ac9b28f0SMichael Lotz result = accessResult; 149ac9b28f0SMichael Lotz message->what = 0; 150ac9b28f0SMichael Lotz break; 151ac9b28f0SMichael Lotz } 152ac9b28f0SMichael Lotz } 153*cfa81315SMichael Lotz 154*cfa81315SMichael Lotz status_t validateResult = _ValidateAppAccess(*keyring, 155*cfa81315SMichael Lotz callingAppInfo, accessFlags); 156*cfa81315SMichael Lotz if (validateResult != B_OK) { 157*cfa81315SMichael Lotz result = validateResult; 158*cfa81315SMichael Lotz message->what = 0; 159*cfa81315SMichael Lotz break; 160*cfa81315SMichael Lotz } 161*cfa81315SMichael Lotz 162*cfa81315SMichael Lotz break; 163ac9b28f0SMichael Lotz } 164ac9b28f0SMichael Lotz } 165ac9b28f0SMichael Lotz 16695eee1a3SMichael Lotz break; 16795eee1a3SMichael Lotz } 16895eee1a3SMichael Lotz } 1690dfaf59dSMichael Lotz 1708d9bc9e0SMichael Lotz switch (message->what) { 1718d9bc9e0SMichael Lotz case KEY_STORE_GET_KEY: 1728d9bc9e0SMichael Lotz { 17395eee1a3SMichael Lotz BString identifier; 17495eee1a3SMichael Lotz if (message->FindString("identifier", &identifier) != B_OK) { 17595eee1a3SMichael Lotz result = B_BAD_VALUE; 17695eee1a3SMichael Lotz break; 17795eee1a3SMichael Lotz } 17895eee1a3SMichael Lotz 17995eee1a3SMichael Lotz bool secondaryIdentifierOptional; 18095eee1a3SMichael Lotz if (message->FindBool("secondaryIdentifierOptional", 18195eee1a3SMichael Lotz &secondaryIdentifierOptional) != B_OK) { 18295eee1a3SMichael Lotz secondaryIdentifierOptional = false; 18395eee1a3SMichael Lotz } 18495eee1a3SMichael Lotz 18595eee1a3SMichael Lotz BString secondaryIdentifier; 18695eee1a3SMichael Lotz if (message->FindString("secondaryIdentifier", 18795eee1a3SMichael Lotz &secondaryIdentifier) != B_OK) { 18895eee1a3SMichael Lotz secondaryIdentifier = ""; 18995eee1a3SMichael Lotz secondaryIdentifierOptional = true; 19095eee1a3SMichael Lotz } 19195eee1a3SMichael Lotz 19295eee1a3SMichael Lotz BMessage keyMessage; 19395eee1a3SMichael Lotz result = keyring->FindKey(identifier, secondaryIdentifier, 19495eee1a3SMichael Lotz secondaryIdentifierOptional, &keyMessage); 19595eee1a3SMichael Lotz if (result == B_OK) 19695eee1a3SMichael Lotz reply.AddMessage("key", &keyMessage); 197f16fef70SMichael Lotz 1988d9bc9e0SMichael Lotz break; 1998d9bc9e0SMichael Lotz } 2008d9bc9e0SMichael Lotz 2018d9bc9e0SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 2028d9bc9e0SMichael Lotz { 2030dfaf59dSMichael Lotz BKeyType type; 2040dfaf59dSMichael Lotz BKeyPurpose purpose; 2050dfaf59dSMichael Lotz uint32 cookie; 2060dfaf59dSMichael Lotz if (message->FindUInt32("type", (uint32*)&type) != B_OK 2070dfaf59dSMichael Lotz || message->FindUInt32("purpose", (uint32*)&purpose) != B_OK 2080dfaf59dSMichael Lotz || message->FindUInt32("cookie", &cookie) != B_OK) { 2090dfaf59dSMichael Lotz result = B_BAD_VALUE; 2100dfaf59dSMichael Lotz break; 2110dfaf59dSMichael Lotz } 2120dfaf59dSMichael Lotz 2130dfaf59dSMichael Lotz BMessage keyMessage; 21495eee1a3SMichael Lotz result = keyring->FindKey(type, purpose, cookie, keyMessage); 2150dfaf59dSMichael Lotz if (result == B_OK) { 2160dfaf59dSMichael Lotz cookie++; 2170dfaf59dSMichael Lotz reply.AddUInt32("cookie", cookie); 2180dfaf59dSMichael Lotz reply.AddMessage("key", &keyMessage); 2190dfaf59dSMichael Lotz } 2200dfaf59dSMichael Lotz 2210dfaf59dSMichael Lotz break; 2220dfaf59dSMichael Lotz } 2230dfaf59dSMichael Lotz 2240dfaf59dSMichael Lotz case KEY_STORE_ADD_KEY: 2250dfaf59dSMichael Lotz { 2260dfaf59dSMichael Lotz BMessage keyMessage; 2270dfaf59dSMichael Lotz BString identifier; 2280dfaf59dSMichael Lotz if (message->FindMessage("key", &keyMessage) != B_OK 2290dfaf59dSMichael Lotz || keyMessage.FindString("identifier", &identifier) != B_OK) { 2300dfaf59dSMichael Lotz result = B_BAD_VALUE; 2310dfaf59dSMichael Lotz break; 2320dfaf59dSMichael Lotz } 2330dfaf59dSMichael Lotz 2340dfaf59dSMichael Lotz BString secondaryIdentifier; 2350dfaf59dSMichael Lotz if (keyMessage.FindString("secondaryIdentifier", 2360dfaf59dSMichael Lotz &secondaryIdentifier) != B_OK) { 2370dfaf59dSMichael Lotz secondaryIdentifier = ""; 2380dfaf59dSMichael Lotz } 2390dfaf59dSMichael Lotz 24095eee1a3SMichael Lotz result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage); 24195eee1a3SMichael Lotz if (result == B_OK) 24295eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 24395eee1a3SMichael Lotz 24495eee1a3SMichael Lotz break; 24595eee1a3SMichael Lotz } 24695eee1a3SMichael Lotz 24795eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEY: 24895eee1a3SMichael Lotz { 24995eee1a3SMichael Lotz BMessage keyMessage; 25095eee1a3SMichael Lotz BString identifier; 25195eee1a3SMichael Lotz if (message->FindMessage("key", &keyMessage) != B_OK 25295eee1a3SMichael Lotz || keyMessage.FindString("identifier", &identifier) != B_OK) { 25395eee1a3SMichael Lotz result = B_BAD_VALUE; 25495eee1a3SMichael Lotz break; 25595eee1a3SMichael Lotz } 25695eee1a3SMichael Lotz 25795eee1a3SMichael Lotz result = keyring->RemoveKey(identifier, keyMessage); 25895eee1a3SMichael Lotz if (result == B_OK) 25995eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 26095eee1a3SMichael Lotz 26195eee1a3SMichael Lotz break; 26295eee1a3SMichael Lotz } 26395eee1a3SMichael Lotz 26495eee1a3SMichael Lotz case KEY_STORE_ADD_KEYRING: 26595eee1a3SMichael Lotz { 26695eee1a3SMichael Lotz BMessage keyMessage; 26795eee1a3SMichael Lotz BString keyring; 26895eee1a3SMichael Lotz if (message->FindString("keyring", &keyring) != B_OK 26995eee1a3SMichael Lotz || message->FindMessage("key", &keyMessage) != B_OK) { 27095eee1a3SMichael Lotz result = B_BAD_VALUE; 27195eee1a3SMichael Lotz break; 27295eee1a3SMichael Lotz } 27395eee1a3SMichael Lotz 27495eee1a3SMichael Lotz result = _AddKeyring(keyring, keyMessage); 27595eee1a3SMichael Lotz if (result == B_OK) 27695eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 27795eee1a3SMichael Lotz 27895eee1a3SMichael Lotz break; 27995eee1a3SMichael Lotz } 28095eee1a3SMichael Lotz 28195eee1a3SMichael Lotz case KEY_STORE_REMOVE_KEYRING: 28295eee1a3SMichael Lotz { 28395eee1a3SMichael Lotz BString keyringName; 28495eee1a3SMichael Lotz if (message->FindString("keyring", &keyringName) != B_OK) 28595eee1a3SMichael Lotz keyringName = ""; 28695eee1a3SMichael Lotz 28795eee1a3SMichael Lotz result = _RemoveKeyring(keyringName); 28895eee1a3SMichael Lotz if (result == B_OK) 28995eee1a3SMichael Lotz _WriteKeyStoreDatabase(); 29095eee1a3SMichael Lotz 29195eee1a3SMichael Lotz break; 29295eee1a3SMichael Lotz } 29395eee1a3SMichael Lotz 29495eee1a3SMichael Lotz case KEY_STORE_GET_NEXT_KEYRING: 29595eee1a3SMichael Lotz { 29695eee1a3SMichael Lotz uint32 cookie; 29795eee1a3SMichael Lotz if (message->FindUInt32("cookie", &cookie) != B_OK) { 29895eee1a3SMichael Lotz result = B_BAD_VALUE; 29995eee1a3SMichael Lotz break; 30095eee1a3SMichael Lotz } 30195eee1a3SMichael Lotz 30295eee1a3SMichael Lotz if (cookie == 0) 30395eee1a3SMichael Lotz keyring = fDefaultKeyring; 30495eee1a3SMichael Lotz else 30595eee1a3SMichael Lotz keyring = fKeyrings.ItemAt(cookie - 1); 30695eee1a3SMichael Lotz 30795eee1a3SMichael Lotz if (keyring == NULL) { 30895eee1a3SMichael Lotz result = B_ENTRY_NOT_FOUND; 30995eee1a3SMichael Lotz break; 31095eee1a3SMichael Lotz } 31195eee1a3SMichael Lotz 31295eee1a3SMichael Lotz cookie++; 31395eee1a3SMichael Lotz reply.AddUInt32("cookie", cookie); 31495eee1a3SMichael Lotz reply.AddString("keyring", keyring->Name()); 31595eee1a3SMichael Lotz result = B_OK; 31695eee1a3SMichael Lotz break; 31795eee1a3SMichael Lotz } 31895eee1a3SMichael Lotz 31995eee1a3SMichael Lotz case KEY_STORE_IS_KEYRING_ACCESSIBLE: 32095eee1a3SMichael Lotz { 32195eee1a3SMichael Lotz reply.AddBool("accessible", keyring->IsAccessible()); 32295eee1a3SMichael Lotz result = B_OK; 323f16fef70SMichael Lotz break; 32495eee1a3SMichael Lotz } 32595eee1a3SMichael Lotz 326ac9b28f0SMichael Lotz case KEY_STORE_REVOKE_ACCESS: 327ac9b28f0SMichael Lotz { 328ac9b28f0SMichael Lotz keyring->RevokeAccess(); 329ac9b28f0SMichael Lotz result = B_OK; 330f16fef70SMichael Lotz break; 331f16fef70SMichael Lotz } 332f16fef70SMichael Lotz 333f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 334f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 335f16fef70SMichael Lotz { 336f16fef70SMichael Lotz // We also need access to the default keyring. 337f16fef70SMichael Lotz while (!fDefaultKeyring->IsAccessible()) { 338f16fef70SMichael Lotz status_t accessResult = _AccessKeyring(*fDefaultKeyring); 339f16fef70SMichael Lotz if (accessResult != B_OK) { 340f16fef70SMichael Lotz result = accessResult; 341f16fef70SMichael Lotz message->what = 0; 342f16fef70SMichael Lotz break; 343f16fef70SMichael Lotz } 344f16fef70SMichael Lotz } 345f16fef70SMichael Lotz 346f16fef70SMichael Lotz if (message->what == 0) 347f16fef70SMichael Lotz break; 348f16fef70SMichael Lotz 349f16fef70SMichael Lotz BString secondaryIdentifier = keyring->Name(); 350f16fef70SMichael Lotz BMessage keyMessage = keyring->KeyMessage(); 351f16fef70SMichael Lotz keyMessage.RemoveName("identifier"); 352f16fef70SMichael Lotz keyMessage.AddString("identifier", kKeyringKeysIdentifier); 353f16fef70SMichael Lotz keyMessage.RemoveName("secondaryIdentifier"); 354f16fef70SMichael Lotz keyMessage.AddString("secondaryIdentifier", secondaryIdentifier); 355f16fef70SMichael Lotz 356f16fef70SMichael Lotz switch (message->what) { 357f16fef70SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 358f16fef70SMichael Lotz result = fDefaultKeyring->AddKey(kKeyringKeysIdentifier, 359f16fef70SMichael Lotz secondaryIdentifier, keyMessage); 360f16fef70SMichael Lotz break; 361f16fef70SMichael Lotz 362f16fef70SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 363f16fef70SMichael Lotz result = fDefaultKeyring->RemoveKey(kKeyringKeysIdentifier, 364f16fef70SMichael Lotz keyMessage); 365f16fef70SMichael Lotz break; 366f16fef70SMichael Lotz } 367f16fef70SMichael Lotz 368f16fef70SMichael Lotz if (result == B_OK) 369f16fef70SMichael Lotz _WriteKeyStoreDatabase(); 370f16fef70SMichael Lotz 371f16fef70SMichael Lotz break; 372ac9b28f0SMichael Lotz } 373ac9b28f0SMichael Lotz 37495eee1a3SMichael Lotz case 0: 37595eee1a3SMichael Lotz { 37695eee1a3SMichael Lotz // Just the error case from above. 3778d9bc9e0SMichael Lotz break; 3788d9bc9e0SMichael Lotz } 3798d9bc9e0SMichael Lotz 3808d9bc9e0SMichael Lotz default: 3818d9bc9e0SMichael Lotz { 3828d9bc9e0SMichael Lotz printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n", 3838d9bc9e0SMichael Lotz message->what, (const char*)&message->what); 3848d9bc9e0SMichael Lotz break; 3858d9bc9e0SMichael Lotz } 3868d9bc9e0SMichael Lotz } 3878d9bc9e0SMichael Lotz 3880dfaf59dSMichael Lotz if (message->IsSourceWaiting()) { 3890dfaf59dSMichael Lotz if (result == B_OK) 3900dfaf59dSMichael Lotz reply.what = KEY_STORE_SUCCESS; 3910dfaf59dSMichael Lotz else { 3920dfaf59dSMichael Lotz reply.what = KEY_STORE_RESULT; 3930dfaf59dSMichael Lotz reply.AddInt32("result", result); 3940dfaf59dSMichael Lotz } 3950dfaf59dSMichael Lotz 3960dfaf59dSMichael Lotz message->SendReply(&reply); 3970dfaf59dSMichael Lotz } 3988d9bc9e0SMichael Lotz } 3998d9bc9e0SMichael Lotz 4008d9bc9e0SMichael Lotz 4018d9bc9e0SMichael Lotz status_t 4020dfaf59dSMichael Lotz KeyStoreServer::_ReadKeyStoreDatabase() 4038d9bc9e0SMichael Lotz { 40495eee1a3SMichael Lotz BMessage keyrings; 40595eee1a3SMichael Lotz status_t result = keyrings.Unflatten(&fKeyStoreFile); 4060dfaf59dSMichael Lotz if (result != B_OK) { 4070dfaf59dSMichael Lotz printf("failed to read keystore database\n"); 4080dfaf59dSMichael Lotz _WriteKeyStoreDatabase(); 4090dfaf59dSMichael Lotz return result; 4100dfaf59dSMichael Lotz } 4110dfaf59dSMichael Lotz 41295eee1a3SMichael Lotz int32 index = 0; 41395eee1a3SMichael Lotz char* keyringName = NULL; 4141b3bb46aSMichael Lotz while (keyrings.GetInfo(B_RAW_TYPE, index++, &keyringName, NULL) == B_OK) { 4151b3bb46aSMichael Lotz Keyring* keyring = new(std::nothrow) Keyring(keyringName); 4161b3bb46aSMichael Lotz if (keyring == NULL) { 4171b3bb46aSMichael Lotz printf("no memory for allocating keyring \"%s\"\n", keyringName); 41895eee1a3SMichael Lotz continue; 41995eee1a3SMichael Lotz } 42095eee1a3SMichael Lotz 4211b3bb46aSMichael Lotz status_t result = keyring->ReadFromMessage(keyrings); 4221b3bb46aSMichael Lotz if (result != B_OK) { 4231b3bb46aSMichael Lotz printf("failed to read keyring \"%s\" from data\n", keyringName); 4241b3bb46aSMichael Lotz delete keyring; 42595eee1a3SMichael Lotz continue; 42695eee1a3SMichael Lotz } 42795eee1a3SMichael Lotz 42895eee1a3SMichael Lotz if (strlen(keyringName) == 0) 42995eee1a3SMichael Lotz fDefaultKeyring = keyring; 43095eee1a3SMichael Lotz else 43195eee1a3SMichael Lotz fKeyrings.BinaryInsert(keyring, &Keyring::Compare); 43295eee1a3SMichael Lotz } 43395eee1a3SMichael Lotz 4340dfaf59dSMichael Lotz return B_OK; 4350dfaf59dSMichael Lotz } 4360dfaf59dSMichael Lotz 4370dfaf59dSMichael Lotz 4380dfaf59dSMichael Lotz status_t 4390dfaf59dSMichael Lotz KeyStoreServer::_WriteKeyStoreDatabase() 4400dfaf59dSMichael Lotz { 44195eee1a3SMichael Lotz BMessage keyrings; 44295eee1a3SMichael Lotz if (fDefaultKeyring != NULL) 4431b3bb46aSMichael Lotz fDefaultKeyring->WriteToMessage(keyrings); 4440dfaf59dSMichael Lotz 44595eee1a3SMichael Lotz for (int32 i = 0; i < fKeyrings.CountItems(); i++) { 44695eee1a3SMichael Lotz Keyring* keyring = fKeyrings.ItemAt(i); 44795eee1a3SMichael Lotz if (keyring == NULL) 4480dfaf59dSMichael Lotz continue; 44995eee1a3SMichael Lotz 4501b3bb46aSMichael Lotz status_t result = keyring->WriteToMessage(keyrings); 4511b3bb46aSMichael Lotz if (result != B_OK) 4521b3bb46aSMichael Lotz return result; 4530dfaf59dSMichael Lotz } 4540dfaf59dSMichael Lotz 455aef629f2SMichael Lotz fKeyStoreFile.SetSize(0); 456aef629f2SMichael Lotz fKeyStoreFile.Seek(0, SEEK_SET); 45795eee1a3SMichael Lotz return keyrings.Flatten(&fKeyStoreFile); 4580dfaf59dSMichael Lotz } 4590dfaf59dSMichael Lotz 4600dfaf59dSMichael Lotz 46197b3abf1SMichael Lotz uint32 46297b3abf1SMichael Lotz KeyStoreServer::_AccessFlagsFor(uint32 command) const 46397b3abf1SMichael Lotz { 46497b3abf1SMichael Lotz switch (command) { 46597b3abf1SMichael Lotz case KEY_STORE_GET_KEY: 46697b3abf1SMichael Lotz return kFlagGetKey; 46797b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_KEY: 46897b3abf1SMichael Lotz return kFlagEnumerateKeys; 46997b3abf1SMichael Lotz case KEY_STORE_ADD_KEY: 47097b3abf1SMichael Lotz return kFlagAddKey; 47197b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEY: 47297b3abf1SMichael Lotz return kFlagRemoveKey; 47397b3abf1SMichael Lotz case KEY_STORE_ADD_KEYRING: 47497b3abf1SMichael Lotz return kFlagAddKeyring; 47597b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEYRING: 47697b3abf1SMichael Lotz return kFlagRemoveKeyring; 47797b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_KEYRING: 47897b3abf1SMichael Lotz return kFlagEnumerateKeyrings; 47997b3abf1SMichael Lotz case KEY_STORE_SET_MASTER_KEY: 48097b3abf1SMichael Lotz return kFlagSetMasterKey; 48197b3abf1SMichael Lotz case KEY_STORE_REMOVE_MASTER_KEY: 48297b3abf1SMichael Lotz return kFlagRemoveMasterKey; 48397b3abf1SMichael Lotz case KEY_STORE_ADD_KEYRING_TO_MASTER: 48497b3abf1SMichael Lotz return kFlagAddKeyringsToMaster; 48597b3abf1SMichael Lotz case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: 48697b3abf1SMichael Lotz return kFlagRemoveKeyringsFromMaster; 48797b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_MASTER_KEYRING: 48897b3abf1SMichael Lotz return kFlagEnumerateMasterKeyrings; 48997b3abf1SMichael Lotz case KEY_STORE_IS_KEYRING_ACCESSIBLE: 49097b3abf1SMichael Lotz return kFlagQueryAccessibility; 49197b3abf1SMichael Lotz case KEY_STORE_REVOKE_ACCESS: 49297b3abf1SMichael Lotz return kFlagRevokeAccess; 49397b3abf1SMichael Lotz case KEY_STORE_GET_NEXT_APPLICATION: 49497b3abf1SMichael Lotz return kFlagEnumerateApplications; 49597b3abf1SMichael Lotz case KEY_STORE_REMOVE_APPLICATION: 49697b3abf1SMichael Lotz return kFlagRemoveApplications; 49797b3abf1SMichael Lotz } 49897b3abf1SMichael Lotz 49997b3abf1SMichael Lotz return 0; 50097b3abf1SMichael Lotz } 50197b3abf1SMichael Lotz 50297b3abf1SMichael Lotz 50376df966eSMichael Lotz status_t 50476df966eSMichael Lotz KeyStoreServer::_ResolveCallingApp(const BMessage& message, 50576df966eSMichael Lotz app_info& callingAppInfo) const 50676df966eSMichael Lotz { 50776df966eSMichael Lotz team_id callingTeam = message.ReturnAddress().Team(); 50876df966eSMichael Lotz status_t result = be_roster->GetRunningAppInfo(callingTeam, 50976df966eSMichael Lotz &callingAppInfo); 51076df966eSMichael Lotz if (result != B_OK) 51176df966eSMichael Lotz return result; 51276df966eSMichael Lotz 51376df966eSMichael Lotz // Do some sanity checks. 51476df966eSMichael Lotz if (callingAppInfo.team != callingTeam) 51576df966eSMichael Lotz return B_ERROR; 51676df966eSMichael Lotz 51776df966eSMichael Lotz return B_OK; 51876df966eSMichael Lotz } 51976df966eSMichael Lotz 52076df966eSMichael Lotz 521*cfa81315SMichael Lotz status_t 522*cfa81315SMichael Lotz KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo, 523*cfa81315SMichael Lotz uint32 accessFlags) 524*cfa81315SMichael Lotz { 525*cfa81315SMichael Lotz BMessage appMessage; 526*cfa81315SMichael Lotz BPath path(&appInfo.ref); 527*cfa81315SMichael Lotz status_t result = keyring.FindApplication(appInfo.signature, 528*cfa81315SMichael Lotz path.Path(), appMessage); 529*cfa81315SMichael Lotz if (result != B_OK && result != B_ENTRY_NOT_FOUND) 530*cfa81315SMichael Lotz return result; 531*cfa81315SMichael Lotz 532*cfa81315SMichael Lotz // TODO: Implement running image checksum mechanism. 533*cfa81315SMichael Lotz BString checksum = "dummy"; 534*cfa81315SMichael Lotz 535*cfa81315SMichael Lotz bool appIsNew = false; 536*cfa81315SMichael Lotz bool appWasUpdated = false; 537*cfa81315SMichael Lotz uint32 appFlags = 0; 538*cfa81315SMichael Lotz BString appSum = ""; 539*cfa81315SMichael Lotz if (result == B_OK) { 540*cfa81315SMichael Lotz if (appMessage.FindUInt32("flags", &appFlags) != B_OK 541*cfa81315SMichael Lotz || appMessage.FindString("checksum", &appSum) != B_OK) { 542*cfa81315SMichael Lotz appIsNew = true; 543*cfa81315SMichael Lotz appFlags = 0; 544*cfa81315SMichael Lotz } else if (appSum != checksum) { 545*cfa81315SMichael Lotz appWasUpdated = true; 546*cfa81315SMichael Lotz appFlags = 0; 547*cfa81315SMichael Lotz } 548*cfa81315SMichael Lotz } else 549*cfa81315SMichael Lotz appIsNew = true; 550*cfa81315SMichael Lotz 551*cfa81315SMichael Lotz if ((accessFlags & appFlags) == accessFlags) 552*cfa81315SMichael Lotz return B_OK; 553*cfa81315SMichael Lotz 554*cfa81315SMichael Lotz bool allowAlways = false; 555*cfa81315SMichael Lotz result = _RequestAppAccess(keyring.Name(), appInfo.signature, path.Path(), 556*cfa81315SMichael Lotz appIsNew, appWasUpdated, accessFlags, allowAlways); 557*cfa81315SMichael Lotz if (result != B_OK || !allowAlways) 558*cfa81315SMichael Lotz return result; 559*cfa81315SMichael Lotz 560*cfa81315SMichael Lotz appMessage.MakeEmpty(); 561*cfa81315SMichael Lotz appMessage.AddString("path", path.Path()); 562*cfa81315SMichael Lotz appMessage.AddUInt32("flags", accessFlags); 563*cfa81315SMichael Lotz appMessage.AddString("checksum", checksum); 564*cfa81315SMichael Lotz 565*cfa81315SMichael Lotz keyring.RemoveApplication(appInfo.signature, path.Path()); 566*cfa81315SMichael Lotz if (keyring.AddApplication(appInfo.signature, appMessage) == B_OK) 567*cfa81315SMichael Lotz _WriteKeyStoreDatabase(); 568*cfa81315SMichael Lotz 569*cfa81315SMichael Lotz return B_OK; 570*cfa81315SMichael Lotz } 571*cfa81315SMichael Lotz 572*cfa81315SMichael Lotz 573*cfa81315SMichael Lotz status_t 574*cfa81315SMichael Lotz KeyStoreServer::_RequestAppAccess(const BString& keyringName, 575*cfa81315SMichael Lotz const char* signature, const char* path, bool appIsNew, bool appWasUpdated, 576*cfa81315SMichael Lotz uint32 accessFlags, bool& allowAlways) 577*cfa81315SMichael Lotz { 578*cfa81315SMichael Lotz AppAccessRequestWindow* requestWindow 579*cfa81315SMichael Lotz = new(std::nothrow) AppAccessRequestWindow(keyringName, signature, path, 580*cfa81315SMichael Lotz appIsNew, appWasUpdated); 581*cfa81315SMichael Lotz if (requestWindow == NULL) 582*cfa81315SMichael Lotz return B_NO_MEMORY; 583*cfa81315SMichael Lotz 584*cfa81315SMichael Lotz return requestWindow->RequestAppAccess(allowAlways); 585*cfa81315SMichael Lotz } 586*cfa81315SMichael Lotz 587*cfa81315SMichael Lotz 58895eee1a3SMichael Lotz Keyring* 58995eee1a3SMichael Lotz KeyStoreServer::_FindKeyring(const BString& name) 59095eee1a3SMichael Lotz { 59195eee1a3SMichael Lotz if (name.IsEmpty()) 59295eee1a3SMichael Lotz return fDefaultKeyring; 5930dfaf59dSMichael Lotz 59495eee1a3SMichael Lotz return fKeyrings.BinarySearchByKey(name, &Keyring::Compare); 5950dfaf59dSMichael Lotz } 5960dfaf59dSMichael Lotz 5970dfaf59dSMichael Lotz 5980dfaf59dSMichael Lotz status_t 59995eee1a3SMichael Lotz KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage) 6000dfaf59dSMichael Lotz { 60195eee1a3SMichael Lotz if (_FindKeyring(name) != NULL) 6020dfaf59dSMichael Lotz return B_NAME_IN_USE; 6030dfaf59dSMichael Lotz 6041b3bb46aSMichael Lotz Keyring* keyring = new(std::nothrow) Keyring(name, &keyMessage); 60595eee1a3SMichael Lotz if (keyring == NULL) 60695eee1a3SMichael Lotz return B_NO_MEMORY; 60795eee1a3SMichael Lotz 60895eee1a3SMichael Lotz if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) { 60995eee1a3SMichael Lotz delete keyring; 61095eee1a3SMichael Lotz return B_ERROR; 61195eee1a3SMichael Lotz } 61295eee1a3SMichael Lotz 61395eee1a3SMichael Lotz return B_OK; 61495eee1a3SMichael Lotz } 61595eee1a3SMichael Lotz 61695eee1a3SMichael Lotz 61795eee1a3SMichael Lotz status_t 61895eee1a3SMichael Lotz KeyStoreServer::_RemoveKeyring(const BString& name) 61995eee1a3SMichael Lotz { 62095eee1a3SMichael Lotz Keyring* keyring = _FindKeyring(name); 62195eee1a3SMichael Lotz if (keyring == NULL) 62295eee1a3SMichael Lotz return B_ENTRY_NOT_FOUND; 62395eee1a3SMichael Lotz 62495eee1a3SMichael Lotz if (keyring == fDefaultKeyring) { 62595eee1a3SMichael Lotz // The default keyring can't be removed. 62695eee1a3SMichael Lotz return B_NOT_ALLOWED; 62795eee1a3SMichael Lotz } 62895eee1a3SMichael Lotz 62995eee1a3SMichael Lotz return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR; 6308d9bc9e0SMichael Lotz } 6318d9bc9e0SMichael Lotz 6328d9bc9e0SMichael Lotz 633ac9b28f0SMichael Lotz status_t 634ac9b28f0SMichael Lotz KeyStoreServer::_AccessKeyring(Keyring& keyring) 635ac9b28f0SMichael Lotz { 636ac9b28f0SMichael Lotz // If we are accessing a keyring that has been added to master access we 637ac9b28f0SMichael Lotz // get the key from the default keyring and unlock with that. 638ac9b28f0SMichael Lotz BMessage keyMessage; 639ac9b28f0SMichael Lotz if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) { 640f16fef70SMichael Lotz if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), 641f16fef70SMichael Lotz false, &keyMessage) == B_OK) { 642ac9b28f0SMichael Lotz // We found a key for this keyring, try to access with it. 643ac9b28f0SMichael Lotz if (keyring.Access(keyMessage) == B_OK) 644ac9b28f0SMichael Lotz return B_OK; 645ac9b28f0SMichael Lotz } 646ac9b28f0SMichael Lotz } 647ac9b28f0SMichael Lotz 648ac9b28f0SMichael Lotz // No key, we need to request one from the user. 64990013c82SMichael Lotz status_t result = _RequestKey(keyring.Name(), keyMessage); 650ac9b28f0SMichael Lotz if (result != B_OK) 651ac9b28f0SMichael Lotz return result; 652ac9b28f0SMichael Lotz 653ac9b28f0SMichael Lotz return keyring.Access(keyMessage); 654ac9b28f0SMichael Lotz } 655ac9b28f0SMichael Lotz 656ac9b28f0SMichael Lotz 657ac9b28f0SMichael Lotz status_t 65890013c82SMichael Lotz KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage) 659ac9b28f0SMichael Lotz { 660ac9b28f0SMichael Lotz KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow(); 661ac9b28f0SMichael Lotz if (requestWindow == NULL) 662ac9b28f0SMichael Lotz return B_NO_MEMORY; 663ac9b28f0SMichael Lotz 66490013c82SMichael Lotz return requestWindow->RequestKey(keyringName, keyMessage); 665ac9b28f0SMichael Lotz } 666ac9b28f0SMichael Lotz 667ac9b28f0SMichael Lotz 6688d9bc9e0SMichael Lotz int 6698d9bc9e0SMichael Lotz main(int argc, char* argv[]) 6708d9bc9e0SMichael Lotz { 6718d9bc9e0SMichael Lotz KeyStoreServer* app = new(std::nothrow) KeyStoreServer(); 6728d9bc9e0SMichael Lotz if (app == NULL) 6738d9bc9e0SMichael Lotz return 1; 6748d9bc9e0SMichael Lotz 6758d9bc9e0SMichael Lotz app->Run(); 6768d9bc9e0SMichael Lotz delete app; 6778d9bc9e0SMichael Lotz return 0; 6788d9bc9e0SMichael Lotz } 679