xref: /haiku/src/servers/keystore/KeyStoreServer.cpp (revision 76df966ee6a656a9b51896653b3c411a53688fe4)
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 
9ac9b28f0SMichael Lotz #include "KeyRequestWindow.h"
1095eee1a3SMichael Lotz #include "Keyring.h"
118d9bc9e0SMichael Lotz 
128d9bc9e0SMichael Lotz #include <KeyStoreDefs.h>
138d9bc9e0SMichael Lotz 
140dfaf59dSMichael Lotz #include <Directory.h>
150dfaf59dSMichael Lotz #include <Entry.h>
160dfaf59dSMichael Lotz #include <FindDirectory.h>
170dfaf59dSMichael Lotz #include <Path.h>
18*76df966eSMichael Lotz #include <Roster.h>
190dfaf59dSMichael Lotz #include <String.h>
200dfaf59dSMichael Lotz 
218d9bc9e0SMichael Lotz #include <new>
228d9bc9e0SMichael Lotz 
238d9bc9e0SMichael Lotz #include <stdio.h>
248d9bc9e0SMichael Lotz 
258d9bc9e0SMichael Lotz 
268d9bc9e0SMichael Lotz using namespace BPrivate;
278d9bc9e0SMichael Lotz 
288d9bc9e0SMichael Lotz 
29f16fef70SMichael Lotz static const char* kKeyringKeysIdentifier = "Keyrings";
30f16fef70SMichael Lotz 
3197b3abf1SMichael Lotz static const uint32 kFlagGetKey						= 0x0001;
3297b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeys				= 0x0002;
3397b3abf1SMichael Lotz static const uint32 kFlagAddKey						= 0x0004;
3497b3abf1SMichael Lotz static const uint32 kFlagRemoveKey					= 0x0008;
3597b3abf1SMichael Lotz static const uint32 kFlagAddKeyring					= 0x0010;
3697b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyring				= 0x0020;
3797b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeyrings			= 0x0040;
3897b3abf1SMichael Lotz static const uint32 kFlagSetMasterKey				= 0x0080;
3997b3abf1SMichael Lotz static const uint32 kFlagRemoveMasterKey			= 0x0100;
4097b3abf1SMichael Lotz static const uint32 kFlagAddKeyringsToMaster		= 0x0200;
4197b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyringsFromMaster	= 0x0400;
4297b3abf1SMichael Lotz static const uint32 kFlagEnumerateMasterKeyrings	= 0x0800;
4397b3abf1SMichael Lotz static const uint32 kFlagQueryAccessibility			= 0x1000;
4497b3abf1SMichael Lotz static const uint32 kFlagRevokeAccess				= 0x2000;
4597b3abf1SMichael Lotz static const uint32 kFlagEnumerateApplications		= 0x4000;
4697b3abf1SMichael Lotz static const uint32 kFlagRemoveApplications			= 0x8000;
4797b3abf1SMichael Lotz 
4897b3abf1SMichael Lotz static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys
4997b3abf1SMichael Lotz 	| kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring
5097b3abf1SMichael Lotz 	| kFlagEnumerateKeyrings | kFlagSetMasterKey | kFlagRemoveMasterKey
5197b3abf1SMichael Lotz 	| kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster
5297b3abf1SMichael Lotz 	| kFlagEnumerateMasterKeyrings | kFlagQueryAccessibility
5397b3abf1SMichael Lotz 	| kFlagQueryAccessibility | kFlagRevokeAccess | kFlagEnumerateApplications
5497b3abf1SMichael Lotz 	| 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;
10095eee1a3SMichael Lotz 
10195eee1a3SMichael Lotz 	// Resolve the keyring for the relevant messages.
10295eee1a3SMichael Lotz 	Keyring* keyring = NULL;
10395eee1a3SMichael Lotz 	switch (message->what) {
10495eee1a3SMichael Lotz 		case KEY_STORE_GET_KEY:
10595eee1a3SMichael Lotz 		case KEY_STORE_GET_NEXT_KEY:
10695eee1a3SMichael Lotz 		case KEY_STORE_ADD_KEY:
10795eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEY:
10895eee1a3SMichael Lotz 		case KEY_STORE_IS_KEYRING_ACCESSIBLE:
10995eee1a3SMichael Lotz 		case KEY_STORE_REVOKE_ACCESS:
110f16fef70SMichael Lotz 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
111f16fef70SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
11295eee1a3SMichael Lotz 		{
11395eee1a3SMichael Lotz 			BString keyringName;
11495eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyringName) != B_OK)
11595eee1a3SMichael Lotz 				keyringName = "";
11695eee1a3SMichael Lotz 
11795eee1a3SMichael Lotz 			keyring = _FindKeyring(keyringName);
11895eee1a3SMichael Lotz 			if (keyring == NULL) {
11995eee1a3SMichael Lotz 				result = B_BAD_VALUE;
12095eee1a3SMichael Lotz 				message->what = 0;
12195eee1a3SMichael Lotz 					// So that we don't do anything in the second switch.
12295eee1a3SMichael Lotz 				break;
12395eee1a3SMichael Lotz 			}
12495eee1a3SMichael Lotz 
125ac9b28f0SMichael Lotz 			switch (message->what) {
126ac9b28f0SMichael Lotz 				case KEY_STORE_GET_KEY:
127ac9b28f0SMichael Lotz 				case KEY_STORE_GET_NEXT_KEY:
128ac9b28f0SMichael Lotz 				case KEY_STORE_ADD_KEY:
129ac9b28f0SMichael Lotz 				case KEY_STORE_REMOVE_KEY:
130f16fef70SMichael Lotz 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
131ac9b28f0SMichael Lotz 				{
132ac9b28f0SMichael Lotz 					// These need keyring access to do anything.
133ac9b28f0SMichael Lotz 					while (!keyring->IsAccessible()) {
134ac9b28f0SMichael Lotz 						status_t accessResult = _AccessKeyring(*keyring);
135ac9b28f0SMichael Lotz 						if (accessResult != B_OK) {
136ac9b28f0SMichael Lotz 							result = accessResult;
137ac9b28f0SMichael Lotz 							message->what = 0;
138ac9b28f0SMichael Lotz 							break;
139ac9b28f0SMichael Lotz 						}
140ac9b28f0SMichael Lotz 					}
141ac9b28f0SMichael Lotz 				}
142ac9b28f0SMichael Lotz 			}
143ac9b28f0SMichael Lotz 
14495eee1a3SMichael Lotz 			break;
14595eee1a3SMichael Lotz 		}
14695eee1a3SMichael Lotz 	}
1470dfaf59dSMichael Lotz 
1488d9bc9e0SMichael Lotz 	switch (message->what) {
1498d9bc9e0SMichael Lotz 		case KEY_STORE_GET_KEY:
1508d9bc9e0SMichael Lotz 		{
15195eee1a3SMichael Lotz 			BString identifier;
15295eee1a3SMichael Lotz 			if (message->FindString("identifier", &identifier) != B_OK) {
15395eee1a3SMichael Lotz 				result = B_BAD_VALUE;
15495eee1a3SMichael Lotz 				break;
15595eee1a3SMichael Lotz 			}
15695eee1a3SMichael Lotz 
15795eee1a3SMichael Lotz 			bool secondaryIdentifierOptional;
15895eee1a3SMichael Lotz 			if (message->FindBool("secondaryIdentifierOptional",
15995eee1a3SMichael Lotz 					&secondaryIdentifierOptional) != B_OK) {
16095eee1a3SMichael Lotz 				secondaryIdentifierOptional = false;
16195eee1a3SMichael Lotz 			}
16295eee1a3SMichael Lotz 
16395eee1a3SMichael Lotz 			BString secondaryIdentifier;
16495eee1a3SMichael Lotz 			if (message->FindString("secondaryIdentifier",
16595eee1a3SMichael Lotz 					&secondaryIdentifier) != B_OK) {
16695eee1a3SMichael Lotz 				secondaryIdentifier = "";
16795eee1a3SMichael Lotz 				secondaryIdentifierOptional = true;
16895eee1a3SMichael Lotz 			}
16995eee1a3SMichael Lotz 
17095eee1a3SMichael Lotz 			BMessage keyMessage;
17195eee1a3SMichael Lotz 			result = keyring->FindKey(identifier, secondaryIdentifier,
17295eee1a3SMichael Lotz 				secondaryIdentifierOptional, &keyMessage);
17395eee1a3SMichael Lotz 			if (result == B_OK)
17495eee1a3SMichael Lotz 				reply.AddMessage("key", &keyMessage);
175f16fef70SMichael Lotz 
1768d9bc9e0SMichael Lotz 			break;
1778d9bc9e0SMichael Lotz 		}
1788d9bc9e0SMichael Lotz 
1798d9bc9e0SMichael Lotz 		case KEY_STORE_GET_NEXT_KEY:
1808d9bc9e0SMichael Lotz 		{
1810dfaf59dSMichael Lotz 			BKeyType type;
1820dfaf59dSMichael Lotz 			BKeyPurpose purpose;
1830dfaf59dSMichael Lotz 			uint32 cookie;
1840dfaf59dSMichael Lotz 			if (message->FindUInt32("type", (uint32*)&type) != B_OK
1850dfaf59dSMichael Lotz 				|| message->FindUInt32("purpose", (uint32*)&purpose) != B_OK
1860dfaf59dSMichael Lotz 				|| message->FindUInt32("cookie", &cookie) != B_OK) {
1870dfaf59dSMichael Lotz 				result = B_BAD_VALUE;
1880dfaf59dSMichael Lotz 				break;
1890dfaf59dSMichael Lotz 			}
1900dfaf59dSMichael Lotz 
1910dfaf59dSMichael Lotz 			BMessage keyMessage;
19295eee1a3SMichael Lotz 			result = keyring->FindKey(type, purpose, cookie, keyMessage);
1930dfaf59dSMichael Lotz 			if (result == B_OK) {
1940dfaf59dSMichael Lotz 				cookie++;
1950dfaf59dSMichael Lotz 				reply.AddUInt32("cookie", cookie);
1960dfaf59dSMichael Lotz 				reply.AddMessage("key", &keyMessage);
1970dfaf59dSMichael Lotz 			}
1980dfaf59dSMichael Lotz 
1990dfaf59dSMichael Lotz 			break;
2000dfaf59dSMichael Lotz 		}
2010dfaf59dSMichael Lotz 
2020dfaf59dSMichael Lotz 		case KEY_STORE_ADD_KEY:
2030dfaf59dSMichael Lotz 		{
2040dfaf59dSMichael Lotz 			BMessage keyMessage;
2050dfaf59dSMichael Lotz 			BString identifier;
2060dfaf59dSMichael Lotz 			if (message->FindMessage("key", &keyMessage) != B_OK
2070dfaf59dSMichael Lotz 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
2080dfaf59dSMichael Lotz 				result = B_BAD_VALUE;
2090dfaf59dSMichael Lotz 				break;
2100dfaf59dSMichael Lotz 			}
2110dfaf59dSMichael Lotz 
2120dfaf59dSMichael Lotz 			BString secondaryIdentifier;
2130dfaf59dSMichael Lotz 			if (keyMessage.FindString("secondaryIdentifier",
2140dfaf59dSMichael Lotz 					&secondaryIdentifier) != B_OK) {
2150dfaf59dSMichael Lotz 				secondaryIdentifier = "";
2160dfaf59dSMichael Lotz 			}
2170dfaf59dSMichael Lotz 
21895eee1a3SMichael Lotz 			result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage);
21995eee1a3SMichael Lotz 			if (result == B_OK)
22095eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
22195eee1a3SMichael Lotz 
22295eee1a3SMichael Lotz 			break;
22395eee1a3SMichael Lotz 		}
22495eee1a3SMichael Lotz 
22595eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEY:
22695eee1a3SMichael Lotz 		{
22795eee1a3SMichael Lotz 			BMessage keyMessage;
22895eee1a3SMichael Lotz 			BString identifier;
22995eee1a3SMichael Lotz 			if (message->FindMessage("key", &keyMessage) != B_OK
23095eee1a3SMichael Lotz 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
23195eee1a3SMichael Lotz 				result = B_BAD_VALUE;
23295eee1a3SMichael Lotz 				break;
23395eee1a3SMichael Lotz 			}
23495eee1a3SMichael Lotz 
23595eee1a3SMichael Lotz 			result = keyring->RemoveKey(identifier, keyMessage);
23695eee1a3SMichael Lotz 			if (result == B_OK)
23795eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
23895eee1a3SMichael Lotz 
23995eee1a3SMichael Lotz 			break;
24095eee1a3SMichael Lotz 		}
24195eee1a3SMichael Lotz 
24295eee1a3SMichael Lotz 		case KEY_STORE_ADD_KEYRING:
24395eee1a3SMichael Lotz 		{
24495eee1a3SMichael Lotz 			BMessage keyMessage;
24595eee1a3SMichael Lotz 			BString keyring;
24695eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyring) != B_OK
24795eee1a3SMichael Lotz 				|| message->FindMessage("key", &keyMessage) != B_OK) {
24895eee1a3SMichael Lotz 				result = B_BAD_VALUE;
24995eee1a3SMichael Lotz 				break;
25095eee1a3SMichael Lotz 			}
25195eee1a3SMichael Lotz 
25295eee1a3SMichael Lotz 			result = _AddKeyring(keyring, keyMessage);
25395eee1a3SMichael Lotz 			if (result == B_OK)
25495eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
25595eee1a3SMichael Lotz 
25695eee1a3SMichael Lotz 			break;
25795eee1a3SMichael Lotz 		}
25895eee1a3SMichael Lotz 
25995eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING:
26095eee1a3SMichael Lotz 		{
26195eee1a3SMichael Lotz 			BString keyringName;
26295eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyringName) != B_OK)
26395eee1a3SMichael Lotz 				keyringName = "";
26495eee1a3SMichael Lotz 
26595eee1a3SMichael Lotz 			result = _RemoveKeyring(keyringName);
26695eee1a3SMichael Lotz 			if (result == B_OK)
26795eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
26895eee1a3SMichael Lotz 
26995eee1a3SMichael Lotz 			break;
27095eee1a3SMichael Lotz 		}
27195eee1a3SMichael Lotz 
27295eee1a3SMichael Lotz 		case KEY_STORE_GET_NEXT_KEYRING:
27395eee1a3SMichael Lotz 		{
27495eee1a3SMichael Lotz 			uint32 cookie;
27595eee1a3SMichael Lotz 			if (message->FindUInt32("cookie", &cookie) != B_OK) {
27695eee1a3SMichael Lotz 				result = B_BAD_VALUE;
27795eee1a3SMichael Lotz 				break;
27895eee1a3SMichael Lotz 			}
27995eee1a3SMichael Lotz 
28095eee1a3SMichael Lotz 			if (cookie == 0)
28195eee1a3SMichael Lotz 				keyring = fDefaultKeyring;
28295eee1a3SMichael Lotz 			else
28395eee1a3SMichael Lotz 				keyring = fKeyrings.ItemAt(cookie - 1);
28495eee1a3SMichael Lotz 
28595eee1a3SMichael Lotz 			if (keyring == NULL) {
28695eee1a3SMichael Lotz 				result = B_ENTRY_NOT_FOUND;
28795eee1a3SMichael Lotz 				break;
28895eee1a3SMichael Lotz 			}
28995eee1a3SMichael Lotz 
29095eee1a3SMichael Lotz 			cookie++;
29195eee1a3SMichael Lotz 			reply.AddUInt32("cookie", cookie);
29295eee1a3SMichael Lotz 			reply.AddString("keyring", keyring->Name());
29395eee1a3SMichael Lotz 			result = B_OK;
29495eee1a3SMichael Lotz 			break;
29595eee1a3SMichael Lotz 		}
29695eee1a3SMichael Lotz 
29795eee1a3SMichael Lotz 		case KEY_STORE_IS_KEYRING_ACCESSIBLE:
29895eee1a3SMichael Lotz 		{
29995eee1a3SMichael Lotz 			reply.AddBool("accessible", keyring->IsAccessible());
30095eee1a3SMichael Lotz 			result = B_OK;
301f16fef70SMichael Lotz 			break;
30295eee1a3SMichael Lotz 		}
30395eee1a3SMichael Lotz 
304ac9b28f0SMichael Lotz 		case KEY_STORE_REVOKE_ACCESS:
305ac9b28f0SMichael Lotz 		{
306ac9b28f0SMichael Lotz 			keyring->RevokeAccess();
307ac9b28f0SMichael Lotz 			result = B_OK;
308f16fef70SMichael Lotz 			break;
309f16fef70SMichael Lotz 		}
310f16fef70SMichael Lotz 
311f16fef70SMichael Lotz 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
312f16fef70SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
313f16fef70SMichael Lotz 		{
314f16fef70SMichael Lotz 			// We also need access to the default keyring.
315f16fef70SMichael Lotz 			while (!fDefaultKeyring->IsAccessible()) {
316f16fef70SMichael Lotz 				status_t accessResult = _AccessKeyring(*fDefaultKeyring);
317f16fef70SMichael Lotz 				if (accessResult != B_OK) {
318f16fef70SMichael Lotz 					result = accessResult;
319f16fef70SMichael Lotz 					message->what = 0;
320f16fef70SMichael Lotz 					break;
321f16fef70SMichael Lotz 				}
322f16fef70SMichael Lotz 			}
323f16fef70SMichael Lotz 
324f16fef70SMichael Lotz 			if (message->what == 0)
325f16fef70SMichael Lotz 				break;
326f16fef70SMichael Lotz 
327f16fef70SMichael Lotz 			BString secondaryIdentifier = keyring->Name();
328f16fef70SMichael Lotz 			BMessage keyMessage = keyring->KeyMessage();
329f16fef70SMichael Lotz 			keyMessage.RemoveName("identifier");
330f16fef70SMichael Lotz 			keyMessage.AddString("identifier", kKeyringKeysIdentifier);
331f16fef70SMichael Lotz 			keyMessage.RemoveName("secondaryIdentifier");
332f16fef70SMichael Lotz 			keyMessage.AddString("secondaryIdentifier", secondaryIdentifier);
333f16fef70SMichael Lotz 
334f16fef70SMichael Lotz 			switch (message->what) {
335f16fef70SMichael Lotz 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
336f16fef70SMichael Lotz 					result = fDefaultKeyring->AddKey(kKeyringKeysIdentifier,
337f16fef70SMichael Lotz 						secondaryIdentifier, keyMessage);
338f16fef70SMichael Lotz 					break;
339f16fef70SMichael Lotz 
340f16fef70SMichael Lotz 				case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
341f16fef70SMichael Lotz 					result = fDefaultKeyring->RemoveKey(kKeyringKeysIdentifier,
342f16fef70SMichael Lotz 						keyMessage);
343f16fef70SMichael Lotz 					break;
344f16fef70SMichael Lotz 			}
345f16fef70SMichael Lotz 
346f16fef70SMichael Lotz 			if (result == B_OK)
347f16fef70SMichael Lotz 				_WriteKeyStoreDatabase();
348f16fef70SMichael Lotz 
349f16fef70SMichael Lotz 			break;
350ac9b28f0SMichael Lotz 		}
351ac9b28f0SMichael Lotz 
35295eee1a3SMichael Lotz 		case 0:
35395eee1a3SMichael Lotz 		{
35495eee1a3SMichael Lotz 			// Just the error case from above.
3558d9bc9e0SMichael Lotz 			break;
3568d9bc9e0SMichael Lotz 		}
3578d9bc9e0SMichael Lotz 
3588d9bc9e0SMichael Lotz 		default:
3598d9bc9e0SMichael Lotz 		{
3608d9bc9e0SMichael Lotz 			printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n",
3618d9bc9e0SMichael Lotz 				message->what, (const char*)&message->what);
3628d9bc9e0SMichael Lotz 			break;
3638d9bc9e0SMichael Lotz 		}
3648d9bc9e0SMichael Lotz 	}
3658d9bc9e0SMichael Lotz 
3660dfaf59dSMichael Lotz 	if (message->IsSourceWaiting()) {
3670dfaf59dSMichael Lotz 		if (result == B_OK)
3680dfaf59dSMichael Lotz 			reply.what = KEY_STORE_SUCCESS;
3690dfaf59dSMichael Lotz 		else {
3700dfaf59dSMichael Lotz 			reply.what = KEY_STORE_RESULT;
3710dfaf59dSMichael Lotz 			reply.AddInt32("result", result);
3720dfaf59dSMichael Lotz 		}
3730dfaf59dSMichael Lotz 
3740dfaf59dSMichael Lotz 		message->SendReply(&reply);
3750dfaf59dSMichael Lotz 	}
3768d9bc9e0SMichael Lotz }
3778d9bc9e0SMichael Lotz 
3788d9bc9e0SMichael Lotz 
3798d9bc9e0SMichael Lotz status_t
3800dfaf59dSMichael Lotz KeyStoreServer::_ReadKeyStoreDatabase()
3818d9bc9e0SMichael Lotz {
38295eee1a3SMichael Lotz 	BMessage keyrings;
38395eee1a3SMichael Lotz 	status_t result = keyrings.Unflatten(&fKeyStoreFile);
3840dfaf59dSMichael Lotz 	if (result != B_OK) {
3850dfaf59dSMichael Lotz 		printf("failed to read keystore database\n");
3860dfaf59dSMichael Lotz 		_WriteKeyStoreDatabase();
3870dfaf59dSMichael Lotz 		return result;
3880dfaf59dSMichael Lotz 	}
3890dfaf59dSMichael Lotz 
39095eee1a3SMichael Lotz 	int32 index = 0;
39195eee1a3SMichael Lotz 	char* keyringName = NULL;
3921b3bb46aSMichael Lotz 	while (keyrings.GetInfo(B_RAW_TYPE, index++, &keyringName, NULL) == B_OK) {
3931b3bb46aSMichael Lotz 		Keyring* keyring = new(std::nothrow) Keyring(keyringName);
3941b3bb46aSMichael Lotz 		if (keyring == NULL) {
3951b3bb46aSMichael Lotz 			printf("no memory for allocating keyring \"%s\"\n", keyringName);
39695eee1a3SMichael Lotz 			continue;
39795eee1a3SMichael Lotz 		}
39895eee1a3SMichael Lotz 
3991b3bb46aSMichael Lotz 		status_t result = keyring->ReadFromMessage(keyrings);
4001b3bb46aSMichael Lotz 		if (result != B_OK) {
4011b3bb46aSMichael Lotz 			printf("failed to read keyring \"%s\" from data\n", keyringName);
4021b3bb46aSMichael Lotz 			delete keyring;
40395eee1a3SMichael Lotz 			continue;
40495eee1a3SMichael Lotz 		}
40595eee1a3SMichael Lotz 
40695eee1a3SMichael Lotz 		if (strlen(keyringName) == 0)
40795eee1a3SMichael Lotz 			fDefaultKeyring = keyring;
40895eee1a3SMichael Lotz 		else
40995eee1a3SMichael Lotz 			fKeyrings.BinaryInsert(keyring, &Keyring::Compare);
41095eee1a3SMichael Lotz 	}
41195eee1a3SMichael Lotz 
4120dfaf59dSMichael Lotz 	return B_OK;
4130dfaf59dSMichael Lotz }
4140dfaf59dSMichael Lotz 
4150dfaf59dSMichael Lotz 
4160dfaf59dSMichael Lotz status_t
4170dfaf59dSMichael Lotz KeyStoreServer::_WriteKeyStoreDatabase()
4180dfaf59dSMichael Lotz {
41995eee1a3SMichael Lotz 	BMessage keyrings;
42095eee1a3SMichael Lotz 	if (fDefaultKeyring != NULL)
4211b3bb46aSMichael Lotz 		fDefaultKeyring->WriteToMessage(keyrings);
4220dfaf59dSMichael Lotz 
42395eee1a3SMichael Lotz 	for (int32 i = 0; i < fKeyrings.CountItems(); i++) {
42495eee1a3SMichael Lotz 		Keyring* keyring = fKeyrings.ItemAt(i);
42595eee1a3SMichael Lotz 		if (keyring == NULL)
4260dfaf59dSMichael Lotz 			continue;
42795eee1a3SMichael Lotz 
4281b3bb46aSMichael Lotz 		status_t result = keyring->WriteToMessage(keyrings);
4291b3bb46aSMichael Lotz 		if (result != B_OK)
4301b3bb46aSMichael Lotz 			return result;
4310dfaf59dSMichael Lotz 	}
4320dfaf59dSMichael Lotz 
433aef629f2SMichael Lotz 	fKeyStoreFile.SetSize(0);
434aef629f2SMichael Lotz 	fKeyStoreFile.Seek(0, SEEK_SET);
43595eee1a3SMichael Lotz 	return keyrings.Flatten(&fKeyStoreFile);
4360dfaf59dSMichael Lotz }
4370dfaf59dSMichael Lotz 
4380dfaf59dSMichael Lotz 
43997b3abf1SMichael Lotz uint32
44097b3abf1SMichael Lotz KeyStoreServer::_AccessFlagsFor(uint32 command) const
44197b3abf1SMichael Lotz {
44297b3abf1SMichael Lotz 	switch (command) {
44397b3abf1SMichael Lotz 		case KEY_STORE_GET_KEY:
44497b3abf1SMichael Lotz 			return kFlagGetKey;
44597b3abf1SMichael Lotz 		case KEY_STORE_GET_NEXT_KEY:
44697b3abf1SMichael Lotz 			return kFlagEnumerateKeys;
44797b3abf1SMichael Lotz 		case KEY_STORE_ADD_KEY:
44897b3abf1SMichael Lotz 			return kFlagAddKey;
44997b3abf1SMichael Lotz 		case KEY_STORE_REMOVE_KEY:
45097b3abf1SMichael Lotz 			return kFlagRemoveKey;
45197b3abf1SMichael Lotz 		case KEY_STORE_ADD_KEYRING:
45297b3abf1SMichael Lotz 			return kFlagAddKeyring;
45397b3abf1SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING:
45497b3abf1SMichael Lotz 			return kFlagRemoveKeyring;
45597b3abf1SMichael Lotz 		case KEY_STORE_GET_NEXT_KEYRING:
45697b3abf1SMichael Lotz 			return kFlagEnumerateKeyrings;
45797b3abf1SMichael Lotz 		case KEY_STORE_SET_MASTER_KEY:
45897b3abf1SMichael Lotz 			return kFlagSetMasterKey;
45997b3abf1SMichael Lotz 		case KEY_STORE_REMOVE_MASTER_KEY:
46097b3abf1SMichael Lotz 			return kFlagRemoveMasterKey;
46197b3abf1SMichael Lotz 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
46297b3abf1SMichael Lotz 			return kFlagAddKeyringsToMaster;
46397b3abf1SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
46497b3abf1SMichael Lotz 			return kFlagRemoveKeyringsFromMaster;
46597b3abf1SMichael Lotz 		case KEY_STORE_GET_NEXT_MASTER_KEYRING:
46697b3abf1SMichael Lotz 			return kFlagEnumerateMasterKeyrings;
46797b3abf1SMichael Lotz 		case KEY_STORE_IS_KEYRING_ACCESSIBLE:
46897b3abf1SMichael Lotz 			return kFlagQueryAccessibility;
46997b3abf1SMichael Lotz 		case KEY_STORE_REVOKE_ACCESS:
47097b3abf1SMichael Lotz 			return kFlagRevokeAccess;
47197b3abf1SMichael Lotz 		case KEY_STORE_GET_NEXT_APPLICATION:
47297b3abf1SMichael Lotz 			return kFlagEnumerateApplications;
47397b3abf1SMichael Lotz 		case KEY_STORE_REMOVE_APPLICATION:
47497b3abf1SMichael Lotz 			return kFlagRemoveApplications;
47597b3abf1SMichael Lotz 	}
47697b3abf1SMichael Lotz 
47797b3abf1SMichael Lotz 	return 0;
47897b3abf1SMichael Lotz }
47997b3abf1SMichael Lotz 
48097b3abf1SMichael Lotz 
481*76df966eSMichael Lotz status_t
482*76df966eSMichael Lotz KeyStoreServer::_ResolveCallingApp(const BMessage& message,
483*76df966eSMichael Lotz 	app_info& callingAppInfo) const
484*76df966eSMichael Lotz {
485*76df966eSMichael Lotz 	team_id callingTeam = message.ReturnAddress().Team();
486*76df966eSMichael Lotz 	status_t result = be_roster->GetRunningAppInfo(callingTeam,
487*76df966eSMichael Lotz 		&callingAppInfo);
488*76df966eSMichael Lotz 	if (result != B_OK)
489*76df966eSMichael Lotz 		return result;
490*76df966eSMichael Lotz 
491*76df966eSMichael Lotz 	// Do some sanity checks.
492*76df966eSMichael Lotz 	if (callingAppInfo.team != callingTeam)
493*76df966eSMichael Lotz 		return B_ERROR;
494*76df966eSMichael Lotz 
495*76df966eSMichael Lotz 	return B_OK;
496*76df966eSMichael Lotz }
497*76df966eSMichael Lotz 
498*76df966eSMichael Lotz 
49995eee1a3SMichael Lotz Keyring*
50095eee1a3SMichael Lotz KeyStoreServer::_FindKeyring(const BString& name)
50195eee1a3SMichael Lotz {
50295eee1a3SMichael Lotz 	if (name.IsEmpty())
50395eee1a3SMichael Lotz 		return fDefaultKeyring;
5040dfaf59dSMichael Lotz 
50595eee1a3SMichael Lotz 	return fKeyrings.BinarySearchByKey(name, &Keyring::Compare);
5060dfaf59dSMichael Lotz }
5070dfaf59dSMichael Lotz 
5080dfaf59dSMichael Lotz 
5090dfaf59dSMichael Lotz status_t
51095eee1a3SMichael Lotz KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage)
5110dfaf59dSMichael Lotz {
51295eee1a3SMichael Lotz 	if (_FindKeyring(name) != NULL)
5130dfaf59dSMichael Lotz 		return B_NAME_IN_USE;
5140dfaf59dSMichael Lotz 
5151b3bb46aSMichael Lotz 	Keyring* keyring = new(std::nothrow) Keyring(name, &keyMessage);
51695eee1a3SMichael Lotz 	if (keyring == NULL)
51795eee1a3SMichael Lotz 		return B_NO_MEMORY;
51895eee1a3SMichael Lotz 
51995eee1a3SMichael Lotz 	if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) {
52095eee1a3SMichael Lotz 		delete keyring;
52195eee1a3SMichael Lotz 		return B_ERROR;
52295eee1a3SMichael Lotz 	}
52395eee1a3SMichael Lotz 
52495eee1a3SMichael Lotz 	return B_OK;
52595eee1a3SMichael Lotz }
52695eee1a3SMichael Lotz 
52795eee1a3SMichael Lotz 
52895eee1a3SMichael Lotz status_t
52995eee1a3SMichael Lotz KeyStoreServer::_RemoveKeyring(const BString& name)
53095eee1a3SMichael Lotz {
53195eee1a3SMichael Lotz 	Keyring* keyring = _FindKeyring(name);
53295eee1a3SMichael Lotz 	if (keyring == NULL)
53395eee1a3SMichael Lotz 		return B_ENTRY_NOT_FOUND;
53495eee1a3SMichael Lotz 
53595eee1a3SMichael Lotz 	if (keyring == fDefaultKeyring) {
53695eee1a3SMichael Lotz 		// The default keyring can't be removed.
53795eee1a3SMichael Lotz 		return B_NOT_ALLOWED;
53895eee1a3SMichael Lotz 	}
53995eee1a3SMichael Lotz 
54095eee1a3SMichael Lotz 	return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR;
5418d9bc9e0SMichael Lotz }
5428d9bc9e0SMichael Lotz 
5438d9bc9e0SMichael Lotz 
544ac9b28f0SMichael Lotz status_t
545ac9b28f0SMichael Lotz KeyStoreServer::_AccessKeyring(Keyring& keyring)
546ac9b28f0SMichael Lotz {
547ac9b28f0SMichael Lotz 	// If we are accessing a keyring that has been added to master access we
548ac9b28f0SMichael Lotz 	// get the key from the default keyring and unlock with that.
549ac9b28f0SMichael Lotz 	BMessage keyMessage;
550ac9b28f0SMichael Lotz 	if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) {
551f16fef70SMichael Lotz 		if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(),
552f16fef70SMichael Lotz 				false, &keyMessage) == B_OK) {
553ac9b28f0SMichael Lotz 			// We found a key for this keyring, try to access with it.
554ac9b28f0SMichael Lotz 			if (keyring.Access(keyMessage) == B_OK)
555ac9b28f0SMichael Lotz 				return B_OK;
556ac9b28f0SMichael Lotz 		}
557ac9b28f0SMichael Lotz 	}
558ac9b28f0SMichael Lotz 
559ac9b28f0SMichael Lotz 	// No key, we need to request one from the user.
56090013c82SMichael Lotz 	status_t result = _RequestKey(keyring.Name(), keyMessage);
561ac9b28f0SMichael Lotz 	if (result != B_OK)
562ac9b28f0SMichael Lotz 		return result;
563ac9b28f0SMichael Lotz 
564ac9b28f0SMichael Lotz 	return keyring.Access(keyMessage);
565ac9b28f0SMichael Lotz }
566ac9b28f0SMichael Lotz 
567ac9b28f0SMichael Lotz 
568ac9b28f0SMichael Lotz status_t
56990013c82SMichael Lotz KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage)
570ac9b28f0SMichael Lotz {
571ac9b28f0SMichael Lotz 	KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow();
572ac9b28f0SMichael Lotz 	if (requestWindow == NULL)
573ac9b28f0SMichael Lotz 		return B_NO_MEMORY;
574ac9b28f0SMichael Lotz 
57590013c82SMichael Lotz 	return requestWindow->RequestKey(keyringName, keyMessage);
576ac9b28f0SMichael Lotz }
577ac9b28f0SMichael Lotz 
578ac9b28f0SMichael Lotz 
5798d9bc9e0SMichael Lotz int
5808d9bc9e0SMichael Lotz main(int argc, char* argv[])
5818d9bc9e0SMichael Lotz {
5828d9bc9e0SMichael Lotz 	KeyStoreServer* app = new(std::nothrow) KeyStoreServer();
5838d9bc9e0SMichael Lotz 	if (app == NULL)
5848d9bc9e0SMichael Lotz 		return 1;
5858d9bc9e0SMichael Lotz 
5868d9bc9e0SMichael Lotz 	app->Run();
5878d9bc9e0SMichael Lotz 	delete app;
5888d9bc9e0SMichael Lotz 	return 0;
5898d9bc9e0SMichael Lotz }
590