xref: /haiku/src/servers/keystore/KeyStoreServer.cpp (revision 707717e8bec291f31bef0e5ccaa92de5badc6f54)
1 /*
2  * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "KeyStoreServer.h"
8 
9 #include "AppAccessRequestWindow.h"
10 #include "KeyRequestWindow.h"
11 #include "Keyring.h"
12 
13 #include <KeyStoreDefs.h>
14 
15 #include <Directory.h>
16 #include <Entry.h>
17 #include <FindDirectory.h>
18 #include <Path.h>
19 #include <Roster.h>
20 #include <String.h>
21 
22 #include <new>
23 
24 #include <stdio.h>
25 
26 
27 using namespace BPrivate;
28 
29 
30 static const char* kMasterKeyringName = "Master";
31 static const char* kKeyringKeysIdentifier = "Keyrings";
32 
33 static const uint32 kKeyStoreFormatVersion = 1;
34 
35 static const uint32 kFlagGetKey						= 0x0001;
36 static const uint32 kFlagEnumerateKeys				= 0x0002;
37 static const uint32 kFlagAddKey						= 0x0004;
38 static const uint32 kFlagRemoveKey					= 0x0008;
39 static const uint32 kFlagAddKeyring					= 0x0010;
40 static const uint32 kFlagRemoveKeyring				= 0x0020;
41 static const uint32 kFlagEnumerateKeyrings			= 0x0040;
42 static const uint32 kFlagSetUnlockKey				= 0x0080;
43 static const uint32 kFlagRemoveUnlockKey			= 0x0100;
44 static const uint32 kFlagAddKeyringsToMaster		= 0x0200;
45 static const uint32 kFlagRemoveKeyringsFromMaster	= 0x0400;
46 static const uint32 kFlagEnumerateMasterKeyrings	= 0x0800;
47 static const uint32 kFlagQueryLockState				= 0x1000;
48 static const uint32 kFlagLockKeyring				= 0x2000;
49 static const uint32 kFlagEnumerateApplications		= 0x4000;
50 static const uint32 kFlagRemoveApplications			= 0x8000;
51 
52 static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys
53 	| kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring
54 	| kFlagEnumerateKeyrings | kFlagSetUnlockKey | kFlagRemoveUnlockKey
55 	| kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster
56 	| kFlagEnumerateMasterKeyrings | kFlagQueryLockState | kFlagLockKeyring
57 	| kFlagEnumerateApplications | kFlagRemoveApplications;
58 
59 
KeyStoreServer()60 KeyStoreServer::KeyStoreServer()
61 	:
62 	BApplication(kKeyStoreServerSignature),
63 	fMasterKeyring(NULL),
64 	fKeyrings(20, true)
65 {
66 	BPath path;
67 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
68 		return;
69 
70 	BDirectory settingsDir(path.Path());
71 	path.Append("system");
72 	if (!settingsDir.Contains(path.Path()))
73 		settingsDir.CreateDirectory(path.Path(), NULL);
74 
75 	settingsDir.SetTo(path.Path());
76 	path.Append("keystore");
77 	if (!settingsDir.Contains(path.Path()))
78 		settingsDir.CreateDirectory(path.Path(), NULL);
79 
80 	settingsDir.SetTo(path.Path());
81 	path.Append("keystore_database");
82 
83 	fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE
84 		| (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE));
85 
86 	_ReadKeyStoreDatabase();
87 
88 	if (fMasterKeyring == NULL) {
89 		fMasterKeyring = new(std::nothrow) Keyring(kMasterKeyringName);
90 		fKeyrings.BinaryInsert(fMasterKeyring, &Keyring::Compare);
91 	}
92 }
93 
94 
~KeyStoreServer()95 KeyStoreServer::~KeyStoreServer()
96 {
97 }
98 
99 
100 void
MessageReceived(BMessage * message)101 KeyStoreServer::MessageReceived(BMessage* message)
102 {
103 	BMessage reply;
104 	status_t result = B_UNSUPPORTED;
105 	app_info callingAppInfo;
106 
107 	uint32 accessFlags = _AccessFlagsFor(message->what);
108 	if (accessFlags == 0)
109 		message->what = 0;
110 
111 	if (message->what != 0) {
112 		result = _ResolveCallingApp(*message, callingAppInfo);
113 		if (result != B_OK)
114 			message->what = 0;
115 	}
116 
117 	// Resolve the keyring for the relevant messages.
118 	Keyring* keyring = NULL;
119 	switch (message->what) {
120 		case KEY_STORE_GET_KEY:
121 		case KEY_STORE_GET_NEXT_KEY:
122 		case KEY_STORE_ADD_KEY:
123 		case KEY_STORE_REMOVE_KEY:
124 		case KEY_STORE_IS_KEYRING_UNLOCKED:
125 		case KEY_STORE_LOCK_KEYRING:
126 		case KEY_STORE_SET_UNLOCK_KEY:
127 		case KEY_STORE_REMOVE_UNLOCK_KEY:
128 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
129 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
130 		case KEY_STORE_GET_NEXT_APPLICATION:
131 		case KEY_STORE_REMOVE_APPLICATION:
132 		{
133 			BString keyringName;
134 			if (message->FindString("keyring", &keyringName) != B_OK)
135 				keyringName = "";
136 
137 			keyring = _FindKeyring(keyringName);
138 			if (keyring == NULL) {
139 				result = B_BAD_VALUE;
140 				message->what = 0;
141 					// So that we don't do anything in the second switch.
142 				break;
143 			}
144 
145 			switch (message->what) {
146 				case KEY_STORE_GET_KEY:
147 				case KEY_STORE_GET_NEXT_KEY:
148 				case KEY_STORE_ADD_KEY:
149 				case KEY_STORE_REMOVE_KEY:
150 				case KEY_STORE_SET_UNLOCK_KEY:
151 				case KEY_STORE_REMOVE_UNLOCK_KEY:
152 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
153 				case KEY_STORE_GET_NEXT_APPLICATION:
154 				case KEY_STORE_REMOVE_APPLICATION:
155 				{
156 					// These need keyring access to do anything.
157 					while (!keyring->IsUnlocked()) {
158 						status_t unlockResult = _UnlockKeyring(*keyring);
159 						if (unlockResult != B_OK) {
160 							result = unlockResult;
161 							message->what = 0;
162 							break;
163 						}
164 					}
165 
166 					status_t validateResult = _ValidateAppAccess(*keyring,
167 						callingAppInfo, accessFlags);
168 					if (validateResult != B_OK) {
169 						result = validateResult;
170 						message->what = 0;
171 						break;
172 					}
173 
174 					break;
175 				}
176 			}
177 
178 			break;
179 		}
180 	}
181 
182 	switch (message->what) {
183 		case KEY_STORE_GET_KEY:
184 		{
185 			BString identifier;
186 			if (message->FindString("identifier", &identifier) != B_OK) {
187 				result = B_BAD_VALUE;
188 				break;
189 			}
190 
191 			bool secondaryIdentifierOptional;
192 			if (message->FindBool("secondaryIdentifierOptional",
193 					&secondaryIdentifierOptional) != B_OK) {
194 				secondaryIdentifierOptional = false;
195 			}
196 
197 			BString secondaryIdentifier;
198 			if (message->FindString("secondaryIdentifier",
199 					&secondaryIdentifier) != B_OK) {
200 				secondaryIdentifier = "";
201 				secondaryIdentifierOptional = true;
202 			}
203 
204 			BMessage keyMessage;
205 			result = keyring->FindKey(identifier, secondaryIdentifier,
206 				secondaryIdentifierOptional, &keyMessage);
207 			if (result == B_OK)
208 				reply.AddMessage("key", &keyMessage);
209 
210 			break;
211 		}
212 
213 		case KEY_STORE_GET_NEXT_KEY:
214 		{
215 			BKeyType type;
216 			BKeyPurpose purpose;
217 			uint32 cookie;
218 			if (message->FindUInt32("type", (uint32*)&type) != B_OK
219 				|| message->FindUInt32("purpose", (uint32*)&purpose) != B_OK
220 				|| message->FindUInt32("cookie", &cookie) != B_OK) {
221 				result = B_BAD_VALUE;
222 				break;
223 			}
224 
225 			BMessage keyMessage;
226 			result = keyring->FindKey(type, purpose, cookie, keyMessage);
227 			if (result == B_OK) {
228 				cookie++;
229 				reply.AddUInt32("cookie", cookie);
230 				reply.AddMessage("key", &keyMessage);
231 			}
232 
233 			break;
234 		}
235 
236 		case KEY_STORE_ADD_KEY:
237 		{
238 			BMessage keyMessage;
239 			BString identifier;
240 			if (message->FindMessage("key", &keyMessage) != B_OK
241 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
242 				result = B_BAD_VALUE;
243 				break;
244 			}
245 
246 			BString secondaryIdentifier;
247 			if (keyMessage.FindString("secondaryIdentifier",
248 					&secondaryIdentifier) != B_OK) {
249 				secondaryIdentifier = "";
250 			}
251 
252 			result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage);
253 			if (result == B_OK)
254 				_WriteKeyStoreDatabase();
255 
256 			break;
257 		}
258 
259 		case KEY_STORE_REMOVE_KEY:
260 		{
261 			BMessage keyMessage;
262 			BString identifier;
263 			if (message->FindMessage("key", &keyMessage) != B_OK
264 				|| keyMessage.FindString("identifier", &identifier) != B_OK) {
265 				result = B_BAD_VALUE;
266 				break;
267 			}
268 
269 			result = keyring->RemoveKey(identifier, keyMessage);
270 			if (result == B_OK)
271 				_WriteKeyStoreDatabase();
272 
273 			break;
274 		}
275 
276 		case KEY_STORE_ADD_KEYRING:
277 		{
278 			BMessage keyMessage;
279 			BString keyring;
280 			if (message->FindString("keyring", &keyring) != B_OK) {
281 				result = B_BAD_VALUE;
282 				break;
283 			}
284 
285 			result = _AddKeyring(keyring);
286 			if (result == B_OK)
287 				_WriteKeyStoreDatabase();
288 
289 			break;
290 		}
291 
292 		case KEY_STORE_REMOVE_KEYRING:
293 		{
294 			BString keyringName;
295 			if (message->FindString("keyring", &keyringName) != B_OK)
296 				keyringName = "";
297 
298 			result = _RemoveKeyring(keyringName);
299 			if (result == B_OK)
300 				_WriteKeyStoreDatabase();
301 
302 			break;
303 		}
304 
305 		case KEY_STORE_GET_NEXT_KEYRING:
306 		{
307 			uint32 cookie;
308 			if (message->FindUInt32("cookie", &cookie) != B_OK) {
309 				result = B_BAD_VALUE;
310 				break;
311 			}
312 
313 			keyring = fKeyrings.ItemAt(cookie);
314 			if (keyring == NULL) {
315 				result = B_ENTRY_NOT_FOUND;
316 				break;
317 			}
318 
319 			cookie++;
320 			reply.AddUInt32("cookie", cookie);
321 			reply.AddString("keyring", keyring->Name());
322 			result = B_OK;
323 			break;
324 		}
325 
326 		case KEY_STORE_IS_KEYRING_UNLOCKED:
327 		{
328 			reply.AddBool("unlocked", keyring->IsUnlocked());
329 			result = B_OK;
330 			break;
331 		}
332 
333 		case KEY_STORE_LOCK_KEYRING:
334 		{
335 			keyring->Lock();
336 			result = B_OK;
337 			break;
338 		}
339 
340 		case KEY_STORE_SET_UNLOCK_KEY:
341 		{
342 			BMessage keyMessage;
343 			if (message->FindMessage("key", &keyMessage) != B_OK) {
344 				result = B_BAD_VALUE;
345 				break;
346 			}
347 
348 			result = keyring->SetUnlockKey(keyMessage);
349 			if (result == B_OK)
350 				_WriteKeyStoreDatabase();
351 
352 			// TODO: Update the key in the master if this keyring was added.
353 			break;
354 		}
355 
356 		case KEY_STORE_REMOVE_UNLOCK_KEY:
357 		{
358 			result = keyring->RemoveUnlockKey();
359 			if (result == B_OK)
360 				_WriteKeyStoreDatabase();
361 
362 			break;
363 		}
364 
365 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
366 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
367 		{
368 			// We also need access to the master keyring.
369 			while (!fMasterKeyring->IsUnlocked()) {
370 				status_t unlockResult = _UnlockKeyring(*fMasterKeyring);
371 				if (unlockResult != B_OK) {
372 					result = unlockResult;
373 					message->what = 0;
374 					break;
375 				}
376 			}
377 
378 			if (message->what == 0)
379 				break;
380 
381 			BString secondaryIdentifier = keyring->Name();
382 			BMessage keyMessage = keyring->UnlockKey();
383 			keyMessage.RemoveName("identifier");
384 			keyMessage.AddString("identifier", kKeyringKeysIdentifier);
385 			keyMessage.RemoveName("secondaryIdentifier");
386 			keyMessage.AddString("secondaryIdentifier", secondaryIdentifier);
387 
388 			switch (message->what) {
389 				case KEY_STORE_ADD_KEYRING_TO_MASTER:
390 					result = fMasterKeyring->AddKey(kKeyringKeysIdentifier,
391 						secondaryIdentifier, keyMessage);
392 					break;
393 
394 				case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
395 					result = fMasterKeyring->RemoveKey(kKeyringKeysIdentifier,
396 						keyMessage);
397 					break;
398 			}
399 
400 			if (result == B_OK)
401 				_WriteKeyStoreDatabase();
402 
403 			break;
404 		}
405 
406 		case KEY_STORE_GET_NEXT_APPLICATION:
407 		{
408 			uint32 cookie;
409 			if (message->FindUInt32("cookie", &cookie) != B_OK) {
410 				result = B_BAD_VALUE;
411 				break;
412 			}
413 
414 			BString signature;
415 			BString path;
416 			result = keyring->GetNextApplication(cookie, signature, path);
417 			if (result != B_OK)
418 				break;
419 
420 			reply.AddUInt32("cookie", cookie);
421 			reply.AddString("signature", signature);
422 			reply.AddString("path", path);
423 			result = B_OK;
424 			break;
425 		}
426 
427 		case KEY_STORE_REMOVE_APPLICATION:
428 		{
429 			const char* signature = NULL;
430 			const char* path = NULL;
431 
432 			if (message->FindString("signature", &signature) != B_OK) {
433 				result = B_BAD_VALUE;
434 				break;
435 			}
436 
437 			if (message->FindString("path", &path) != B_OK)
438 				path = NULL;
439 
440 			result = keyring->RemoveApplication(signature, path);
441 			if (result == B_OK)
442 				_WriteKeyStoreDatabase();
443 
444 			break;
445 		}
446 
447 		case 0:
448 		{
449 			// Just the error case from above.
450 			break;
451 		}
452 
453 		default:
454 		{
455 			printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n",
456 				message->what, (const char*)&message->what);
457 			break;
458 		}
459 	}
460 
461 	if (message->IsSourceWaiting()) {
462 		if (result == B_OK)
463 			reply.what = KEY_STORE_SUCCESS;
464 		else {
465 			reply.what = KEY_STORE_RESULT;
466 			reply.AddInt32("result", result);
467 		}
468 
469 		message->SendReply(&reply);
470 	}
471 }
472 
473 
474 status_t
_ReadKeyStoreDatabase()475 KeyStoreServer::_ReadKeyStoreDatabase()
476 {
477 	BMessage keystore;
478 	status_t result = keystore.Unflatten(&fKeyStoreFile);
479 	if (result != B_OK) {
480 		printf("failed to read keystore database\n");
481 		_WriteKeyStoreDatabase();
482 			// Reinitializes the database.
483 		return result;
484 	}
485 
486 	int32 index = 0;
487 	BMessage keyringData;
488 	while (keystore.FindMessage("keyrings", index++, &keyringData) == B_OK) {
489 		Keyring* keyring = new(std::nothrow) Keyring();
490 		if (keyring == NULL) {
491 			printf("no memory for allocating keyring\n");
492 			break;
493 		}
494 
495 		status_t result = keyring->ReadFromMessage(keyringData);
496 		if (result != B_OK) {
497 			printf("failed to read keyring from data\n");
498 			delete keyring;
499 			continue;
500 		}
501 
502 		if (strcmp(keyring->Name(), kMasterKeyringName) == 0)
503 			fMasterKeyring = keyring;
504 
505 		fKeyrings.BinaryInsert(keyring, &Keyring::Compare);
506 	}
507 
508 	return B_OK;
509 }
510 
511 
512 status_t
_WriteKeyStoreDatabase()513 KeyStoreServer::_WriteKeyStoreDatabase()
514 {
515 	BMessage keystore;
516 	keystore.AddUInt32("format", kKeyStoreFormatVersion);
517 
518 	for (int32 i = 0; i < fKeyrings.CountItems(); i++) {
519 		Keyring* keyring = fKeyrings.ItemAt(i);
520 		if (keyring == NULL)
521 			continue;
522 
523 		BMessage keyringData;
524 		status_t result = keyring->WriteToMessage(keyringData);
525 		if (result != B_OK)
526 			return result;
527 
528 		keystore.AddMessage("keyrings", &keyringData);
529 	}
530 
531 	fKeyStoreFile.SetSize(0);
532 	fKeyStoreFile.Seek(0, SEEK_SET);
533 	return keystore.Flatten(&fKeyStoreFile);
534 }
535 
536 
537 uint32
_AccessFlagsFor(uint32 command) const538 KeyStoreServer::_AccessFlagsFor(uint32 command) const
539 {
540 	switch (command) {
541 		case KEY_STORE_GET_KEY:
542 			return kFlagGetKey;
543 		case KEY_STORE_GET_NEXT_KEY:
544 			return kFlagEnumerateKeys;
545 		case KEY_STORE_ADD_KEY:
546 			return kFlagAddKey;
547 		case KEY_STORE_REMOVE_KEY:
548 			return kFlagRemoveKey;
549 		case KEY_STORE_ADD_KEYRING:
550 			return kFlagAddKeyring;
551 		case KEY_STORE_REMOVE_KEYRING:
552 			return kFlagRemoveKeyring;
553 		case KEY_STORE_GET_NEXT_KEYRING:
554 			return kFlagEnumerateKeyrings;
555 		case KEY_STORE_SET_UNLOCK_KEY:
556 			return kFlagSetUnlockKey;
557 		case KEY_STORE_REMOVE_UNLOCK_KEY:
558 			return kFlagRemoveUnlockKey;
559 		case KEY_STORE_ADD_KEYRING_TO_MASTER:
560 			return kFlagAddKeyringsToMaster;
561 		case KEY_STORE_REMOVE_KEYRING_FROM_MASTER:
562 			return kFlagRemoveKeyringsFromMaster;
563 		case KEY_STORE_GET_NEXT_MASTER_KEYRING:
564 			return kFlagEnumerateMasterKeyrings;
565 		case KEY_STORE_IS_KEYRING_UNLOCKED:
566 			return kFlagQueryLockState;
567 		case KEY_STORE_LOCK_KEYRING:
568 			return kFlagLockKeyring;
569 		case KEY_STORE_GET_NEXT_APPLICATION:
570 			return kFlagEnumerateApplications;
571 		case KEY_STORE_REMOVE_APPLICATION:
572 			return kFlagRemoveApplications;
573 	}
574 
575 	return 0;
576 }
577 
578 
579 const char*
_AccessStringFor(uint32 accessFlag) const580 KeyStoreServer::_AccessStringFor(uint32 accessFlag) const
581 {
582 	switch (accessFlag) {
583 		case kFlagGetKey:
584 			return "Get keys from the keyring.";
585 		case kFlagEnumerateKeys:
586 			return "Enumerate and get keys from the keyring.";
587 		case kFlagAddKey:
588 			return "Add keys to the keyring.";
589 		case kFlagRemoveKey:
590 			return "Remove keys from the keyring.";
591 		case kFlagAddKeyring:
592 			return "Add new keyrings.";
593 		case kFlagRemoveKeyring:
594 			return "Remove keyrings.";
595 		case kFlagEnumerateKeyrings:
596 			return "Enumerate the available keyrings.";
597 		case kFlagSetUnlockKey:
598 			return "Set the unlock key of the keyring.";
599 		case kFlagRemoveUnlockKey:
600 			return "Remove the unlock key of the keyring.";
601 		case kFlagAddKeyringsToMaster:
602 			return "Add the keyring key to the master keyring.";
603 		case kFlagRemoveKeyringsFromMaster:
604 			return "Remove the keyring key from the master keyring.";
605 		case kFlagEnumerateMasterKeyrings:
606 			return "Enumerate keyrings added to the master keyring.";
607 		case kFlagQueryLockState:
608 			return "Query the lock state of the keyring.";
609 		case kFlagLockKeyring:
610 			return "Lock the keyring.";
611 		case kFlagEnumerateApplications:
612 			return "Enumerate the applications of the keyring.";
613 		case kFlagRemoveApplications:
614 			return "Remove applications from the keyring.";
615 	}
616 
617 	return NULL;
618 }
619 
620 
621 status_t
_ResolveCallingApp(const BMessage & message,app_info & callingAppInfo) const622 KeyStoreServer::_ResolveCallingApp(const BMessage& message,
623 	app_info& callingAppInfo) const
624 {
625 	team_id callingTeam = message.ReturnAddress().Team();
626 	status_t result = be_roster->GetRunningAppInfo(callingTeam,
627 		&callingAppInfo);
628 	if (result != B_OK)
629 		return result;
630 
631 	// Do some sanity checks.
632 	if (callingAppInfo.team != callingTeam)
633 		return B_ERROR;
634 
635 	return B_OK;
636 }
637 
638 
639 status_t
_ValidateAppAccess(Keyring & keyring,const app_info & appInfo,uint32 accessFlags)640 KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo,
641 	uint32 accessFlags)
642 {
643 	BMessage appMessage;
644 	BPath path(&appInfo.ref);
645 	status_t result = keyring.FindApplication(appInfo.signature,
646 		path.Path(), appMessage);
647 	if (result != B_OK && result != B_ENTRY_NOT_FOUND)
648 		return result;
649 
650 	// TODO: Implement running image checksum mechanism.
651 	BString checksum = path.Path();
652 
653 	bool appIsNew = false;
654 	bool appWasUpdated = false;
655 	uint32 appFlags = 0;
656 	BString appSum = "";
657 	if (result == B_OK) {
658 		if (appMessage.FindUInt32("flags", &appFlags) != B_OK
659 			|| appMessage.FindString("checksum", &appSum) != B_OK) {
660 			appIsNew = true;
661 			appFlags = 0;
662 		} else if (appSum != checksum) {
663 			appWasUpdated = true;
664 			appFlags = 0;
665 		}
666 	} else
667 		appIsNew = true;
668 
669 	if ((accessFlags & appFlags) == accessFlags)
670 		return B_OK;
671 
672 	const char* accessString = _AccessStringFor(accessFlags);
673 	bool allowAlways = false;
674 	result = _RequestAppAccess(keyring.Name(), appInfo.signature, path.Path(),
675 		accessString, appIsNew, appWasUpdated, accessFlags, allowAlways);
676 	if (result != B_OK || !allowAlways)
677 		return result;
678 
679 	appMessage.MakeEmpty();
680 	appMessage.AddString("path", path.Path());
681 	appMessage.AddUInt32("flags", appFlags | accessFlags);
682 	appMessage.AddString("checksum", checksum);
683 
684 	keyring.RemoveApplication(appInfo.signature, path.Path());
685 	if (keyring.AddApplication(appInfo.signature, appMessage) == B_OK)
686 		_WriteKeyStoreDatabase();
687 
688 	return B_OK;
689 }
690 
691 
692 status_t
_RequestAppAccess(const BString & keyringName,const char * signature,const char * path,const char * accessString,bool appIsNew,bool appWasUpdated,uint32 accessFlags,bool & allowAlways)693 KeyStoreServer::_RequestAppAccess(const BString& keyringName,
694 	const char* signature, const char* path, const char* accessString,
695 	bool appIsNew, bool appWasUpdated, uint32 accessFlags, bool& allowAlways)
696 {
697 	AppAccessRequestWindow* requestWindow
698 		= new(std::nothrow) AppAccessRequestWindow(keyringName, signature, path,
699 			accessString, appIsNew, appWasUpdated);
700 	if (requestWindow == NULL)
701 		return B_NO_MEMORY;
702 
703 	return requestWindow->RequestAppAccess(allowAlways);
704 }
705 
706 
707 Keyring*
_FindKeyring(const BString & name)708 KeyStoreServer::_FindKeyring(const BString& name)
709 {
710 	if (name.IsEmpty() || name == kMasterKeyringName)
711 		return fMasterKeyring;
712 
713 	return fKeyrings.BinarySearchByKey(name, &Keyring::Compare);
714 }
715 
716 
717 status_t
_AddKeyring(const BString & name)718 KeyStoreServer::_AddKeyring(const BString& name)
719 {
720 	if (_FindKeyring(name) != NULL)
721 		return B_NAME_IN_USE;
722 
723 	Keyring* keyring = new(std::nothrow) Keyring(name);
724 	if (keyring == NULL)
725 		return B_NO_MEMORY;
726 
727 	if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) {
728 		delete keyring;
729 		return B_ERROR;
730 	}
731 
732 	return B_OK;
733 }
734 
735 
736 status_t
_RemoveKeyring(const BString & name)737 KeyStoreServer::_RemoveKeyring(const BString& name)
738 {
739 	Keyring* keyring = _FindKeyring(name);
740 	if (keyring == NULL)
741 		return B_ENTRY_NOT_FOUND;
742 
743 	if (keyring == fMasterKeyring) {
744 		// The master keyring can't be removed.
745 		return B_NOT_ALLOWED;
746 	}
747 
748 	return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR;
749 }
750 
751 
752 status_t
_UnlockKeyring(Keyring & keyring)753 KeyStoreServer::_UnlockKeyring(Keyring& keyring)
754 {
755 	if (!keyring.HasUnlockKey())
756 		return keyring.Unlock(NULL);
757 
758 	// If we are accessing a keyring that has been added to master access we
759 	// get the key from the master keyring and unlock with that.
760 	BMessage keyMessage;
761 	if (&keyring != fMasterKeyring && fMasterKeyring->IsUnlocked()) {
762 		if (fMasterKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(),
763 				false, &keyMessage) == B_OK) {
764 			// We found a key for this keyring, try to unlock with it.
765 			if (keyring.Unlock(&keyMessage) == B_OK)
766 				return B_OK;
767 		}
768 	}
769 
770 	// No key, we need to request one from the user.
771 	status_t result = _RequestKey(keyring.Name(), keyMessage);
772 	if (result != B_OK)
773 		return result;
774 
775 	return keyring.Unlock(&keyMessage);
776 }
777 
778 
779 status_t
_RequestKey(const BString & keyringName,BMessage & keyMessage)780 KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage)
781 {
782 	KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow();
783 	if (requestWindow == NULL)
784 		return B_NO_MEMORY;
785 
786 	return requestWindow->RequestKey(keyringName, keyMessage);
787 }
788 
789 
790 int
main(int argc,char * argv[])791 main(int argc, char* argv[])
792 {
793 	KeyStoreServer* app = new(std::nothrow) KeyStoreServer();
794 	if (app == NULL)
795 		return 1;
796 
797 	app->Run();
798 	delete app;
799 	return 0;
800 }
801