Implement basic storage and lookup functions.
* Add reading/writing a yet unprotected flat BMessage as the storage backend for the keys. * Factor out the identifier based lookup logic into _FindKey() and use that from _AddKey() to detect duplicates. * Add _FindKey() variant that does the lookup based on given type and purpose constraints.
This commit is contained in:
committed by
Ryan Leavengood
parent
37ac7cb2de
commit
0dfaf59dbb
@@ -8,6 +8,12 @@
|
|||||||
|
|
||||||
#include <KeyStoreDefs.h>
|
#include <KeyStoreDefs.h>
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -20,7 +26,27 @@ KeyStoreServer::KeyStoreServer()
|
|||||||
:
|
:
|
||||||
BApplication(kKeyStoreServerSignature)
|
BApplication(kKeyStoreServerSignature)
|
||||||
{
|
{
|
||||||
_InitKeyStoreDatabase();
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BDirectory settingsDir(path.Path());
|
||||||
|
path.Append("system");
|
||||||
|
if (!settingsDir.Contains(path.Path()))
|
||||||
|
settingsDir.CreateDirectory(path.Path(), NULL);
|
||||||
|
|
||||||
|
settingsDir.SetTo(path.Path());
|
||||||
|
path.Append("keystore");
|
||||||
|
if (!settingsDir.Contains(path.Path()))
|
||||||
|
settingsDir.CreateDirectory(path.Path(), NULL);
|
||||||
|
|
||||||
|
settingsDir.SetTo(path.Path());
|
||||||
|
path.Append("keystore_database");
|
||||||
|
|
||||||
|
fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE
|
||||||
|
| (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE));
|
||||||
|
|
||||||
|
_ReadKeyStoreDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -32,20 +58,56 @@ KeyStoreServer::~KeyStoreServer()
|
|||||||
void
|
void
|
||||||
KeyStoreServer::MessageReceived(BMessage* message)
|
KeyStoreServer::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
|
BMessage reply;
|
||||||
|
status_t result = B_MESSAGE_NOT_UNDERSTOOD;
|
||||||
|
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case KEY_STORE_GET_KEY:
|
case KEY_STORE_GET_KEY:
|
||||||
{
|
{
|
||||||
BMessage reply(KEY_STORE_RESULT);
|
result = B_NOT_ALLOWED;
|
||||||
reply.AddInt32("result", B_NOT_ALLOWED);
|
|
||||||
message->SendReply(&reply);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case KEY_STORE_GET_NEXT_KEY:
|
case KEY_STORE_GET_NEXT_KEY:
|
||||||
{
|
{
|
||||||
BMessage reply(KEY_STORE_RESULT);
|
BKeyType type;
|
||||||
reply.AddInt32("result", B_ENTRY_NOT_FOUND);
|
BKeyPurpose purpose;
|
||||||
message->SendReply(&reply);
|
uint32 cookie;
|
||||||
|
if (message->FindUInt32("type", (uint32*)&type) != B_OK
|
||||||
|
|| message->FindUInt32("purpose", (uint32*)&purpose) != B_OK
|
||||||
|
|| message->FindUInt32("cookie", &cookie) != B_OK) {
|
||||||
|
result = B_BAD_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessage keyMessage;
|
||||||
|
result = _FindKey(type, purpose, cookie, keyMessage);
|
||||||
|
if (result == B_OK) {
|
||||||
|
cookie++;
|
||||||
|
reply.AddUInt32("cookie", cookie);
|
||||||
|
reply.AddMessage("key", &keyMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case KEY_STORE_ADD_KEY:
|
||||||
|
{
|
||||||
|
BMessage keyMessage;
|
||||||
|
BString identifier;
|
||||||
|
if (message->FindMessage("key", &keyMessage) != B_OK
|
||||||
|
|| keyMessage.FindString("identifier", &identifier) != B_OK) {
|
||||||
|
result = B_BAD_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BString secondaryIdentifier;
|
||||||
|
if (keyMessage.FindString("secondaryIdentifier",
|
||||||
|
&secondaryIdentifier) != B_OK) {
|
||||||
|
secondaryIdentifier = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
result = _AddKey(identifier, secondaryIdentifier, keyMessage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +119,17 @@ KeyStoreServer::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message->IsSourceWaiting()) {
|
||||||
|
if (result == B_OK)
|
||||||
|
reply.what = KEY_STORE_SUCCESS;
|
||||||
|
else {
|
||||||
|
reply.what = KEY_STORE_RESULT;
|
||||||
|
reply.AddInt32("result", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
message->SendReply(&reply);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Get thread info that contains our team ID for replying.
|
// Get thread info that contains our team ID for replying.
|
||||||
thread_info threadInfo;
|
thread_info threadInfo;
|
||||||
@@ -360,9 +433,146 @@ KeyStoreServer::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
KeyStoreServer::_InitKeyStoreDatabase()
|
KeyStoreServer::_ReadKeyStoreDatabase()
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
status_t result = fDatabase.Unflatten(&fKeyStoreFile);
|
||||||
|
if (result != B_OK) {
|
||||||
|
printf("failed to read keystore database\n");
|
||||||
|
fDatabase.MakeEmpty();
|
||||||
|
_WriteKeyStoreDatabase();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyStoreServer::_WriteKeyStoreDatabase()
|
||||||
|
{
|
||||||
|
fKeyStoreFile.SetSize(0);
|
||||||
|
fKeyStoreFile.Seek(0, SEEK_SET);
|
||||||
|
return fDatabase.Flatten(&fKeyStoreFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyStoreServer::_FindKey(const BString& identifier,
|
||||||
|
const BString& secondaryIdentifier, bool secondaryIdentifierOptional,
|
||||||
|
BMessage* _foundKeyMessage)
|
||||||
|
{
|
||||||
|
int32 count;
|
||||||
|
type_code type;
|
||||||
|
if (fDatabase.GetInfo(identifier, &type, &count) != B_OK)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
// We have a matching primary identifier, need to check for the secondary
|
||||||
|
// identifier.
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
BMessage candidate;
|
||||||
|
if (fDatabase.FindMessage(identifier, i, &candidate) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
BString candidateIdentifier;
|
||||||
|
if (candidate.FindString("secondaryIdentifier",
|
||||||
|
&candidateIdentifier) != B_OK) {
|
||||||
|
candidateIdentifier = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidateIdentifier == secondaryIdentifier) {
|
||||||
|
if (_foundKeyMessage != NULL)
|
||||||
|
*_foundKeyMessage = candidate;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We didn't find an exact match.
|
||||||
|
if (secondaryIdentifierOptional) {
|
||||||
|
if (_foundKeyMessage == NULL)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
// The secondary identifier is optional, so we just return the
|
||||||
|
// first entry.
|
||||||
|
return fDatabase.FindMessage(identifier, 0, _foundKeyMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyStoreServer::_FindKey(BKeyType type, BKeyPurpose purpose, uint32 index,
|
||||||
|
BMessage& _foundKeyMessage)
|
||||||
|
{
|
||||||
|
for (int32 keyIndex = 0;; keyIndex++) {
|
||||||
|
int32 count = 0;
|
||||||
|
char* identifier = NULL;
|
||||||
|
if (fDatabase.GetInfo(B_MESSAGE_TYPE, keyIndex, &identifier, NULL,
|
||||||
|
&count) != B_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == B_KEY_TYPE_ANY && purpose == B_KEY_PURPOSE_ANY) {
|
||||||
|
// No need to inspect the actual keys.
|
||||||
|
if ((int32)index >= count) {
|
||||||
|
index -= count;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fDatabase.FindMessage(identifier, index, &_foundKeyMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through the keys to check their type and purpose.
|
||||||
|
for (int32 subkeyIndex = 0; subkeyIndex < count; subkeyIndex++) {
|
||||||
|
BMessage subkey;
|
||||||
|
if (fDatabase.FindMessage(identifier, subkeyIndex, &subkey) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
bool match = true;
|
||||||
|
if (type != B_KEY_TYPE_ANY) {
|
||||||
|
BKeyType subkeyType;
|
||||||
|
if (subkey.FindUInt32("type", (uint32*)&subkeyType) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
match = subkeyType == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match && purpose != B_KEY_PURPOSE_ANY) {
|
||||||
|
BKeyPurpose subkeyPurpose;
|
||||||
|
if (subkey.FindUInt32("purpose", (uint32*)&subkeyPurpose)
|
||||||
|
!= B_OK) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = subkeyPurpose == purpose;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
if (index == 0) {
|
||||||
|
_foundKeyMessage = subkey;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyStoreServer::_AddKey(const BString& identifier,
|
||||||
|
const BString& secondaryIdentifier, const BMessage& keyMessage)
|
||||||
|
{
|
||||||
|
// Check for collisions.
|
||||||
|
if (_FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK)
|
||||||
|
return B_NAME_IN_USE;
|
||||||
|
|
||||||
|
// We're fine, just add the new key.
|
||||||
|
fDatabase.AddMessage(identifier, &keyMessage);
|
||||||
|
return _WriteKeyStoreDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <Key.h>
|
||||||
|
|
||||||
|
|
||||||
class KeyStoreServer : public BApplication {
|
class KeyStoreServer : public BApplication {
|
||||||
@@ -17,7 +19,23 @@ virtual ~KeyStoreServer();
|
|||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _InitKeyStoreDatabase();
|
status_t _ReadKeyStoreDatabase();
|
||||||
|
status_t _WriteKeyStoreDatabase();
|
||||||
|
|
||||||
|
status_t _FindKey(const BString& identifier,
|
||||||
|
const BString& secondaryIdentifier,
|
||||||
|
bool secondaryIdentifierOptional,
|
||||||
|
BMessage* _foundKeyMessage);
|
||||||
|
status_t _FindKey(BKeyType type, BKeyPurpose purpose,
|
||||||
|
uint32 index,
|
||||||
|
BMessage& _foundKeyMessage);
|
||||||
|
|
||||||
|
status_t _AddKey(const BString& identifier,
|
||||||
|
const BString& secondaryIdentifier,
|
||||||
|
const BMessage& keyMessage);
|
||||||
|
|
||||||
|
BMessage fDatabase;
|
||||||
|
BFile fKeyStoreFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user