Implement basic keyring access logic and key request dialog.
* The keyring needs to be made accessible before allowing any operation. * Before executing commands the keyring is made accessible if possible (the command is aborted as needed). * Accessing a keyring opens up a preliminary key request dialog. * If the default keyring is accessible and a keyring key for the requested keyring is found, that key will be used to automatically make the requested keyring accessible.
This commit is contained in:
committed by
Ryan Leavengood
parent
5d4a0da455
commit
ac9b28f058
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src servers keystore ;
|
|||||||
UsePrivateHeaders app ;
|
UsePrivateHeaders app ;
|
||||||
|
|
||||||
Server keystore_server :
|
Server keystore_server :
|
||||||
|
KeyRequestWindow.cpp
|
||||||
Keyring.cpp
|
Keyring.cpp
|
||||||
KeyStoreServer.cpp
|
KeyStoreServer.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Michael Lotz, [email protected]. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "KeyRequestWindow.h"
|
||||||
|
|
||||||
|
#include <Button.h>
|
||||||
|
#include <CheckBox.h>
|
||||||
|
#include <GridLayout.h>
|
||||||
|
#include <GridView.h>
|
||||||
|
#include <GroupLayout.h>
|
||||||
|
#include <GroupView.h>
|
||||||
|
#include <MenuField.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <NetworkDevice.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
|
#include <SpaceLayoutItem.h>
|
||||||
|
#include <TextControl.h>
|
||||||
|
#include <View.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kMessageCancel = 'btcl';
|
||||||
|
static const uint32 kMessageOk = 'btok';
|
||||||
|
|
||||||
|
|
||||||
|
class KeyRequestView : public BView {
|
||||||
|
public:
|
||||||
|
KeyRequestView()
|
||||||
|
:
|
||||||
|
BView("KeyRequestView", B_WILL_DRAW),
|
||||||
|
fPassword(NULL)
|
||||||
|
{
|
||||||
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
|
||||||
|
BGroupLayout* rootLayout = new(std::nothrow) BGroupLayout(B_VERTICAL);
|
||||||
|
if (rootLayout == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetLayout(rootLayout);
|
||||||
|
|
||||||
|
BGridView* controls = new(std::nothrow) BGridView();
|
||||||
|
if (controls == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BGridLayout* layout = controls->GridLayout();
|
||||||
|
|
||||||
|
float inset = ceilf(be_plain_font->Size() * 0.7);
|
||||||
|
rootLayout->SetInsets(inset, inset, inset, inset);
|
||||||
|
rootLayout->SetSpacing(inset);
|
||||||
|
layout->SetSpacing(inset, inset);
|
||||||
|
|
||||||
|
fKeyringName = new(std::nothrow) BTextControl("Keyring:", "", NULL);
|
||||||
|
if (fKeyringName == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 row = 0;
|
||||||
|
layout->AddItem(fKeyringName->CreateLabelLayoutItem(), 0, row);
|
||||||
|
layout->AddItem(fKeyringName->CreateTextViewLayoutItem(), 1, row++);
|
||||||
|
|
||||||
|
fPassword = new(std::nothrow) BTextControl("Password:", "", NULL);
|
||||||
|
if (fPassword == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BLayoutItem* layoutItem = fPassword->CreateTextViewLayoutItem();
|
||||||
|
layoutItem->SetExplicitMinSize(BSize(fPassword->StringWidth(
|
||||||
|
"0123456789012345678901234567890123456789") + inset,
|
||||||
|
B_SIZE_UNSET));
|
||||||
|
|
||||||
|
layout->AddItem(fPassword->CreateLabelLayoutItem(), 0, row);
|
||||||
|
layout->AddItem(layoutItem, 1, row++);
|
||||||
|
|
||||||
|
fPersist = new(std::nothrow) BCheckBox("Not yet");
|
||||||
|
layout->AddItem(BSpaceLayoutItem::CreateGlue(), 0, row);
|
||||||
|
layout->AddView(fPersist, 1, row++);
|
||||||
|
|
||||||
|
BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL);
|
||||||
|
if (buttons == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fCancelButton = new(std::nothrow) BButton("Cancel",
|
||||||
|
new BMessage(kMessageCancel));
|
||||||
|
buttons->GroupLayout()->AddView(fCancelButton);
|
||||||
|
|
||||||
|
buttons->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
|
||||||
|
|
||||||
|
fOkButton = new(std::nothrow) BButton("OK", new BMessage(kMessageOk));
|
||||||
|
buttons->GroupLayout()->AddView(fOkButton);
|
||||||
|
|
||||||
|
rootLayout->AddView(controls);
|
||||||
|
rootLayout->AddView(buttons);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
AttachedToWindow()
|
||||||
|
{
|
||||||
|
fCancelButton->SetTarget(Window());
|
||||||
|
fOkButton->SetTarget(Window());
|
||||||
|
fOkButton->MakeDefault(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUp(const BMessage& keyMessage)
|
||||||
|
{
|
||||||
|
BString keyringName;
|
||||||
|
if (keyMessage.FindString("keyring", &keyringName) == B_OK)
|
||||||
|
fKeyringName->SetText(keyringName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Complete(BMessage& keyMessage)
|
||||||
|
{
|
||||||
|
keyMessage.RemoveName("password");
|
||||||
|
keyMessage.AddString("password", fPassword->Text());
|
||||||
|
|
||||||
|
keyMessage.RemoveName("persistent");
|
||||||
|
keyMessage.AddBool("persistent", fPersist->Value() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BTextControl* fKeyringName;
|
||||||
|
BTextControl* fPassword;
|
||||||
|
BCheckBox* fPersist;
|
||||||
|
BButton* fCancelButton;
|
||||||
|
BButton* fOkButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
KeyRequestWindow::KeyRequestWindow()
|
||||||
|
:
|
||||||
|
BWindow(BRect(50, 50, 269, 302), "Access Keyring",
|
||||||
|
B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS
|
||||||
|
| B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
|
||||||
|
fRequestView(NULL),
|
||||||
|
fDoneSem(-1),
|
||||||
|
fResult(B_ERROR)
|
||||||
|
{
|
||||||
|
fDoneSem = create_sem(0, "keyring access dialog");
|
||||||
|
if (fDoneSem < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BLayout* layout = new(std::nothrow) BGroupLayout(B_HORIZONTAL);
|
||||||
|
if (layout == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetLayout(layout);
|
||||||
|
|
||||||
|
fRequestView = new(std::nothrow) KeyRequestView();
|
||||||
|
if (fRequestView == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
layout->AddView(fRequestView);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KeyRequestWindow::~KeyRequestWindow()
|
||||||
|
{
|
||||||
|
if (fDoneSem >= 0)
|
||||||
|
delete_sem(fDoneSem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyRequestWindow::DispatchMessage(BMessage* message, BHandler* handler)
|
||||||
|
{
|
||||||
|
int8 key;
|
||||||
|
if (message->what == B_KEY_DOWN
|
||||||
|
&& message->FindInt8("byte", 0, &key) == B_OK
|
||||||
|
&& key == B_ESCAPE) {
|
||||||
|
PostMessage(kMessageCancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
BWindow::DispatchMessage(message, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyRequestWindow::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMessageCancel:
|
||||||
|
case kMessageOk:
|
||||||
|
fResult = message->what == kMessageOk ? B_OK : B_CANCELED;
|
||||||
|
release_sem(fDoneSem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyRequestWindow::RequestKey(BMessage& keyMessage)
|
||||||
|
{
|
||||||
|
fRequestView->SetUp(keyMessage);
|
||||||
|
|
||||||
|
CenterOnScreen();
|
||||||
|
Show();
|
||||||
|
|
||||||
|
while (acquire_sem(fDoneSem) == B_INTERRUPTED)
|
||||||
|
;
|
||||||
|
|
||||||
|
status_t result = fResult;
|
||||||
|
fRequestView->Complete(keyMessage);
|
||||||
|
|
||||||
|
LockLooper();
|
||||||
|
Quit();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Michael Lotz, [email protected]. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KEY_REQUEST_WINDOW_H
|
||||||
|
#define _KEY_REQUEST_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Message.h>
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
|
class KeyRequestView;
|
||||||
|
|
||||||
|
|
||||||
|
class KeyRequestWindow : public BWindow {
|
||||||
|
public:
|
||||||
|
KeyRequestWindow();
|
||||||
|
virtual ~KeyRequestWindow();
|
||||||
|
|
||||||
|
virtual void DispatchMessage(BMessage* message,
|
||||||
|
BHandler* handler);
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
status_t RequestKey(BMessage& keyMessage);
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeyRequestView* fRequestView;
|
||||||
|
sem_id fDoneSem;
|
||||||
|
status_t fResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _KEY_REQUEST_WINDOW_H
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "KeyStoreServer.h"
|
#include "KeyStoreServer.h"
|
||||||
|
|
||||||
|
#include "KeyRequestWindow.h"
|
||||||
#include "Keyring.h"
|
#include "Keyring.h"
|
||||||
|
|
||||||
#include <KeyStoreDefs.h>
|
#include <KeyStoreDefs.h>
|
||||||
@@ -89,6 +91,24 @@ KeyStoreServer::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (message->what) {
|
||||||
|
case KEY_STORE_GET_KEY:
|
||||||
|
case KEY_STORE_GET_NEXT_KEY:
|
||||||
|
case KEY_STORE_ADD_KEY:
|
||||||
|
case KEY_STORE_REMOVE_KEY:
|
||||||
|
{
|
||||||
|
// These need keyring access to do anything.
|
||||||
|
while (!keyring->IsAccessible()) {
|
||||||
|
status_t accessResult = _AccessKeyring(*keyring);
|
||||||
|
if (accessResult != B_OK) {
|
||||||
|
result = accessResult;
|
||||||
|
message->what = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,6 +267,12 @@ KeyStoreServer::MessageReceived(BMessage* message)
|
|||||||
result = B_OK;
|
result = B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case KEY_STORE_REVOKE_ACCESS:
|
||||||
|
{
|
||||||
|
keyring->RevokeAccess();
|
||||||
|
result = B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
// Just the error case from above.
|
// Just the error case from above.
|
||||||
@@ -380,6 +406,42 @@ KeyStoreServer::_RemoveKeyring(const BString& name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyStoreServer::_AccessKeyring(Keyring& keyring)
|
||||||
|
{
|
||||||
|
// If we are accessing a keyring that has been added to master access we
|
||||||
|
// get the key from the default keyring and unlock with that.
|
||||||
|
BMessage keyMessage;
|
||||||
|
if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) {
|
||||||
|
if (fDefaultKeyring->FindKey("Keyrings", keyring.Name(), false,
|
||||||
|
&keyMessage) == B_OK) {
|
||||||
|
// We found a key for this keyring, try to access with it.
|
||||||
|
if (keyring.Access(keyMessage) == B_OK)
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No key, we need to request one from the user.
|
||||||
|
keyMessage.AddString("keyring", keyring.Name());
|
||||||
|
status_t result = _RequestKey(keyMessage);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return keyring.Access(keyMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyStoreServer::_RequestKey(BMessage& keyMessage)
|
||||||
|
{
|
||||||
|
KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow();
|
||||||
|
if (requestWindow == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
return requestWindow->RequestKey(keyMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char* argv[])
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ private:
|
|||||||
const BMessage& keyMessage);
|
const BMessage& keyMessage);
|
||||||
status_t _RemoveKeyring(const BString& name);
|
status_t _RemoveKeyring(const BString& name);
|
||||||
|
|
||||||
|
status_t _AccessKeyring(Keyring& keyring);
|
||||||
|
|
||||||
|
status_t _RequestKey(BMessage& keyMessage);
|
||||||
|
|
||||||
Keyring* fDefaultKeyring;
|
Keyring* fDefaultKeyring;
|
||||||
KeyringList fKeyrings;
|
KeyringList fKeyrings;
|
||||||
BFile fKeyStoreFile;
|
BFile fKeyStoreFile;
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
Keyring::Keyring(const char* name, const BMessage& data)
|
Keyring::Keyring(const char* name, const BMessage& data)
|
||||||
:
|
:
|
||||||
fName(name),
|
fName(name),
|
||||||
fData(data)
|
fData(data),
|
||||||
|
fAccessible(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,10 +21,25 @@ Keyring::~Keyring()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Keyring::Access(const BMessage& keyMessage)
|
||||||
|
{
|
||||||
|
fAccessible = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Keyring::RevokeAccess()
|
||||||
|
{
|
||||||
|
fAccessible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Keyring::IsAccessible()
|
Keyring::IsAccessible()
|
||||||
{
|
{
|
||||||
return true;
|
return fAccessible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -31,6 +47,9 @@ status_t
|
|||||||
Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier,
|
Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier,
|
||||||
bool secondaryIdentifierOptional, BMessage* _foundKeyMessage)
|
bool secondaryIdentifierOptional, BMessage* _foundKeyMessage)
|
||||||
{
|
{
|
||||||
|
if (!fAccessible)
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
int32 count;
|
int32 count;
|
||||||
type_code type;
|
type_code type;
|
||||||
if (fData.GetInfo(identifier, &type, &count) != B_OK)
|
if (fData.GetInfo(identifier, &type, &count) != B_OK)
|
||||||
@@ -74,6 +93,9 @@ status_t
|
|||||||
Keyring::FindKey(BKeyType type, BKeyPurpose purpose, uint32 index,
|
Keyring::FindKey(BKeyType type, BKeyPurpose purpose, uint32 index,
|
||||||
BMessage& _foundKeyMessage)
|
BMessage& _foundKeyMessage)
|
||||||
{
|
{
|
||||||
|
if (!fAccessible)
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
for (int32 keyIndex = 0;; keyIndex++) {
|
for (int32 keyIndex = 0;; keyIndex++) {
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
char* identifier = NULL;
|
char* identifier = NULL;
|
||||||
@@ -136,6 +158,9 @@ status_t
|
|||||||
Keyring::AddKey(const BString& identifier, const BString& secondaryIdentifier,
|
Keyring::AddKey(const BString& identifier, const BString& secondaryIdentifier,
|
||||||
const BMessage& keyMessage)
|
const BMessage& keyMessage)
|
||||||
{
|
{
|
||||||
|
if (!fAccessible)
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
// Check for collisions.
|
// Check for collisions.
|
||||||
if (FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK)
|
if (FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK)
|
||||||
return B_NAME_IN_USE;
|
return B_NAME_IN_USE;
|
||||||
@@ -149,6 +174,9 @@ status_t
|
|||||||
Keyring::RemoveKey(const BString& identifier,
|
Keyring::RemoveKey(const BString& identifier,
|
||||||
const BMessage& keyMessage)
|
const BMessage& keyMessage)
|
||||||
{
|
{
|
||||||
|
if (!fAccessible)
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
int32 count;
|
int32 count;
|
||||||
type_code type;
|
type_code type;
|
||||||
if (fData.GetInfo(identifier, &type, &count) != B_OK)
|
if (fData.GetInfo(identifier, &type, &count) != B_OK)
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public:
|
|||||||
const char* Name() const { return fName; }
|
const char* Name() const { return fName; }
|
||||||
const BMessage& Data() const { return fData; }
|
const BMessage& Data() const { return fData; }
|
||||||
|
|
||||||
|
status_t Access(const BMessage& keyMessage);
|
||||||
|
void RevokeAccess();
|
||||||
bool IsAccessible();
|
bool IsAccessible();
|
||||||
|
|
||||||
status_t FindKey(const BString& identifier,
|
status_t FindKey(const BString& identifier,
|
||||||
@@ -43,6 +45,7 @@ static int Compare(const BString* name,
|
|||||||
private:
|
private:
|
||||||
BString fName;
|
BString fName;
|
||||||
BMessage fData;
|
BMessage fData;
|
||||||
|
bool fAccessible;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user