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