xref: /haiku/src/servers/keystore/KeyStoreServer.cpp (revision 1b3bb46aed33bd68bf5e4dba1625ad3211b31adc)
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>
180dfaf59dSMichael Lotz #include <String.h>
190dfaf59dSMichael Lotz 
208d9bc9e0SMichael Lotz #include <new>
218d9bc9e0SMichael Lotz 
228d9bc9e0SMichael Lotz #include <stdio.h>
238d9bc9e0SMichael Lotz 
248d9bc9e0SMichael Lotz 
258d9bc9e0SMichael Lotz using namespace BPrivate;
268d9bc9e0SMichael Lotz 
278d9bc9e0SMichael Lotz 
28f16fef70SMichael Lotz static const char* kKeyringKeysIdentifier = "Keyrings";
29f16fef70SMichael Lotz 
3097b3abf1SMichael Lotz static const uint32 kFlagGetKey						= 0x0001;
3197b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeys				= 0x0002;
3297b3abf1SMichael Lotz static const uint32 kFlagAddKey						= 0x0004;
3397b3abf1SMichael Lotz static const uint32 kFlagRemoveKey					= 0x0008;
3497b3abf1SMichael Lotz static const uint32 kFlagAddKeyring					= 0x0010;
3597b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyring				= 0x0020;
3697b3abf1SMichael Lotz static const uint32 kFlagEnumerateKeyrings			= 0x0040;
3797b3abf1SMichael Lotz static const uint32 kFlagSetMasterKey				= 0x0080;
3897b3abf1SMichael Lotz static const uint32 kFlagRemoveMasterKey			= 0x0100;
3997b3abf1SMichael Lotz static const uint32 kFlagAddKeyringsToMaster		= 0x0200;
4097b3abf1SMichael Lotz static const uint32 kFlagRemoveKeyringsFromMaster	= 0x0400;
4197b3abf1SMichael Lotz static const uint32 kFlagEnumerateMasterKeyrings	= 0x0800;
4297b3abf1SMichael Lotz static const uint32 kFlagQueryAccessibility			= 0x1000;
4397b3abf1SMichael Lotz static const uint32 kFlagRevokeAccess				= 0x2000;
4497b3abf1SMichael Lotz static const uint32 kFlagEnumerateApplications		= 0x4000;
4597b3abf1SMichael Lotz static const uint32 kFlagRemoveApplications			= 0x8000;
4697b3abf1SMichael Lotz 
4797b3abf1SMichael Lotz static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys
4897b3abf1SMichael Lotz 	| kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring
4997b3abf1SMichael Lotz 	| kFlagEnumerateKeyrings | kFlagSetMasterKey | kFlagRemoveMasterKey
5097b3abf1SMichael Lotz 	| kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster
5197b3abf1SMichael Lotz 	| kFlagEnumerateMasterKeyrings | kFlagQueryAccessibility
5297b3abf1SMichael Lotz 	| kFlagQueryAccessibility | kFlagRevokeAccess | kFlagEnumerateApplications
5397b3abf1SMichael Lotz 	| kFlagRemoveApplications;
5497b3abf1SMichael Lotz 
55f16fef70SMichael Lotz 
568d9bc9e0SMichael Lotz KeyStoreServer::KeyStoreServer()
578d9bc9e0SMichael Lotz 	:
5895eee1a3SMichael Lotz 	BApplication(kKeyStoreServerSignature),
5995eee1a3SMichael Lotz 	fDefaultKeyring(NULL),
6095eee1a3SMichael Lotz 	fKeyrings(20, true)
618d9bc9e0SMichael Lotz {
620dfaf59dSMichael Lotz 	BPath path;
630dfaf59dSMichael Lotz 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
640dfaf59dSMichael Lotz 		return;
650dfaf59dSMichael Lotz 
660dfaf59dSMichael Lotz 	BDirectory settingsDir(path.Path());
670dfaf59dSMichael Lotz 	path.Append("system");
680dfaf59dSMichael Lotz 	if (!settingsDir.Contains(path.Path()))
690dfaf59dSMichael Lotz 		settingsDir.CreateDirectory(path.Path(), NULL);
700dfaf59dSMichael Lotz 
710dfaf59dSMichael Lotz 	settingsDir.SetTo(path.Path());
720dfaf59dSMichael Lotz 	path.Append("keystore");
730dfaf59dSMichael Lotz 	if (!settingsDir.Contains(path.Path()))
740dfaf59dSMichael Lotz 		settingsDir.CreateDirectory(path.Path(), NULL);
750dfaf59dSMichael Lotz 
760dfaf59dSMichael Lotz 	settingsDir.SetTo(path.Path());
770dfaf59dSMichael Lotz 	path.Append("keystore_database");
780dfaf59dSMichael Lotz 
790dfaf59dSMichael Lotz 	fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE
800dfaf59dSMichael Lotz 		| (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE));
810dfaf59dSMichael Lotz 
820dfaf59dSMichael Lotz 	_ReadKeyStoreDatabase();
8395eee1a3SMichael Lotz 
8495eee1a3SMichael Lotz 	if (fDefaultKeyring == NULL)
85*1b3bb46aSMichael Lotz 		fDefaultKeyring = new(std::nothrow) Keyring("");
868d9bc9e0SMichael Lotz }
878d9bc9e0SMichael Lotz 
888d9bc9e0SMichael Lotz 
898d9bc9e0SMichael Lotz KeyStoreServer::~KeyStoreServer()
908d9bc9e0SMichael Lotz {
918d9bc9e0SMichael Lotz }
928d9bc9e0SMichael Lotz 
938d9bc9e0SMichael Lotz 
948d9bc9e0SMichael Lotz void
958d9bc9e0SMichael Lotz KeyStoreServer::MessageReceived(BMessage* message)
968d9bc9e0SMichael Lotz {
970dfaf59dSMichael Lotz 	BMessage reply;
9895eee1a3SMichael Lotz 	status_t result = B_UNSUPPORTED;
9995eee1a3SMichael Lotz 
10095eee1a3SMichael Lotz 	// Resolve the keyring for the relevant messages.
10195eee1a3SMichael Lotz 	Keyring* keyring = NULL;
10295eee1a3SMichael Lotz 	switch (message->what) {
10395eee1a3SMichael Lotz 		case KEY_STORE_GET_KEY:
10495eee1a3SMichael Lotz 		case KEY_STORE_GET_NEXT_KEY:
10595eee1a3SMichael Lotz 		case KEY_STORE_ADD_KEY:
10695eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEY:
10795eee1a3SMichael Lotz 		case KEY_STORE_IS_KEYRING_ACCESSIBLE:
10895eee1a3SMichael Lotz 		case KEY_STORE_REVOKE_ACCESS:
109f16fef70SMichael Lotz 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
110f16fef70SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
11195eee1a3SMichael Lotz 		{
11295eee1a3SMichael Lotz 			BString keyringName;
11395eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyringName) != B_OK)
11495eee1a3SMichael Lotz 				keyringName = "";
11595eee1a3SMichael Lotz 
11695eee1a3SMichael Lotz 			keyring = _FindKeyring(keyringName);
11795eee1a3SMichael Lotz 			if (keyring == NULL) {
11895eee1a3SMichael Lotz 				result = B_BAD_VALUE;
11995eee1a3SMichael Lotz 				message->what = 0;
12095eee1a3SMichael Lotz 					// So that we don't do anything in the second switch.
12195eee1a3SMichael Lotz 				break;
12295eee1a3SMichael Lotz 			}
12395eee1a3SMichael Lotz 
124ac9b28f0SMichael Lotz 			switch (message->what) {
125ac9b28f0SMichael Lotz 				case KEY_STORE_GET_KEY:
126ac9b28f0SMichael Lotz 				case KEY_STORE_GET_NEXT_KEY:
127ac9b28f0SMichael Lotz 				case KEY_STORE_ADD_KEY:
128ac9b28f0SMichael Lotz 				case KEY_STORE_REMOVE_KEY:
129f16fef70SMichael Lotz 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
130ac9b28f0SMichael Lotz 				{
131ac9b28f0SMichael Lotz 					// These need keyring access to do anything.
132ac9b28f0SMichael Lotz 					while (!keyring->IsAccessible()) {
133ac9b28f0SMichael Lotz 						status_t accessResult = _AccessKeyring(*keyring);
134ac9b28f0SMichael Lotz 						if (accessResult != B_OK) {
135ac9b28f0SMichael Lotz 							result = accessResult;
136ac9b28f0SMichael Lotz 							message->what = 0;
137ac9b28f0SMichael Lotz 							break;
138ac9b28f0SMichael Lotz 						}
139ac9b28f0SMichael Lotz 					}
140ac9b28f0SMichael Lotz 				}
141ac9b28f0SMichael Lotz 			}
142ac9b28f0SMichael Lotz 
14395eee1a3SMichael Lotz 			break;
14495eee1a3SMichael Lotz 		}
14595eee1a3SMichael Lotz 	}
1460dfaf59dSMichael Lotz 
1478d9bc9e0SMichael Lotz 	switch (message->what) {
1488d9bc9e0SMichael Lotz 		case KEY_STORE_GET_KEY:
1498d9bc9e0SMichael Lotz 		{
15095eee1a3SMichael Lotz 			BString identifier;
15195eee1a3SMichael Lotz 			if (message->FindString("identifier", &identifier) != B_OK) {
15295eee1a3SMichael Lotz 				result = B_BAD_VALUE;
15395eee1a3SMichael Lotz 				break;
15495eee1a3SMichael Lotz 			}
15595eee1a3SMichael Lotz 
15695eee1a3SMichael Lotz 			bool secondaryIdentifierOptional;
15795eee1a3SMichael Lotz 			if (message->FindBool("secondaryIdentifierOptional",
15895eee1a3SMichael Lotz 					&secondaryIdentifierOptional) != B_OK) {
15995eee1a3SMichael Lotz 				secondaryIdentifierOptional = false;
16095eee1a3SMichael Lotz 			}
16195eee1a3SMichael Lotz 
16295eee1a3SMichael Lotz 			BString secondaryIdentifier;
16395eee1a3SMichael Lotz 			if (message->FindString("secondaryIdentifier",
16495eee1a3SMichael Lotz 					&secondaryIdentifier) != B_OK) {
16595eee1a3SMichael Lotz 				secondaryIdentifier = "";
16695eee1a3SMichael Lotz 				secondaryIdentifierOptional = true;
16795eee1a3SMichael Lotz 			}
16895eee1a3SMichael Lotz 
16995eee1a3SMichael Lotz 			BMessage keyMessage;
17095eee1a3SMichael Lotz 			result = keyring->FindKey(identifier, secondaryIdentifier,
17195eee1a3SMichael Lotz 				secondaryIdentifierOptional, &keyMessage);
17295eee1a3SMichael Lotz 			if (result == B_OK)
17395eee1a3SMichael Lotz 				reply.AddMessage("key", &keyMessage);
174f16fef70SMichael Lotz 
1758d9bc9e0SMichael Lotz 			break;
1768d9bc9e0SMichael Lotz 		}
1778d9bc9e0SMichael Lotz 
1788d9bc9e0SMichael Lotz 		case KEY_STORE_GET_NEXT_KEY:
1798d9bc9e0SMichael Lotz 		{
1800dfaf59dSMichael Lotz 			BKeyType type;
1810dfaf59dSMichael Lotz 			BKeyPurpose purpose;
1820dfaf59dSMichael Lotz 			uint32 cookie;
1830dfaf59dSMichael Lotz 			if (message->FindUInt32("type", (uint32*)&type) != B_OK
1840dfaf59dSMichael Lotz 				|| message->FindUInt32("purpose", (uint32*)&purpose) != B_OK
1850dfaf59dSMichael Lotz 				|| message->FindUInt32("cookie", &cookie) != B_OK) {
1860dfaf59dSMichael Lotz 				result = B_BAD_VALUE;
1870dfaf59dSMichael Lotz 				break;
1880dfaf59dSMichael Lotz 			}
1890dfaf59dSMichael Lotz 
1900dfaf59dSMichael Lotz 			BMessage keyMessage;
19195eee1a3SMichael Lotz 			result = keyring->FindKey(type, purpose, cookie, keyMessage);
1920dfaf59dSMichael Lotz 			if (result == B_OK) {
1930dfaf59dSMichael Lotz 				cookie++;
1940dfaf59dSMichael Lotz 				reply.AddUInt32("cookie", cookie);
1950dfaf59dSMichael Lotz 				reply.AddMessage("key", &keyMessage);
1960dfaf59dSMichael Lotz 			}
1970dfaf59dSMichael Lotz 
1980dfaf59dSMichael Lotz 			break;
1990dfaf59dSMichael Lotz 		}
2000dfaf59dSMichael Lotz 
2010dfaf59dSMichael Lotz 		case KEY_STORE_ADD_KEY:
2020dfaf59dSMichael Lotz 		{
2030dfaf59dSMichael Lotz 			BMessage keyMessage;
2040dfaf59dSMichael Lotz 			BString identifier;
2050dfaf59dSMichael Lotz 			if (message->FindMessage("key", &keyMessage) != B_OK
2060dfaf59dSMichael Lotz 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
2070dfaf59dSMichael Lotz 				result = B_BAD_VALUE;
2080dfaf59dSMichael Lotz 				break;
2090dfaf59dSMichael Lotz 			}
2100dfaf59dSMichael Lotz 
2110dfaf59dSMichael Lotz 			BString secondaryIdentifier;
2120dfaf59dSMichael Lotz 			if (keyMessage.FindString("secondaryIdentifier",
2130dfaf59dSMichael Lotz 					&secondaryIdentifier) != B_OK) {
2140dfaf59dSMichael Lotz 				secondaryIdentifier = "";
2150dfaf59dSMichael Lotz 			}
2160dfaf59dSMichael Lotz 
21795eee1a3SMichael Lotz 			result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage);
21895eee1a3SMichael Lotz 			if (result == B_OK)
21995eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
22095eee1a3SMichael Lotz 
22195eee1a3SMichael Lotz 			break;
22295eee1a3SMichael Lotz 		}
22395eee1a3SMichael Lotz 
22495eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEY:
22595eee1a3SMichael Lotz 		{
22695eee1a3SMichael Lotz 			BMessage keyMessage;
22795eee1a3SMichael Lotz 			BString identifier;
22895eee1a3SMichael Lotz 			if (message->FindMessage("key", &keyMessage) != B_OK
22995eee1a3SMichael Lotz 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
23095eee1a3SMichael Lotz 				result = B_BAD_VALUE;
23195eee1a3SMichael Lotz 				break;
23295eee1a3SMichael Lotz 			}
23395eee1a3SMichael Lotz 
23495eee1a3SMichael Lotz 			result = keyring->RemoveKey(identifier, keyMessage);
23595eee1a3SMichael Lotz 			if (result == B_OK)
23695eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
23795eee1a3SMichael Lotz 
23895eee1a3SMichael Lotz 			break;
23995eee1a3SMichael Lotz 		}
24095eee1a3SMichael Lotz 
24195eee1a3SMichael Lotz 		case KEY_STORE_ADD_KEYRING:
24295eee1a3SMichael Lotz 		{
24395eee1a3SMichael Lotz 			BMessage keyMessage;
24495eee1a3SMichael Lotz 			BString keyring;
24595eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyring) != B_OK
24695eee1a3SMichael Lotz 				|| message->FindMessage("key", &keyMessage) != B_OK) {
24795eee1a3SMichael Lotz 				result = B_BAD_VALUE;
24895eee1a3SMichael Lotz 				break;
24995eee1a3SMichael Lotz 			}
25095eee1a3SMichael Lotz 
25195eee1a3SMichael Lotz 			result = _AddKeyring(keyring, keyMessage);
25295eee1a3SMichael Lotz 			if (result == B_OK)
25395eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
25495eee1a3SMichael Lotz 
25595eee1a3SMichael Lotz 			break;
25695eee1a3SMichael Lotz 		}
25795eee1a3SMichael Lotz 
25895eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING:
25995eee1a3SMichael Lotz 		{
26095eee1a3SMichael Lotz 			BString keyringName;
26195eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyringName) != B_OK)
26295eee1a3SMichael Lotz 				keyringName = "";
26395eee1a3SMichael Lotz 
26495eee1a3SMichael Lotz 			result = _RemoveKeyring(keyringName);
26595eee1a3SMichael Lotz 			if (result == B_OK)
26695eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
26795eee1a3SMichael Lotz 
26895eee1a3SMichael Lotz 			break;
26995eee1a3SMichael Lotz 		}
27095eee1a3SMichael Lotz 
27195eee1a3SMichael Lotz 		case KEY_STORE_GET_NEXT_KEYRING:
27295eee1a3SMichael Lotz 		{
27395eee1a3SMichael Lotz 			uint32 cookie;
27495eee1a3SMichael Lotz 			if (message->FindUInt32("cookie", &cookie) != B_OK) {
27595eee1a3SMichael Lotz 				result = B_BAD_VALUE;
27695eee1a3SMichael Lotz 				break;
27795eee1a3SMichael Lotz 			}
27895eee1a3SMichael Lotz 
27995eee1a3SMichael Lotz 			if (cookie == 0)
28095eee1a3SMichael Lotz 				keyring = fDefaultKeyring;
28195eee1a3SMichael Lotz 			else
28295eee1a3SMichael Lotz 				keyring = fKeyrings.ItemAt(cookie - 1);
28395eee1a3SMichael Lotz 
28495eee1a3SMichael Lotz 			if (keyring == NULL) {
28595eee1a3SMichael Lotz 				result = B_ENTRY_NOT_FOUND;
28695eee1a3SMichael Lotz 				break;
28795eee1a3SMichael Lotz 			}
28895eee1a3SMichael Lotz 
28995eee1a3SMichael Lotz 			cookie++;
29095eee1a3SMichael Lotz 			reply.AddUInt32("cookie", cookie);
29195eee1a3SMichael Lotz 			reply.AddString("keyring", keyring->Name());
29295eee1a3SMichael Lotz 			result = B_OK;
29395eee1a3SMichael Lotz 			break;
29495eee1a3SMichael Lotz 		}
29595eee1a3SMichael Lotz 
29695eee1a3SMichael Lotz 		case KEY_STORE_IS_KEYRING_ACCESSIBLE:
29795eee1a3SMichael Lotz 		{
29895eee1a3SMichael Lotz 			reply.AddBool("accessible", keyring->IsAccessible());
29995eee1a3SMichael Lotz 			result = B_OK;
300f16fef70SMichael Lotz 			break;
30195eee1a3SMichael Lotz 		}
30295eee1a3SMichael Lotz 
303ac9b28f0SMichael Lotz 		case KEY_STORE_REVOKE_ACCESS:
304ac9b28f0SMichael Lotz 		{
305ac9b28f0SMichael Lotz 			keyring->RevokeAccess();
306ac9b28f0SMichael Lotz 			result = B_OK;
307f16fef70SMichael Lotz 			break;
308f16fef70SMichael Lotz 		}
309f16fef70SMichael Lotz 
310f16fef70SMichael Lotz 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
311f16fef70SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
312f16fef70SMichael Lotz 		{
313f16fef70SMichael Lotz 			// We also need access to the default keyring.
314f16fef70SMichael Lotz 			while (!fDefaultKeyring->IsAccessible()) {
315f16fef70SMichael Lotz 				status_t accessResult = _AccessKeyring(*fDefaultKeyring);
316f16fef70SMichael Lotz 				if (accessResult != B_OK) {
317f16fef70SMichael Lotz 					result = accessResult;
318f16fef70SMichael Lotz 					message->what = 0;
319f16fef70SMichael Lotz 					break;
320f16fef70SMichael Lotz 				}
321f16fef70SMichael Lotz 			}
322f16fef70SMichael Lotz 
323f16fef70SMichael Lotz 			if (message->what == 0)
324f16fef70SMichael Lotz 				break;
325f16fef70SMichael Lotz 
326f16fef70SMichael Lotz 			BString secondaryIdentifier = keyring->Name();
327f16fef70SMichael Lotz 			BMessage keyMessage = keyring->KeyMessage();
328f16fef70SMichael Lotz 			keyMessage.RemoveName("identifier");
329f16fef70SMichael Lotz 			keyMessage.AddString("identifier", kKeyringKeysIdentifier);
330f16fef70SMichael Lotz 			keyMessage.RemoveName("secondaryIdentifier");
331f16fef70SMichael Lotz 			keyMessage.AddString("secondaryIdentifier", secondaryIdentifier);
332f16fef70SMichael Lotz 
333f16fef70SMichael Lotz 			switch (message->what) {
334f16fef70SMichael Lotz 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
335f16fef70SMichael Lotz 					result = fDefaultKeyring->AddKey(kKeyringKeysIdentifier,
336f16fef70SMichael Lotz 						secondaryIdentifier, keyMessage);
337f16fef70SMichael Lotz 					break;
338f16fef70SMichael Lotz 
339f16fef70SMichael Lotz 				case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
340f16fef70SMichael Lotz 					result = fDefaultKeyring->RemoveKey(kKeyringKeysIdentifier,
341f16fef70SMichael Lotz 						keyMessage);
342f16fef70SMichael Lotz 					break;
343f16fef70SMichael Lotz 			}
344f16fef70SMichael Lotz 
345f16fef70SMichael Lotz 			if (result == B_OK)
346f16fef70SMichael Lotz 				_WriteKeyStoreDatabase();
347f16fef70SMichael Lotz 
348f16fef70SMichael Lotz 			break;
349ac9b28f0SMichael Lotz 		}
350ac9b28f0SMichael Lotz 
35195eee1a3SMichael Lotz 		case 0:
35295eee1a3SMichael Lotz 		{
35395eee1a3SMichael Lotz 			// Just the error case from above.
3548d9bc9e0SMichael Lotz 			break;
3558d9bc9e0SMichael Lotz 		}
3568d9bc9e0SMichael Lotz 
3578d9bc9e0SMichael Lotz 		default:
3588d9bc9e0SMichael Lotz 		{
3598d9bc9e0SMichael Lotz 			printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n",
3608d9bc9e0SMichael Lotz 				message->what, (const char*)&message->what);
3618d9bc9e0SMichael Lotz 			break;
3628d9bc9e0SMichael Lotz 		}
3638d9bc9e0SMichael Lotz 	}
3648d9bc9e0SMichael Lotz 
3650dfaf59dSMichael Lotz 	if (message->IsSourceWaiting()) {
3660dfaf59dSMichael Lotz 		if (result == B_OK)
3670dfaf59dSMichael Lotz 			reply.what = KEY_STORE_SUCCESS;
3680dfaf59dSMichael Lotz 		else {
3690dfaf59dSMichael Lotz 			reply.what = KEY_STORE_RESULT;
3700dfaf59dSMichael Lotz 			reply.AddInt32("result", result);
3710dfaf59dSMichael Lotz 		}
3720dfaf59dSMichael Lotz 
3730dfaf59dSMichael Lotz 		message->SendReply(&reply);
3740dfaf59dSMichael Lotz 	}
3758d9bc9e0SMichael Lotz }
3768d9bc9e0SMichael Lotz 
3778d9bc9e0SMichael Lotz 
3788d9bc9e0SMichael Lotz status_t
3790dfaf59dSMichael Lotz KeyStoreServer::_ReadKeyStoreDatabase()
3808d9bc9e0SMichael Lotz {
38195eee1a3SMichael Lotz 	BMessage keyrings;
38295eee1a3SMichael Lotz 	status_t result = keyrings.Unflatten(&fKeyStoreFile);
3830dfaf59dSMichael Lotz 	if (result != B_OK) {
3840dfaf59dSMichael Lotz 		printf("failed to read keystore database\n");
3850dfaf59dSMichael Lotz 		_WriteKeyStoreDatabase();
3860dfaf59dSMichael Lotz 		return result;
3870dfaf59dSMichael Lotz 	}
3880dfaf59dSMichael Lotz 
38995eee1a3SMichael Lotz 	int32 index = 0;
39095eee1a3SMichael Lotz 	char* keyringName = NULL;
391*1b3bb46aSMichael Lotz 	while (keyrings.GetInfo(B_RAW_TYPE, index++, &keyringName, NULL) == B_OK) {
392*1b3bb46aSMichael Lotz 		Keyring* keyring = new(std::nothrow) Keyring(keyringName);
393*1b3bb46aSMichael Lotz 		if (keyring == NULL) {
394*1b3bb46aSMichael Lotz 			printf("no memory for allocating keyring \"%s\"\n", keyringName);
39595eee1a3SMichael Lotz 			continue;
39695eee1a3SMichael Lotz 		}
39795eee1a3SMichael Lotz 
398*1b3bb46aSMichael Lotz 		status_t result = keyring->ReadFromMessage(keyrings);
399*1b3bb46aSMichael Lotz 		if (result != B_OK) {
400*1b3bb46aSMichael Lotz 			printf("failed to read keyring \"%s\" from data\n", keyringName);
401*1b3bb46aSMichael Lotz 			delete keyring;
40295eee1a3SMichael Lotz 			continue;
40395eee1a3SMichael Lotz 		}
40495eee1a3SMichael Lotz 
40595eee1a3SMichael Lotz 		if (strlen(keyringName) == 0)
40695eee1a3SMichael Lotz 			fDefaultKeyring = keyring;
40795eee1a3SMichael Lotz 		else
40895eee1a3SMichael Lotz 			fKeyrings.BinaryInsert(keyring, &Keyring::Compare);
40995eee1a3SMichael Lotz 	}
41095eee1a3SMichael Lotz 
4110dfaf59dSMichael Lotz 	return B_OK;
4120dfaf59dSMichael Lotz }
4130dfaf59dSMichael Lotz 
4140dfaf59dSMichael Lotz 
4150dfaf59dSMichael Lotz status_t
4160dfaf59dSMichael Lotz KeyStoreServer::_WriteKeyStoreDatabase()
4170dfaf59dSMichael Lotz {
4180dfaf59dSMichael Lotz 	fKeyStoreFile.SetSize(0);
4190dfaf59dSMichael Lotz 	fKeyStoreFile.Seek(0, SEEK_SET);
4200dfaf59dSMichael Lotz 
42195eee1a3SMichael Lotz 	BMessage keyrings;
42295eee1a3SMichael Lotz 	if (fDefaultKeyring != NULL)
423*1b3bb46aSMichael Lotz 		fDefaultKeyring->WriteToMessage(keyrings);
4240dfaf59dSMichael Lotz 
42595eee1a3SMichael Lotz 	for (int32 i = 0; i < fKeyrings.CountItems(); i++) {
42695eee1a3SMichael Lotz 		Keyring* keyring = fKeyrings.ItemAt(i);
42795eee1a3SMichael Lotz 		if (keyring == NULL)
4280dfaf59dSMichael Lotz 			continue;
42995eee1a3SMichael Lotz 
430*1b3bb46aSMichael Lotz 		status_t result = keyring->WriteToMessage(keyrings);
431*1b3bb46aSMichael Lotz 		if (result != B_OK)
432*1b3bb46aSMichael Lotz 			return result;
4330dfaf59dSMichael Lotz 	}
4340dfaf59dSMichael Lotz 
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 
48195eee1a3SMichael Lotz Keyring*
48295eee1a3SMichael Lotz KeyStoreServer::_FindKeyring(const BString& name)
48395eee1a3SMichael Lotz {
48495eee1a3SMichael Lotz 	if (name.IsEmpty())
48595eee1a3SMichael Lotz 		return fDefaultKeyring;
4860dfaf59dSMichael Lotz 
48795eee1a3SMichael Lotz 	return fKeyrings.BinarySearchByKey(name, &Keyring::Compare);
4880dfaf59dSMichael Lotz }
4890dfaf59dSMichael Lotz 
4900dfaf59dSMichael Lotz 
4910dfaf59dSMichael Lotz status_t
49295eee1a3SMichael Lotz KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage)
4930dfaf59dSMichael Lotz {
49495eee1a3SMichael Lotz 	if (_FindKeyring(name) != NULL)
4950dfaf59dSMichael Lotz 		return B_NAME_IN_USE;
4960dfaf59dSMichael Lotz 
497*1b3bb46aSMichael Lotz 	Keyring* keyring = new(std::nothrow) Keyring(name, &keyMessage);
49895eee1a3SMichael Lotz 	if (keyring == NULL)
49995eee1a3SMichael Lotz 		return B_NO_MEMORY;
50095eee1a3SMichael Lotz 
50195eee1a3SMichael Lotz 	if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) {
50295eee1a3SMichael Lotz 		delete keyring;
50395eee1a3SMichael Lotz 		return B_ERROR;
50495eee1a3SMichael Lotz 	}
50595eee1a3SMichael Lotz 
50695eee1a3SMichael Lotz 	return B_OK;
50795eee1a3SMichael Lotz }
50895eee1a3SMichael Lotz 
50995eee1a3SMichael Lotz 
51095eee1a3SMichael Lotz status_t
51195eee1a3SMichael Lotz KeyStoreServer::_RemoveKeyring(const BString& name)
51295eee1a3SMichael Lotz {
51395eee1a3SMichael Lotz 	Keyring* keyring = _FindKeyring(name);
51495eee1a3SMichael Lotz 	if (keyring == NULL)
51595eee1a3SMichael Lotz 		return B_ENTRY_NOT_FOUND;
51695eee1a3SMichael Lotz 
51795eee1a3SMichael Lotz 	if (keyring == fDefaultKeyring) {
51895eee1a3SMichael Lotz 		// The default keyring can't be removed.
51995eee1a3SMichael Lotz 		return B_NOT_ALLOWED;
52095eee1a3SMichael Lotz 	}
52195eee1a3SMichael Lotz 
52295eee1a3SMichael Lotz 	return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR;
5238d9bc9e0SMichael Lotz }
5248d9bc9e0SMichael Lotz 
5258d9bc9e0SMichael Lotz 
526ac9b28f0SMichael Lotz status_t
527ac9b28f0SMichael Lotz KeyStoreServer::_AccessKeyring(Keyring& keyring)
528ac9b28f0SMichael Lotz {
529ac9b28f0SMichael Lotz 	// If we are accessing a keyring that has been added to master access we
530ac9b28f0SMichael Lotz 	// get the key from the default keyring and unlock with that.
531ac9b28f0SMichael Lotz 	BMessage keyMessage;
532ac9b28f0SMichael Lotz 	if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) {
533f16fef70SMichael Lotz 		if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(),
534f16fef70SMichael Lotz 				false, &keyMessage) == B_OK) {
535ac9b28f0SMichael Lotz 			// We found a key for this keyring, try to access with it.
536ac9b28f0SMichael Lotz 			if (keyring.Access(keyMessage) == B_OK)
537ac9b28f0SMichael Lotz 				return B_OK;
538ac9b28f0SMichael Lotz 		}
539ac9b28f0SMichael Lotz 	}
540ac9b28f0SMichael Lotz 
541ac9b28f0SMichael Lotz 	// No key, we need to request one from the user.
54290013c82SMichael Lotz 	status_t result = _RequestKey(keyring.Name(), keyMessage);
543ac9b28f0SMichael Lotz 	if (result != B_OK)
544ac9b28f0SMichael Lotz 		return result;
545ac9b28f0SMichael Lotz 
546ac9b28f0SMichael Lotz 	return keyring.Access(keyMessage);
547ac9b28f0SMichael Lotz }
548ac9b28f0SMichael Lotz 
549ac9b28f0SMichael Lotz 
550ac9b28f0SMichael Lotz status_t
55190013c82SMichael Lotz KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage)
552ac9b28f0SMichael Lotz {
553ac9b28f0SMichael Lotz 	KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow();
554ac9b28f0SMichael Lotz 	if (requestWindow == NULL)
555ac9b28f0SMichael Lotz 		return B_NO_MEMORY;
556ac9b28f0SMichael Lotz 
55790013c82SMichael Lotz 	return requestWindow->RequestKey(keyringName, keyMessage);
558ac9b28f0SMichael Lotz }
559ac9b28f0SMichael Lotz 
560ac9b28f0SMichael Lotz 
5618d9bc9e0SMichael Lotz int
5628d9bc9e0SMichael Lotz main(int argc, char* argv[])
5638d9bc9e0SMichael Lotz {
5648d9bc9e0SMichael Lotz 	KeyStoreServer* app = new(std::nothrow) KeyStoreServer();
5658d9bc9e0SMichael Lotz 	if (app == NULL)
5668d9bc9e0SMichael Lotz 		return 1;
5678d9bc9e0SMichael Lotz 
5688d9bc9e0SMichael Lotz 	app->Run();
5698d9bc9e0SMichael Lotz 	delete app;
5708d9bc9e0SMichael Lotz 	return 0;
5718d9bc9e0SMichael Lotz }
572