xref: /haiku/src/servers/keystore/KeyStoreServer.cpp (revision f16fef70bee3877ed2b72e9b5714bc6b4f93b4bd)
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 
28*f16fef70SMichael Lotz static const char* kKeyringKeysIdentifier = "Keyrings";
29*f16fef70SMichael Lotz 
30*f16fef70SMichael Lotz 
318d9bc9e0SMichael Lotz KeyStoreServer::KeyStoreServer()
328d9bc9e0SMichael Lotz 	:
3395eee1a3SMichael Lotz 	BApplication(kKeyStoreServerSignature),
3495eee1a3SMichael Lotz 	fDefaultKeyring(NULL),
3595eee1a3SMichael Lotz 	fKeyrings(20, true)
368d9bc9e0SMichael Lotz {
370dfaf59dSMichael Lotz 	BPath path;
380dfaf59dSMichael Lotz 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
390dfaf59dSMichael Lotz 		return;
400dfaf59dSMichael Lotz 
410dfaf59dSMichael Lotz 	BDirectory settingsDir(path.Path());
420dfaf59dSMichael Lotz 	path.Append("system");
430dfaf59dSMichael Lotz 	if (!settingsDir.Contains(path.Path()))
440dfaf59dSMichael Lotz 		settingsDir.CreateDirectory(path.Path(), NULL);
450dfaf59dSMichael Lotz 
460dfaf59dSMichael Lotz 	settingsDir.SetTo(path.Path());
470dfaf59dSMichael Lotz 	path.Append("keystore");
480dfaf59dSMichael Lotz 	if (!settingsDir.Contains(path.Path()))
490dfaf59dSMichael Lotz 		settingsDir.CreateDirectory(path.Path(), NULL);
500dfaf59dSMichael Lotz 
510dfaf59dSMichael Lotz 	settingsDir.SetTo(path.Path());
520dfaf59dSMichael Lotz 	path.Append("keystore_database");
530dfaf59dSMichael Lotz 
540dfaf59dSMichael Lotz 	fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE
550dfaf59dSMichael Lotz 		| (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE));
560dfaf59dSMichael Lotz 
570dfaf59dSMichael Lotz 	_ReadKeyStoreDatabase();
5895eee1a3SMichael Lotz 
5995eee1a3SMichael Lotz 	if (fDefaultKeyring == NULL)
6095eee1a3SMichael Lotz 		fDefaultKeyring = new(std::nothrow) Keyring("", BMessage());
618d9bc9e0SMichael Lotz }
628d9bc9e0SMichael Lotz 
638d9bc9e0SMichael Lotz 
648d9bc9e0SMichael Lotz KeyStoreServer::~KeyStoreServer()
658d9bc9e0SMichael Lotz {
668d9bc9e0SMichael Lotz }
678d9bc9e0SMichael Lotz 
688d9bc9e0SMichael Lotz 
698d9bc9e0SMichael Lotz void
708d9bc9e0SMichael Lotz KeyStoreServer::MessageReceived(BMessage* message)
718d9bc9e0SMichael Lotz {
720dfaf59dSMichael Lotz 	BMessage reply;
7395eee1a3SMichael Lotz 	status_t result = B_UNSUPPORTED;
7495eee1a3SMichael Lotz 
7595eee1a3SMichael Lotz 	// Resolve the keyring for the relevant messages.
7695eee1a3SMichael Lotz 	Keyring* keyring = NULL;
7795eee1a3SMichael Lotz 	switch (message->what) {
7895eee1a3SMichael Lotz 		case KEY_STORE_GET_KEY:
7995eee1a3SMichael Lotz 		case KEY_STORE_GET_NEXT_KEY:
8095eee1a3SMichael Lotz 		case KEY_STORE_ADD_KEY:
8195eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEY:
8295eee1a3SMichael Lotz 		case KEY_STORE_IS_KEYRING_ACCESSIBLE:
8395eee1a3SMichael Lotz 		case KEY_STORE_REVOKE_ACCESS:
84*f16fef70SMichael Lotz 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
85*f16fef70SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
8695eee1a3SMichael Lotz 		{
8795eee1a3SMichael Lotz 			BString keyringName;
8895eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyringName) != B_OK)
8995eee1a3SMichael Lotz 				keyringName = "";
9095eee1a3SMichael Lotz 
9195eee1a3SMichael Lotz 			keyring = _FindKeyring(keyringName);
9295eee1a3SMichael Lotz 			if (keyring == NULL) {
9395eee1a3SMichael Lotz 				result = B_BAD_VALUE;
9495eee1a3SMichael Lotz 				message->what = 0;
9595eee1a3SMichael Lotz 					// So that we don't do anything in the second switch.
9695eee1a3SMichael Lotz 				break;
9795eee1a3SMichael Lotz 			}
9895eee1a3SMichael Lotz 
99ac9b28f0SMichael Lotz 			switch (message->what) {
100ac9b28f0SMichael Lotz 				case KEY_STORE_GET_KEY:
101ac9b28f0SMichael Lotz 				case KEY_STORE_GET_NEXT_KEY:
102ac9b28f0SMichael Lotz 				case KEY_STORE_ADD_KEY:
103ac9b28f0SMichael Lotz 				case KEY_STORE_REMOVE_KEY:
104*f16fef70SMichael Lotz 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
105ac9b28f0SMichael Lotz 				{
106ac9b28f0SMichael Lotz 					// These need keyring access to do anything.
107ac9b28f0SMichael Lotz 					while (!keyring->IsAccessible()) {
108ac9b28f0SMichael Lotz 						status_t accessResult = _AccessKeyring(*keyring);
109ac9b28f0SMichael Lotz 						if (accessResult != B_OK) {
110ac9b28f0SMichael Lotz 							result = accessResult;
111ac9b28f0SMichael Lotz 							message->what = 0;
112ac9b28f0SMichael Lotz 							break;
113ac9b28f0SMichael Lotz 						}
114ac9b28f0SMichael Lotz 					}
115ac9b28f0SMichael Lotz 				}
116ac9b28f0SMichael Lotz 			}
117ac9b28f0SMichael Lotz 
11895eee1a3SMichael Lotz 			break;
11995eee1a3SMichael Lotz 		}
12095eee1a3SMichael Lotz 	}
1210dfaf59dSMichael Lotz 
1228d9bc9e0SMichael Lotz 	switch (message->what) {
1238d9bc9e0SMichael Lotz 		case KEY_STORE_GET_KEY:
1248d9bc9e0SMichael Lotz 		{
12595eee1a3SMichael Lotz 			BString identifier;
12695eee1a3SMichael Lotz 			if (message->FindString("identifier", &identifier) != B_OK) {
12795eee1a3SMichael Lotz 				result = B_BAD_VALUE;
12895eee1a3SMichael Lotz 				break;
12995eee1a3SMichael Lotz 			}
13095eee1a3SMichael Lotz 
13195eee1a3SMichael Lotz 			bool secondaryIdentifierOptional;
13295eee1a3SMichael Lotz 			if (message->FindBool("secondaryIdentifierOptional",
13395eee1a3SMichael Lotz 					&secondaryIdentifierOptional) != B_OK) {
13495eee1a3SMichael Lotz 				secondaryIdentifierOptional = false;
13595eee1a3SMichael Lotz 			}
13695eee1a3SMichael Lotz 
13795eee1a3SMichael Lotz 			BString secondaryIdentifier;
13895eee1a3SMichael Lotz 			if (message->FindString("secondaryIdentifier",
13995eee1a3SMichael Lotz 					&secondaryIdentifier) != B_OK) {
14095eee1a3SMichael Lotz 				secondaryIdentifier = "";
14195eee1a3SMichael Lotz 				secondaryIdentifierOptional = true;
14295eee1a3SMichael Lotz 			}
14395eee1a3SMichael Lotz 
14495eee1a3SMichael Lotz 			BMessage keyMessage;
14595eee1a3SMichael Lotz 			result = keyring->FindKey(identifier, secondaryIdentifier,
14695eee1a3SMichael Lotz 				secondaryIdentifierOptional, &keyMessage);
14795eee1a3SMichael Lotz 			if (result == B_OK)
14895eee1a3SMichael Lotz 				reply.AddMessage("key", &keyMessage);
149*f16fef70SMichael Lotz 
1508d9bc9e0SMichael Lotz 			break;
1518d9bc9e0SMichael Lotz 		}
1528d9bc9e0SMichael Lotz 
1538d9bc9e0SMichael Lotz 		case KEY_STORE_GET_NEXT_KEY:
1548d9bc9e0SMichael Lotz 		{
1550dfaf59dSMichael Lotz 			BKeyType type;
1560dfaf59dSMichael Lotz 			BKeyPurpose purpose;
1570dfaf59dSMichael Lotz 			uint32 cookie;
1580dfaf59dSMichael Lotz 			if (message->FindUInt32("type", (uint32*)&type) != B_OK
1590dfaf59dSMichael Lotz 				|| message->FindUInt32("purpose", (uint32*)&purpose) != B_OK
1600dfaf59dSMichael Lotz 				|| message->FindUInt32("cookie", &cookie) != B_OK) {
1610dfaf59dSMichael Lotz 				result = B_BAD_VALUE;
1620dfaf59dSMichael Lotz 				break;
1630dfaf59dSMichael Lotz 			}
1640dfaf59dSMichael Lotz 
1650dfaf59dSMichael Lotz 			BMessage keyMessage;
16695eee1a3SMichael Lotz 			result = keyring->FindKey(type, purpose, cookie, keyMessage);
1670dfaf59dSMichael Lotz 			if (result == B_OK) {
1680dfaf59dSMichael Lotz 				cookie++;
1690dfaf59dSMichael Lotz 				reply.AddUInt32("cookie", cookie);
1700dfaf59dSMichael Lotz 				reply.AddMessage("key", &keyMessage);
1710dfaf59dSMichael Lotz 			}
1720dfaf59dSMichael Lotz 
1730dfaf59dSMichael Lotz 			break;
1740dfaf59dSMichael Lotz 		}
1750dfaf59dSMichael Lotz 
1760dfaf59dSMichael Lotz 		case KEY_STORE_ADD_KEY:
1770dfaf59dSMichael Lotz 		{
1780dfaf59dSMichael Lotz 			BMessage keyMessage;
1790dfaf59dSMichael Lotz 			BString identifier;
1800dfaf59dSMichael Lotz 			if (message->FindMessage("key", &keyMessage) != B_OK
1810dfaf59dSMichael Lotz 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
1820dfaf59dSMichael Lotz 				result = B_BAD_VALUE;
1830dfaf59dSMichael Lotz 				break;
1840dfaf59dSMichael Lotz 			}
1850dfaf59dSMichael Lotz 
1860dfaf59dSMichael Lotz 			BString secondaryIdentifier;
1870dfaf59dSMichael Lotz 			if (keyMessage.FindString("secondaryIdentifier",
1880dfaf59dSMichael Lotz 					&secondaryIdentifier) != B_OK) {
1890dfaf59dSMichael Lotz 				secondaryIdentifier = "";
1900dfaf59dSMichael Lotz 			}
1910dfaf59dSMichael Lotz 
19295eee1a3SMichael Lotz 			result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage);
19395eee1a3SMichael Lotz 			if (result == B_OK)
19495eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
19595eee1a3SMichael Lotz 
19695eee1a3SMichael Lotz 			break;
19795eee1a3SMichael Lotz 		}
19895eee1a3SMichael Lotz 
19995eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEY:
20095eee1a3SMichael Lotz 		{
20195eee1a3SMichael Lotz 			BMessage keyMessage;
20295eee1a3SMichael Lotz 			BString identifier;
20395eee1a3SMichael Lotz 			if (message->FindMessage("key", &keyMessage) != B_OK
20495eee1a3SMichael Lotz 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
20595eee1a3SMichael Lotz 				result = B_BAD_VALUE;
20695eee1a3SMichael Lotz 				break;
20795eee1a3SMichael Lotz 			}
20895eee1a3SMichael Lotz 
20995eee1a3SMichael Lotz 			result = keyring->RemoveKey(identifier, keyMessage);
21095eee1a3SMichael Lotz 			if (result == B_OK)
21195eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
21295eee1a3SMichael Lotz 
21395eee1a3SMichael Lotz 			break;
21495eee1a3SMichael Lotz 		}
21595eee1a3SMichael Lotz 
21695eee1a3SMichael Lotz 		case KEY_STORE_ADD_KEYRING:
21795eee1a3SMichael Lotz 		{
21895eee1a3SMichael Lotz 			BMessage keyMessage;
21995eee1a3SMichael Lotz 			BString keyring;
22095eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyring) != B_OK
22195eee1a3SMichael Lotz 				|| message->FindMessage("key", &keyMessage) != B_OK) {
22295eee1a3SMichael Lotz 				result = B_BAD_VALUE;
22395eee1a3SMichael Lotz 				break;
22495eee1a3SMichael Lotz 			}
22595eee1a3SMichael Lotz 
22695eee1a3SMichael Lotz 			result = _AddKeyring(keyring, keyMessage);
22795eee1a3SMichael Lotz 			if (result == B_OK)
22895eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
22995eee1a3SMichael Lotz 
23095eee1a3SMichael Lotz 			break;
23195eee1a3SMichael Lotz 		}
23295eee1a3SMichael Lotz 
23395eee1a3SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING:
23495eee1a3SMichael Lotz 		{
23595eee1a3SMichael Lotz 			BString keyringName;
23695eee1a3SMichael Lotz 			if (message->FindString("keyring", &keyringName) != B_OK)
23795eee1a3SMichael Lotz 				keyringName = "";
23895eee1a3SMichael Lotz 
23995eee1a3SMichael Lotz 			result = _RemoveKeyring(keyringName);
24095eee1a3SMichael Lotz 			if (result == B_OK)
24195eee1a3SMichael Lotz 				_WriteKeyStoreDatabase();
24295eee1a3SMichael Lotz 
24395eee1a3SMichael Lotz 			break;
24495eee1a3SMichael Lotz 		}
24595eee1a3SMichael Lotz 
24695eee1a3SMichael Lotz 		case KEY_STORE_GET_NEXT_KEYRING:
24795eee1a3SMichael Lotz 		{
24895eee1a3SMichael Lotz 			uint32 cookie;
24995eee1a3SMichael Lotz 			if (message->FindUInt32("cookie", &cookie) != B_OK) {
25095eee1a3SMichael Lotz 				result = B_BAD_VALUE;
25195eee1a3SMichael Lotz 				break;
25295eee1a3SMichael Lotz 			}
25395eee1a3SMichael Lotz 
25495eee1a3SMichael Lotz 			if (cookie == 0)
25595eee1a3SMichael Lotz 				keyring = fDefaultKeyring;
25695eee1a3SMichael Lotz 			else
25795eee1a3SMichael Lotz 				keyring = fKeyrings.ItemAt(cookie - 1);
25895eee1a3SMichael Lotz 
25995eee1a3SMichael Lotz 			if (keyring == NULL) {
26095eee1a3SMichael Lotz 				result = B_ENTRY_NOT_FOUND;
26195eee1a3SMichael Lotz 				break;
26295eee1a3SMichael Lotz 			}
26395eee1a3SMichael Lotz 
26495eee1a3SMichael Lotz 			cookie++;
26595eee1a3SMichael Lotz 			reply.AddUInt32("cookie", cookie);
26695eee1a3SMichael Lotz 			reply.AddString("keyring", keyring->Name());
26795eee1a3SMichael Lotz 			result = B_OK;
26895eee1a3SMichael Lotz 			break;
26995eee1a3SMichael Lotz 		}
27095eee1a3SMichael Lotz 
27195eee1a3SMichael Lotz 		case KEY_STORE_IS_KEYRING_ACCESSIBLE:
27295eee1a3SMichael Lotz 		{
27395eee1a3SMichael Lotz 			reply.AddBool("accessible", keyring->IsAccessible());
27495eee1a3SMichael Lotz 			result = B_OK;
275*f16fef70SMichael Lotz 			break;
27695eee1a3SMichael Lotz 		}
27795eee1a3SMichael Lotz 
278ac9b28f0SMichael Lotz 		case KEY_STORE_REVOKE_ACCESS:
279ac9b28f0SMichael Lotz 		{
280ac9b28f0SMichael Lotz 			keyring->RevokeAccess();
281ac9b28f0SMichael Lotz 			result = B_OK;
282*f16fef70SMichael Lotz 			break;
283*f16fef70SMichael Lotz 		}
284*f16fef70SMichael Lotz 
285*f16fef70SMichael Lotz 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
286*f16fef70SMichael Lotz 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
287*f16fef70SMichael Lotz 		{
288*f16fef70SMichael Lotz 			// We also need access to the default keyring.
289*f16fef70SMichael Lotz 			while (!fDefaultKeyring->IsAccessible()) {
290*f16fef70SMichael Lotz 				status_t accessResult = _AccessKeyring(*fDefaultKeyring);
291*f16fef70SMichael Lotz 				if (accessResult != B_OK) {
292*f16fef70SMichael Lotz 					result = accessResult;
293*f16fef70SMichael Lotz 					message->what = 0;
294*f16fef70SMichael Lotz 					break;
295*f16fef70SMichael Lotz 				}
296*f16fef70SMichael Lotz 			}
297*f16fef70SMichael Lotz 
298*f16fef70SMichael Lotz 			if (message->what == 0)
299*f16fef70SMichael Lotz 				break;
300*f16fef70SMichael Lotz 
301*f16fef70SMichael Lotz 			BString secondaryIdentifier = keyring->Name();
302*f16fef70SMichael Lotz 			BMessage keyMessage = keyring->KeyMessage();
303*f16fef70SMichael Lotz 			keyMessage.RemoveName("identifier");
304*f16fef70SMichael Lotz 			keyMessage.AddString("identifier", kKeyringKeysIdentifier);
305*f16fef70SMichael Lotz 			keyMessage.RemoveName("secondaryIdentifier");
306*f16fef70SMichael Lotz 			keyMessage.AddString("secondaryIdentifier", secondaryIdentifier);
307*f16fef70SMichael Lotz 
308*f16fef70SMichael Lotz 			switch (message->what) {
309*f16fef70SMichael Lotz 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
310*f16fef70SMichael Lotz 					result = fDefaultKeyring->AddKey(kKeyringKeysIdentifier,
311*f16fef70SMichael Lotz 						secondaryIdentifier, keyMessage);
312*f16fef70SMichael Lotz 					break;
313*f16fef70SMichael Lotz 
314*f16fef70SMichael Lotz 				case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
315*f16fef70SMichael Lotz 					result = fDefaultKeyring->RemoveKey(kKeyringKeysIdentifier,
316*f16fef70SMichael Lotz 						keyMessage);
317*f16fef70SMichael Lotz 					break;
318*f16fef70SMichael Lotz 			}
319*f16fef70SMichael Lotz 
320*f16fef70SMichael Lotz 			if (result == B_OK)
321*f16fef70SMichael Lotz 				_WriteKeyStoreDatabase();
322*f16fef70SMichael Lotz 
323*f16fef70SMichael Lotz 			break;
324ac9b28f0SMichael Lotz 		}
325ac9b28f0SMichael Lotz 
32695eee1a3SMichael Lotz 		case 0:
32795eee1a3SMichael Lotz 		{
32895eee1a3SMichael Lotz 			// Just the error case from above.
3298d9bc9e0SMichael Lotz 			break;
3308d9bc9e0SMichael Lotz 		}
3318d9bc9e0SMichael Lotz 
3328d9bc9e0SMichael Lotz 		default:
3338d9bc9e0SMichael Lotz 		{
3348d9bc9e0SMichael Lotz 			printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n",
3358d9bc9e0SMichael Lotz 				message->what, (const char*)&message->what);
3368d9bc9e0SMichael Lotz 			break;
3378d9bc9e0SMichael Lotz 		}
3388d9bc9e0SMichael Lotz 	}
3398d9bc9e0SMichael Lotz 
3400dfaf59dSMichael Lotz 	if (message->IsSourceWaiting()) {
3410dfaf59dSMichael Lotz 		if (result == B_OK)
3420dfaf59dSMichael Lotz 			reply.what = KEY_STORE_SUCCESS;
3430dfaf59dSMichael Lotz 		else {
3440dfaf59dSMichael Lotz 			reply.what = KEY_STORE_RESULT;
3450dfaf59dSMichael Lotz 			reply.AddInt32("result", result);
3460dfaf59dSMichael Lotz 		}
3470dfaf59dSMichael Lotz 
3480dfaf59dSMichael Lotz 		message->SendReply(&reply);
3490dfaf59dSMichael Lotz 	}
3508d9bc9e0SMichael Lotz }
3518d9bc9e0SMichael Lotz 
3528d9bc9e0SMichael Lotz 
3538d9bc9e0SMichael Lotz status_t
3540dfaf59dSMichael Lotz KeyStoreServer::_ReadKeyStoreDatabase()
3558d9bc9e0SMichael Lotz {
35695eee1a3SMichael Lotz 	BMessage keyrings;
35795eee1a3SMichael Lotz 	status_t result = keyrings.Unflatten(&fKeyStoreFile);
3580dfaf59dSMichael Lotz 	if (result != B_OK) {
3590dfaf59dSMichael Lotz 		printf("failed to read keystore database\n");
3600dfaf59dSMichael Lotz 		_WriteKeyStoreDatabase();
3610dfaf59dSMichael Lotz 		return result;
3620dfaf59dSMichael Lotz 	}
3630dfaf59dSMichael Lotz 
36495eee1a3SMichael Lotz 	int32 index = 0;
36595eee1a3SMichael Lotz 	char* keyringName = NULL;
36695eee1a3SMichael Lotz 	while (keyrings.GetInfo(B_MESSAGE_TYPE, index++, &keyringName,
36795eee1a3SMichael Lotz 			NULL) == B_OK) {
36895eee1a3SMichael Lotz 
36995eee1a3SMichael Lotz 		BMessage keyringData;
37095eee1a3SMichael Lotz 		if (keyrings.FindMessage(keyringName, &keyringData) != B_OK) {
37195eee1a3SMichael Lotz 			printf("failed to retrieve keyring data for keyring \"%s\"\n",
37295eee1a3SMichael Lotz 				keyringName);
37395eee1a3SMichael Lotz 			continue;
37495eee1a3SMichael Lotz 		}
37595eee1a3SMichael Lotz 
37695eee1a3SMichael Lotz 		Keyring* keyring = new(std::nothrow) Keyring(keyringName, keyringData);
37795eee1a3SMichael Lotz 		if (keyring == NULL) {
37895eee1a3SMichael Lotz 			printf("no memory for allocating keyring \"%s\"\n", keyringName);
37995eee1a3SMichael Lotz 			continue;
38095eee1a3SMichael Lotz 		}
38195eee1a3SMichael Lotz 
38295eee1a3SMichael Lotz 		if (strlen(keyringName) == 0)
38395eee1a3SMichael Lotz 			fDefaultKeyring = keyring;
38495eee1a3SMichael Lotz 		else
38595eee1a3SMichael Lotz 			fKeyrings.BinaryInsert(keyring, &Keyring::Compare);
38695eee1a3SMichael Lotz 	}
38795eee1a3SMichael Lotz 
3880dfaf59dSMichael Lotz 	return B_OK;
3890dfaf59dSMichael Lotz }
3900dfaf59dSMichael Lotz 
3910dfaf59dSMichael Lotz 
3920dfaf59dSMichael Lotz status_t
3930dfaf59dSMichael Lotz KeyStoreServer::_WriteKeyStoreDatabase()
3940dfaf59dSMichael Lotz {
3950dfaf59dSMichael Lotz 	fKeyStoreFile.SetSize(0);
3960dfaf59dSMichael Lotz 	fKeyStoreFile.Seek(0, SEEK_SET);
3970dfaf59dSMichael Lotz 
39895eee1a3SMichael Lotz 	BMessage keyrings;
39995eee1a3SMichael Lotz 	if (fDefaultKeyring != NULL)
40095eee1a3SMichael Lotz 		keyrings.AddMessage("", &fDefaultKeyring->Data());
4010dfaf59dSMichael Lotz 
40295eee1a3SMichael Lotz 	for (int32 i = 0; i < fKeyrings.CountItems(); i++) {
40395eee1a3SMichael Lotz 		Keyring* keyring = fKeyrings.ItemAt(i);
40495eee1a3SMichael Lotz 		if (keyring == NULL)
4050dfaf59dSMichael Lotz 			continue;
40695eee1a3SMichael Lotz 
40795eee1a3SMichael Lotz 		keyrings.AddMessage(keyring->Name(), &keyring->Data());
4080dfaf59dSMichael Lotz 	}
4090dfaf59dSMichael Lotz 
41095eee1a3SMichael Lotz 	return keyrings.Flatten(&fKeyStoreFile);
4110dfaf59dSMichael Lotz }
4120dfaf59dSMichael Lotz 
4130dfaf59dSMichael Lotz 
41495eee1a3SMichael Lotz Keyring*
41595eee1a3SMichael Lotz KeyStoreServer::_FindKeyring(const BString& name)
41695eee1a3SMichael Lotz {
41795eee1a3SMichael Lotz 	if (name.IsEmpty())
41895eee1a3SMichael Lotz 		return fDefaultKeyring;
4190dfaf59dSMichael Lotz 
42095eee1a3SMichael Lotz 	return fKeyrings.BinarySearchByKey(name, &Keyring::Compare);
4210dfaf59dSMichael Lotz }
4220dfaf59dSMichael Lotz 
4230dfaf59dSMichael Lotz 
4240dfaf59dSMichael Lotz status_t
42595eee1a3SMichael Lotz KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage)
4260dfaf59dSMichael Lotz {
42795eee1a3SMichael Lotz 	if (_FindKeyring(name) != NULL)
4280dfaf59dSMichael Lotz 		return B_NAME_IN_USE;
4290dfaf59dSMichael Lotz 
4301dd765c9SMichael Lotz 	Keyring* keyring = new(std::nothrow) Keyring(name, BMessage(), &keyMessage);
43195eee1a3SMichael Lotz 	if (keyring == NULL)
43295eee1a3SMichael Lotz 		return B_NO_MEMORY;
43395eee1a3SMichael Lotz 
43495eee1a3SMichael Lotz 	if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) {
43595eee1a3SMichael Lotz 		delete keyring;
43695eee1a3SMichael Lotz 		return B_ERROR;
43795eee1a3SMichael Lotz 	}
43895eee1a3SMichael Lotz 
43995eee1a3SMichael Lotz 	return B_OK;
44095eee1a3SMichael Lotz }
44195eee1a3SMichael Lotz 
44295eee1a3SMichael Lotz 
44395eee1a3SMichael Lotz status_t
44495eee1a3SMichael Lotz KeyStoreServer::_RemoveKeyring(const BString& name)
44595eee1a3SMichael Lotz {
44695eee1a3SMichael Lotz 	Keyring* keyring = _FindKeyring(name);
44795eee1a3SMichael Lotz 	if (keyring == NULL)
44895eee1a3SMichael Lotz 		return B_ENTRY_NOT_FOUND;
44995eee1a3SMichael Lotz 
45095eee1a3SMichael Lotz 	if (keyring == fDefaultKeyring) {
45195eee1a3SMichael Lotz 		// The default keyring can't be removed.
45295eee1a3SMichael Lotz 		return B_NOT_ALLOWED;
45395eee1a3SMichael Lotz 	}
45495eee1a3SMichael Lotz 
45595eee1a3SMichael Lotz 	return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR;
4568d9bc9e0SMichael Lotz }
4578d9bc9e0SMichael Lotz 
4588d9bc9e0SMichael Lotz 
459ac9b28f0SMichael Lotz status_t
460ac9b28f0SMichael Lotz KeyStoreServer::_AccessKeyring(Keyring& keyring)
461ac9b28f0SMichael Lotz {
462ac9b28f0SMichael Lotz 	// If we are accessing a keyring that has been added to master access we
463ac9b28f0SMichael Lotz 	// get the key from the default keyring and unlock with that.
464ac9b28f0SMichael Lotz 	BMessage keyMessage;
465ac9b28f0SMichael Lotz 	if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) {
466*f16fef70SMichael Lotz 		if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(),
467*f16fef70SMichael Lotz 				false, &keyMessage) == B_OK) {
468ac9b28f0SMichael Lotz 			// We found a key for this keyring, try to access with it.
469ac9b28f0SMichael Lotz 			if (keyring.Access(keyMessage) == B_OK)
470ac9b28f0SMichael Lotz 				return B_OK;
471ac9b28f0SMichael Lotz 		}
472ac9b28f0SMichael Lotz 	}
473ac9b28f0SMichael Lotz 
474ac9b28f0SMichael Lotz 	// No key, we need to request one from the user.
475ac9b28f0SMichael Lotz 	keyMessage.AddString("keyring", keyring.Name());
476ac9b28f0SMichael Lotz 	status_t result = _RequestKey(keyMessage);
477ac9b28f0SMichael Lotz 	if (result != B_OK)
478ac9b28f0SMichael Lotz 		return result;
479ac9b28f0SMichael Lotz 
480ac9b28f0SMichael Lotz 	return keyring.Access(keyMessage);
481ac9b28f0SMichael Lotz }
482ac9b28f0SMichael Lotz 
483ac9b28f0SMichael Lotz 
484ac9b28f0SMichael Lotz status_t
485ac9b28f0SMichael Lotz KeyStoreServer::_RequestKey(BMessage& keyMessage)
486ac9b28f0SMichael Lotz {
487ac9b28f0SMichael Lotz 	KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow();
488ac9b28f0SMichael Lotz 	if (requestWindow == NULL)
489ac9b28f0SMichael Lotz 		return B_NO_MEMORY;
490ac9b28f0SMichael Lotz 
491ac9b28f0SMichael Lotz 	return requestWindow->RequestKey(keyMessage);
492ac9b28f0SMichael Lotz }
493ac9b28f0SMichael Lotz 
494ac9b28f0SMichael Lotz 
4958d9bc9e0SMichael Lotz int
4968d9bc9e0SMichael Lotz main(int argc, char* argv[])
4978d9bc9e0SMichael Lotz {
4988d9bc9e0SMichael Lotz 	KeyStoreServer* app = new(std::nothrow) KeyStoreServer();
4998d9bc9e0SMichael Lotz 	if (app == NULL)
5008d9bc9e0SMichael Lotz 		return 1;
5018d9bc9e0SMichael Lotz 
5028d9bc9e0SMichael Lotz 	app->Run();
5038d9bc9e0SMichael Lotz 	delete app;
5048d9bc9e0SMichael Lotz 	return 0;
5058d9bc9e0SMichael Lotz }
506