xref: /haiku/src/servers/keystore/KeyStoreServer.cpp (revision c8ae843f3dcba6c16eda5d2b5db1f981ee69f448)
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