mirror of
https://review.haiku-os.org/haiku
synced 2025-02-22 21:48:35 +01:00
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:
parent
5d4a0da455
commit
ac9b28f058
@ -3,6 +3,7 @@ SubDir HAIKU_TOP src servers keystore ;
|
||||
UsePrivateHeaders app ;
|
||||
|
||||
Server keystore_server :
|
||||
KeyRequestWindow.cpp
|
||||
Keyring.cpp
|
||||
KeyStoreServer.cpp
|
||||
|
||||
|
212
src/servers/keystore/KeyRequestWindow.cpp
Normal file
212
src/servers/keystore/KeyRequestWindow.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2012, Michael Lotz, mmlr@mlotz.ch. 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;
|
||||
}
|
34
src/servers/keystore/KeyRequestWindow.h
Normal file
34
src/servers/keystore/KeyRequestWindow.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012, Michael Lotz, mmlr@mlotz.ch. 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 "KeyRequestWindow.h"
|
||||
#include "Keyring.h"
|
||||
|
||||
#include <KeyStoreDefs.h>
|
||||
@ -89,6 +91,24 @@ KeyStoreServer::MessageReceived(BMessage* message)
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -247,6 +267,12 @@ KeyStoreServer::MessageReceived(BMessage* message)
|
||||
result = B_OK;
|
||||
}
|
||||
|
||||
case KEY_STORE_REVOKE_ACCESS:
|
||||
{
|
||||
keyring->RevokeAccess();
|
||||
result = B_OK;
|
||||
}
|
||||
|
||||
case 0:
|
||||
{
|
||||
// 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
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
|
@ -34,6 +34,10 @@ private:
|
||||
const BMessage& keyMessage);
|
||||
status_t _RemoveKeyring(const BString& name);
|
||||
|
||||
status_t _AccessKeyring(Keyring& keyring);
|
||||
|
||||
status_t _RequestKey(BMessage& keyMessage);
|
||||
|
||||
Keyring* fDefaultKeyring;
|
||||
KeyringList fKeyrings;
|
||||
BFile fKeyStoreFile;
|
||||
|
@ -10,7 +10,8 @@
|
||||
Keyring::Keyring(const char* name, const BMessage& data)
|
||||
:
|
||||
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
|
||||
Keyring::IsAccessible()
|
||||
{
|
||||
return true;
|
||||
return fAccessible;
|
||||
}
|
||||
|
||||
|
||||
@ -31,6 +47,9 @@ status_t
|
||||
Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier,
|
||||
bool secondaryIdentifierOptional, BMessage* _foundKeyMessage)
|
||||
{
|
||||
if (!fAccessible)
|
||||
return B_NOT_ALLOWED;
|
||||
|
||||
int32 count;
|
||||
type_code type;
|
||||
if (fData.GetInfo(identifier, &type, &count) != B_OK)
|
||||
@ -74,6 +93,9 @@ status_t
|
||||
Keyring::FindKey(BKeyType type, BKeyPurpose purpose, uint32 index,
|
||||
BMessage& _foundKeyMessage)
|
||||
{
|
||||
if (!fAccessible)
|
||||
return B_NOT_ALLOWED;
|
||||
|
||||
for (int32 keyIndex = 0;; keyIndex++) {
|
||||
int32 count = 0;
|
||||
char* identifier = NULL;
|
||||
@ -136,6 +158,9 @@ status_t
|
||||
Keyring::AddKey(const BString& identifier, const BString& secondaryIdentifier,
|
||||
const BMessage& keyMessage)
|
||||
{
|
||||
if (!fAccessible)
|
||||
return B_NOT_ALLOWED;
|
||||
|
||||
// Check for collisions.
|
||||
if (FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK)
|
||||
return B_NAME_IN_USE;
|
||||
@ -149,6 +174,9 @@ status_t
|
||||
Keyring::RemoveKey(const BString& identifier,
|
||||
const BMessage& keyMessage)
|
||||
{
|
||||
if (!fAccessible)
|
||||
return B_NOT_ALLOWED;
|
||||
|
||||
int32 count;
|
||||
type_code type;
|
||||
if (fData.GetInfo(identifier, &type, &count) != B_OK)
|
||||
|
@ -19,6 +19,8 @@ public:
|
||||
const char* Name() const { return fName; }
|
||||
const BMessage& Data() const { return fData; }
|
||||
|
||||
status_t Access(const BMessage& keyMessage);
|
||||
void RevokeAccess();
|
||||
bool IsAccessible();
|
||||
|
||||
status_t FindKey(const BString& identifier,
|
||||
@ -43,6 +45,7 @@ static int Compare(const BString* name,
|
||||
private:
|
||||
BString fName;
|
||||
BMessage fData;
|
||||
bool fAccessible;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user