Allow to change key expiry date.

Select new date in a popup. Controlled by a specific configuration flag.
This commit is contained in:
SET
2020-11-07 22:17:44 +01:00
parent fcd595d530
commit 2bddf29596
17 changed files with 328 additions and 7 deletions

View File

@@ -31,6 +31,7 @@ using namespace std;
"canDelete" : true,
"canEditOwnerTrust" : true,
"canEditUidValidity" : true,
"canEditExpiryTime" : true,
"privKeyIds" : [
"fullKeyId1",
"fullKeyId2"
@@ -141,6 +142,20 @@ bool AppConfig::CanEditUidValidity() const
return cnObject.get("canEditUidValidity");
}
bool AppConfig::CanEditExpiryTime() const
{
if (PrivateKeyIds().size() == 0)
return false;
const WString commonName = GetSubjectDnAttribute(WSslCertificate::DnAttributeName::CommonName);
if (!m_SubjectCNObject.contains(commonName.toUTF8()))
return false;
Json::Object cnObject = m_SubjectCNObject.get(commonName.toUTF8());
if (!cnObject.contains("canEditExpiryTime"))
return false;
return cnObject.get("canEditExpiryTime");
}
vector<WString> AppConfig::PrivateKeyIds() const
{
// List private key identifiers.

View File

@@ -54,6 +54,12 @@ public:
* @return
*/
bool CanEditUidValidity() const;
/**
* Allows to edit expiry time of a key.
* Only private keys are concerned.
* @return
*/
bool CanEditExpiryTime() const;
/**
* List of full private key identifiers. The user may delete these private keys.
* Must be full keyid, short keyid or fingerprint.

View File

@@ -133,3 +133,30 @@ const Error GpgMEWorker::CertifyKey(const char* fprSigningKey,
*/
return e;
}
const Error GpgMEWorker::SetExpiryTime(const char * keyFpr,
const string& passphrase,
const string& timeString)
{
Error e;
Key k = FindKey(keyFpr, e, true);
if (e.code() != 0)
return e;
e = m_ctx->addSigningKey(k); // +++
if (e.code() != 0)
return e;
m_ctx->setPinentryMode(Context::PinentryMode::PinentryLoopback);
if (m_ppp == NULL)
m_ppp = new LoopbackPassphraseProvider();
m_ppp->SetPassphrase(passphrase);
m_ctx->setPassphraseProvider(m_ppp);
SetExpiryTimeEditInteractor * interactor
= new SetExpiryTimeEditInteractor(timeString);
GpgME::Data d;
e = m_ctx->edit(k, std::unique_ptr<SetExpiryTimeEditInteractor> (interactor), d);
m_ctx->clearSigningKeys();
return e;
}

View File

@@ -15,6 +15,7 @@
#include <gpgme++/key.h>
#include <gpgme++/gpgsetownertrusteditinteractor.h>
#include <gpgme++/gpgsignkeyeditinteractor.h>
#include <gpgme++/gpgsetexpirytimeeditinteractor.h>
#include <vector>
#include "LoopbackPassphraseProvider.h"
@@ -75,6 +76,14 @@ public:
const char * fprKeyToSign,
vector<uint>& userIDsToSign, int options,
const string& passphrase);
/**
* Set new expiry time of a secret key.
* @param timeString
* @return
*/
const Error SetExpiryTime(const char * keyFpr,
const string& passphrase,
const string& timeString = "0");
private:
Context * m_ctx;
@@ -121,5 +130,18 @@ public:
};
class SetExpiryTimeEditInteractor : public GpgSetExpiryTimeEditInteractor
{
public:
SetExpiryTimeEditInteractor(const std::string& timeString = "0")
: GpgSetExpiryTimeEditInteractor(timeString)
{
};
virtual ~SetExpiryTimeEditInteractor()
{
};
};
#endif /* GPGMEWORKER_H */

View File

@@ -376,6 +376,9 @@ void K7Main::DisplaySubKeys(const WString& fullKeyID, bool secret)
rootNode->setChildCountPolicy(ChildCountPolicy::Enabled);
m_ttbSubKeys->setTreeRoot(unique_ptr<WTreeTableNode> (rootNode), TR("SubKeys"));
rootNode->expand();
bool canEditExpiry = m_config->CanEditExpiryTime()
&& Tools::KeyHasSecret(k.primaryFingerprint())
&& m_keyEdit->IsOurKey(k.primaryFingerprint());
for (uint i = 0; i < k.numSubkeys(); i++)
{
Subkey sk = k.subkey(i);
@@ -384,7 +387,12 @@ void K7Main::DisplaySubKeys(const WString& fullKeyID, bool secret)
TreeTableNodeText * ttntFpr = new TreeTableNodeText(sk.fingerprint(), skNode, 1);
skNode->setColumnWidget(1, unique_ptr<TreeTableNodeText> (ttntFpr));
WString exp = sk.neverExpires() ? TR("Never") : MakeDateTimeLabel(sk.expirationTime());
skNode->setColumnWidget(2, cpp14::make_unique<WText> (exp));
WText * lblExpiry = new WText(exp);
if (canEditExpiry) {
lblExpiry->setToolTip(TR("TTTDoubleCLick"));
lblExpiry->doubleClicked().connect(std::bind(&KeyEdit::OnExpiryClicked, m_keyEdit, skNode, WString(k.primaryFingerprint())));
}
skNode->setColumnWidget(2, unique_ptr<WText> (lblExpiry));
WString usage = sk.canAuthenticate() ? WString("A") : WString::Empty;
usage += sk.canCertify() ? WString("C") : WString::Empty;
usage += sk.canEncrypt() ? WString("E") : WString::Empty;

View File

@@ -21,7 +21,9 @@ KeyEdit::KeyEdit(K7Main * owner)
{
m_owner = owner;
m_popupUid = NULL;
m_popupExpiryTime = NULL;
m_targetUidValidityKeyFpr = WString::Empty;
m_expiryEditedKeyFpr = WString::Empty;
}
KeyEdit::~KeyEdit()
@@ -170,3 +172,34 @@ void KeyEdit::CertifyKey()
m_popupUid->ShowPassphrase(false);
m_owner->DisplayUids(keyToSign);
}
void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr)
{
if (keyFpr != m_expiryEditedKeyFpr) {
delete m_popupExpiryTime;
WText * lblExpiry = static_cast<WText*> (subkeyNode->columnWidget(2));
m_popupExpiryTime = new PopupExpiryTime(lblExpiry, m_owner->m_tmwMessage);
m_popupExpiryTime->Create(keyFpr);
m_expiryEditedKeyFpr = keyFpr;
m_popupExpiryTime->GetApplyButton()->clicked().connect(this, &KeyEdit::SetExpiryTime);
}
m_popupExpiryTime->show();
}
void KeyEdit::SetExpiryTime()
{
GpgMEWorker gpgWorker;
GpgME::Error e = gpgWorker.SetExpiryTime(m_expiryEditedKeyFpr.toUTF8().c_str(),
m_popupExpiryTime->GetPassphrase(),
m_popupExpiryTime->GetExpiryTime());
if (e.code() != 0)
{
m_owner->m_tmwMessage->SetText(TR("SetExpirationTimeFailure"));
m_popupExpiryTime->ShowPassphrase(true);
return;
}
m_owner->m_tmwMessage->SetText(TR("SetExpirationTimeSuccess"));
m_popupExpiryTime->ShowPassphrase(false);
m_owner->DisplaySubKeys(m_expiryEditedKeyFpr, true);
}

View File

@@ -14,6 +14,7 @@
#include "K7Main.h"
#include <Wt/WComboBox.h>
#include "PopupCertifyUserId.h"
#include "PopupExpiryTime.h"
using namespace Wt;
@@ -53,11 +54,20 @@ public:
* @param targetKeyFpr : The key to sign.
*/
void OnUidValidityClicked(WTreeTableNode * uidNode, vector<WString>& privateKeys, const WString& targetKeyFpr);
/**
* Shows a popup with parameters to change expiry date.
* @param subkeyNode
* @param keyFpr
*/
void OnExpiryClicked(WTreeTableNode * subkeyNode, const WString& keyFpr);
private:
K7Main * m_owner;
PopupCertifyUserId * m_popupUid;
WString m_targetUidValidityKeyFpr;
PopupExpiryTime * m_popupExpiryTime;
WString m_expiryEditedKeyFpr;
/**
* Unknown is common.
* \n If keyHasSecret is true, show only Ultimate level.
@@ -68,6 +78,7 @@ private:
*/
void FillOwnerTrustCombo(WComboBox * cmb, bool keyHasSecret);
void CertifyKey();
void SetExpiryTime();
};
#endif /* KEYEDIT_H */

View File

@@ -44,7 +44,6 @@ void PopupCertifyUserId::Create(vector<WString>& privateKeys,
{
m_fprKeyToSign = fprKeyToSign;
m_cwMain = static_cast<WContainerWidget*> (implementation());
// White in css file, like default background color.
m_cwMain->setStyleClass("popup");
WVBoxLayout * vblMain = new WVBoxLayout();

88
PopupExpiryTime.cpp Normal file
View File

@@ -0,0 +1,88 @@
/*
* File: PopupExpiryTime.cpp
* Author: SET - nmset@yandex.com
* License : GPL v2
* Copyright SET - © 2019
*
* Created on November 7, 2020, 6:05 PM
*/
#include "PopupExpiryTime.h"
#include "global.h"
#include <Wt/WVBoxLayout.h>
#include <Wt/WHBoxLayout.h>
#include <Wt/WText.h>
using namespace std;
PopupExpiryTime::PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget * txtMessage,
const WLength& width)
: WPopupWidget(cpp14::make_unique<WContainerWidget>())
{
m_tmwMessage = txtMessage;
m_cwMain = NULL;
m_keyFpr = WString::Empty;
setTransient(false);
setAnchorWidget(anchorWidget);
setWidth(width);
}
PopupExpiryTime::~PopupExpiryTime()
{
}
void PopupExpiryTime::Create(const WString& keyFpr)
{
m_keyFpr = keyFpr;
m_cwMain = static_cast<WContainerWidget*> (implementation());
m_cwMain->setStyleClass("popup");
WVBoxLayout * vblMain = new WVBoxLayout();
m_cwMain->setLayout(unique_ptr<WVBoxLayout> (vblMain));
WHBoxLayout * hblExpiry = new WHBoxLayout();
WText * lblExpiry = new WText(TR("ExpiryDate"));
hblExpiry->addWidget(unique_ptr<WText> (lblExpiry));
m_deExpiry = new WDateEdit();
hblExpiry->addWidget(unique_ptr<WDateEdit> (m_deExpiry), 1);
vblMain->addLayout(unique_ptr<WHBoxLayout> (hblExpiry));
WHBoxLayout * hblPassphrase = new WHBoxLayout();
m_lblPassphrase = new WText(TR("Passphrase"));
hblPassphrase->addWidget(unique_ptr<WText> (m_lblPassphrase));
m_lePassphrase = new WLineEdit();
m_lePassphrase->setEchoMode(EchoMode::Password);
hblPassphrase->addWidget(unique_ptr<WLineEdit> (m_lePassphrase), 1);
vblMain->addLayout(unique_ptr<WHBoxLayout> (hblPassphrase));
WHBoxLayout * hblButtons = new WHBoxLayout();
WPushButton * btnClose = new WPushButton(TR("Close"));
btnClose->clicked().connect(this, &WPopupWidget::hide);
hblButtons->addWidget(unique_ptr<WPushButton> (btnClose));
m_btnApply = new WPushButton(TR("Apply"));
hblButtons->addWidget(unique_ptr<WPushButton> (m_btnApply));
vblMain->addLayout(unique_ptr<WHBoxLayout> (hblButtons));
}
const string PopupExpiryTime::GetExpiryTime() const
{
if (m_deExpiry->text().empty())
return "0";
return m_deExpiry->text().toUTF8();
}
void PopupExpiryTime::ShowPassphrase(bool show)
{
// See comments in PopupCertifyUserId::ShowPassphrase
if (show)
{
m_lblPassphrase->show();
m_lePassphrase->show();
m_lePassphrase->setText(WString::Empty);
}
else
{
m_lblPassphrase->hide();
m_lePassphrase->hide();
}
}

70
PopupExpiryTime.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* File: PopupExpiryTime.h
* Author: SET - nmset@yandex.com
* License : GPL v2
* Copyright SET - © 2019
*
* Created on November 7, 2020, 6:05 PM
*/
#ifndef POPUPEXPIRYTIME_H
#define POPUPEXPIRYTIME_H
#include <Wt/WPopupWidget.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WDateEdit.h>
#include <Wt/WLineEdit.h>
#include <Wt/WPushButton.h>
#include "TransientMessageWidget.h"
using namespace Wt;
class PopupExpiryTime : public WPopupWidget
{
public:
PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget * txtMessage,
const WLength& width = 300);
virtual ~PopupExpiryTime();
void Create(const WString& keyFpr);
/**
* Controls visibility of passphrase widgets.
* \n Need not be always visible as the passphrase is cached by gpg-agent.
* \n During that caching period, a wrong input passphrase will not be looked
* for by GPG engine, and may be confusing.
* @param show
*/
void ShowPassphrase(bool show = true);
/**
* Used to forward the passphrase to the loopback passphrase provider.
* @return
*/
const string GetPassphrase()
{
return m_lePassphrase->text().toUTF8();
}
/**
* Returns the new expiry date.
*/
const std::string GetExpiryTime() const;
/**
* Caller binds its function here.
* @return
*/
WPushButton* GetApplyButton()
{
return m_btnApply;
}
private:
TransientMessageWidget * m_tmwMessage;
WContainerWidget * m_cwMain;
WDateEdit * m_deExpiry;
WLineEdit * m_lePassphrase;
WPushButton * m_btnApply;
WText * m_lblPassphrase;
WString m_keyFpr;
};
#endif /* POPUPEXPIRYTIME_H */

View File

@@ -2,8 +2,8 @@
It is developed in C++ as a NetBeans project on the [WebToolkit](https://www.webtoolkit.eu/)(Wt) libraries.
It allows to view, import, delete and certify keys. Certification trust level can also be changed.
Key generation, changing expiry date and adding user identities are not (yet) implemented.
It allows to view, import, delete and certify keys. Certification trust level and secret key expiry date can also be changed.
Key generation, exporting keys and adding user identities are not (yet) implemented.
These keys can then be used by other Wt applications, or applications based on other libraries, to encrypt and sign data. As such, it suits my personal needs.

View File

@@ -107,4 +107,9 @@
<message id='SigStatusIsExpired'>Expired</message>
<message id='SigStatusIsRevokation'>Revocation</message>
<message id='ExpiryDate'>Expiry date</message>
<message id='SetExpirationTimeSuccess'>Expiration time succesfully changed</message>
<message id='SetExpirationTimeFailure'>Set expiration time failed</message>
<message id='Close'>Close</message>
</messages>

View File

@@ -107,4 +107,9 @@
<message id='SigStatusIsExpired'>Expiré</message>
<message id='SigStatusIsRevokation'>Revocation</message>
<message id='ExpiryDate'>Date d'expiration</message>
<message id='SetExpirationTimeSuccess'>Date d'expiration changée avec succès</message>
<message id='SetExpirationTimeFailure'>Echec de changement de la date d'expiration</message>
<message id='Close'>Fermer</message>
</messages>

View File

@@ -43,6 +43,7 @@ OBJECTFILES= \
${OBJECTDIR}/LoopbackPassphraseProvider.o \
${OBJECTDIR}/PopupCertifyUserId.o \
${OBJECTDIR}/PopupDeleter.o \
${OBJECTDIR}/PopupExpiryTime.o \
${OBJECTDIR}/PopupUploader.o \
${OBJECTDIR}/SensitiveTreeTableNodeText.o \
${OBJECTDIR}/Tools.o \
@@ -114,6 +115,11 @@ ${OBJECTDIR}/PopupDeleter.o: PopupDeleter.cpp
${RM} "$@.d"
$(COMPILE.cc) -O2 -s -DLARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/PopupDeleter.o PopupDeleter.cpp
${OBJECTDIR}/PopupExpiryTime.o: PopupExpiryTime.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
$(COMPILE.cc) -O2 -s -DLARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/PopupExpiryTime.o PopupExpiryTime.cpp
${OBJECTDIR}/PopupUploader.o: PopupUploader.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"

View File

@@ -43,6 +43,7 @@ OBJECTFILES= \
${OBJECTDIR}/LoopbackPassphraseProvider.o \
${OBJECTDIR}/PopupCertifyUserId.o \
${OBJECTDIR}/PopupDeleter.o \
${OBJECTDIR}/PopupExpiryTime.o \
${OBJECTDIR}/PopupUploader.o \
${OBJECTDIR}/SensitiveTreeTableNodeText.o \
${OBJECTDIR}/Tools.o \
@@ -114,6 +115,11 @@ ${OBJECTDIR}/PopupDeleter.o: PopupDeleter.cpp
${RM} "$@.d"
$(COMPILE.cc) -g -DDEVTIME -I/usr/local/Wt-Debug/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/PopupDeleter.o PopupDeleter.cpp
${OBJECTDIR}/PopupExpiryTime.o: PopupExpiryTime.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
$(COMPILE.cc) -g -DDEVTIME -I/usr/local/Wt-Debug/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/PopupExpiryTime.o PopupExpiryTime.cpp
${OBJECTDIR}/PopupUploader.o: PopupUploader.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"

View File

@@ -43,6 +43,7 @@ OBJECTFILES= \
${OBJECTDIR}/LoopbackPassphraseProvider.o \
${OBJECTDIR}/PopupCertifyUserId.o \
${OBJECTDIR}/PopupDeleter.o \
${OBJECTDIR}/PopupExpiryTime.o \
${OBJECTDIR}/PopupUploader.o \
${OBJECTDIR}/SensitiveTreeTableNodeText.o \
${OBJECTDIR}/Tools.o \
@@ -114,6 +115,11 @@ ${OBJECTDIR}/PopupDeleter.o: PopupDeleter.cpp
${RM} "$@.d"
$(COMPILE.cc) -O2 -s -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/PopupDeleter.o PopupDeleter.cpp
${OBJECTDIR}/PopupExpiryTime.o: PopupExpiryTime.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
$(COMPILE.cc) -O2 -s -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/PopupExpiryTime.o PopupExpiryTime.cpp
${OBJECTDIR}/PopupUploader.o: PopupUploader.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"

View File

@@ -12,6 +12,7 @@
<itemPath>LoopbackPassphraseProvider.h</itemPath>
<itemPath>PopupCertifyUserId.h</itemPath>
<itemPath>PopupDeleter.h</itemPath>
<itemPath>PopupExpiryTime.h</itemPath>
<itemPath>PopupUploader.h</itemPath>
<itemPath>SensitiveTreeTableNodeText.h</itemPath>
<itemPath>Tools.h</itemPath>
@@ -37,6 +38,7 @@
<itemPath>LoopbackPassphraseProvider.cpp</itemPath>
<itemPath>PopupCertifyUserId.cpp</itemPath>
<itemPath>PopupDeleter.cpp</itemPath>
<itemPath>PopupExpiryTime.cpp</itemPath>
<itemPath>PopupUploader.cpp</itemPath>
<itemPath>SensitiveTreeTableNodeText.cpp</itemPath>
<itemPath>Tools.cpp</itemPath>
@@ -129,6 +131,10 @@
</item>
<item path="PopupDeleter.h" ex="false" tool="3" flavor2="0">
</item>
<item path="PopupExpiryTime.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="PopupExpiryTime.h" ex="false" tool="3" flavor2="0">
</item>
<item path="PopupUploader.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="PopupUploader.h" ex="false" tool="3" flavor2="0">
@@ -229,6 +235,10 @@
</item>
<item path="PopupDeleter.h" ex="false" tool="3" flavor2="0">
</item>
<item path="PopupExpiryTime.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="PopupExpiryTime.h" ex="false" tool="3" flavor2="0">
</item>
<item path="PopupUploader.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="PopupUploader.h" ex="false" tool="3" flavor2="0">
@@ -333,6 +343,10 @@
</item>
<item path="PopupDeleter.h" ex="false" tool="3" flavor2="0">
</item>
<item path="PopupExpiryTime.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="PopupExpiryTime.h" ex="false" tool="3" flavor2="0">
</item>
<item path="PopupUploader.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="PopupUploader.h" ex="false" tool="3" flavor2="0">