Allow changing subkey expiry time.

Needs GPGME 1.15.0.
Using the same UI for changing expiry time of the primary secret key.
This commit is contained in:
SET
2020-11-21 20:53:01 +01:00
parent bb174075df
commit e9a55a1f69
7 changed files with 100 additions and 12 deletions

View File

@@ -145,6 +145,42 @@ const Error GpgMEWorker::CertifyKey(const char* fprSigningKey,
return e; return e;
} }
const Error GpgMEWorker::SetSubkeyExpiryTime(const char* keyFpr,
const char* subkeyFpr,
const string& passphrase,
ulong expires)
{
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;
vector<GpgME::Subkey> subkey;
for (uint i = 0; i < k.subkeys().size(); i++)
{
GpgME::Subkey sk = k.subkey(i);
if (string(sk.fingerprint()) == string(subkeyFpr))
{
subkey.push_back(sk);
break;
}
}
// There should always be at least one subkey (the key itself).
m_ctx->setPinentryMode(Context::PinentryMode::PinentryLoopback);
if (m_ppp == NULL)
m_ppp = new LoopbackPassphraseProvider();
m_ppp->SetPassphrase(passphrase);
m_ctx->setPassphraseProvider(m_ppp);
e = m_ctx->setExpire(k, expires, subkey);
return e;
}
const Error GpgMEWorker::SetExpiryTime(const char * keyFpr, const Error GpgMEWorker::SetExpiryTime(const char * keyFpr,
const string& passphrase, const string& passphrase,
const string& timeString) const string& timeString)
@@ -168,7 +204,7 @@ const Error GpgMEWorker::SetExpiryTime(const char * keyFpr,
GpgME::Data d; GpgME::Data d;
e = m_ctx->edit(k, std::unique_ptr<SetExpiryTimeEditInteractor> (interactor), d); e = m_ctx->edit(k, std::unique_ptr<SetExpiryTimeEditInteractor> (interactor), d);
m_ctx->clearSigningKeys(); m_ctx->clearSigningKeys();
// NB : with a wrong passphrase, e.code() is 0 !
return e; return e;
} }

View File

@@ -77,6 +77,10 @@ public:
const char * fprKeyToSign, const char * fprKeyToSign,
vector<uint>& userIDsToSign, int options, vector<uint>& userIDsToSign, int options,
const string& passphrase); const string& passphrase);
const Error SetSubkeyExpiryTime(const char * keyFpr,
const char * subkeyFpr,
const string& passphrase,
ulong expires = 63072000);
/** /**
* Set new expiry time of a secret key. * Set new expiry time of a secret key.
* @param timeString * @param timeString
@@ -111,8 +115,8 @@ public:
* @return * @return
*/ */
const Error RevokeUserID(const char * keyFpr, const string& passphrase, const Error RevokeUserID(const char * keyFpr, const string& passphrase,
const string& name, const string& email, const string& name, const string& email,
const string& comment); const string& comment);
/** /**
* Creates a pair of secret and public keys with the default engine * Creates a pair of secret and public keys with the default engine
* algorithms. Default expiry time is 2 * 365 days. * algorithms. Default expiry time is 2 * 365 days.

View File

@@ -428,7 +428,10 @@ void K7Main::DisplaySubKeys(const WString& fullKeyID, bool secret)
if (canEditExpiry) if (canEditExpiry)
{ {
lblExpiry->setToolTip(TR("TTTDoubleCLick")); lblExpiry->setToolTip(TR("TTTDoubleCLick"));
lblExpiry->doubleClicked().connect(std::bind(&KeyEdit::OnExpiryClicked, m_keyEdit, skNode, WString(k.primaryFingerprint()))); lblExpiry->doubleClicked().connect(std::bind(&KeyEdit::OnExpiryClicked,
m_keyEdit, skNode,
WString(k.primaryFingerprint()),
WString(sk.fingerprint())));
} }
skNode->setColumnWidget(2, unique_ptr<WText> (lblExpiry)); skNode->setColumnWidget(2, unique_ptr<WText> (lblExpiry));
WString usage = sk.canAuthenticate() ? WString("A") : WString::Empty; WString usage = sk.canAuthenticate() ? WString("A") : WString::Empty;

View File

@@ -170,7 +170,8 @@ void KeyEdit::CertifyKey()
m_owner->DisplayUids(keyToSign); m_owner->DisplayUids(keyToSign);
} }
void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr) void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr,
const WString& subkeyFpr)
{ {
if (keyFpr != m_expiryEditedKeyFpr) if (keyFpr != m_expiryEditedKeyFpr)
{ {
@@ -181,15 +182,29 @@ void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr)
m_expiryEditedKeyFpr = keyFpr; m_expiryEditedKeyFpr = keyFpr;
m_popupExpiryTime->GetApplyButton()->clicked().connect(this, &KeyEdit::SetExpiryTime); m_popupExpiryTime->GetApplyButton()->clicked().connect(this, &KeyEdit::SetExpiryTime);
} }
m_popupExpiryTime->SetSubkeyFpr(subkeyFpr);
m_popupExpiryTime->show(); m_popupExpiryTime->show();
} }
void KeyEdit::SetExpiryTime() void KeyEdit::SetExpiryTime()
{ {
GpgMEWorker gpgWorker; GpgMEWorker gpgWorker;
GpgME::Error e = gpgWorker.SetExpiryTime(m_expiryEditedKeyFpr.toUTF8().c_str(), GpgME::Error e;
m_popupExpiryTime->GetPassphrase(), const WString keyFpr = m_popupExpiryTime->GetKeyFpr();
m_popupExpiryTime->GetExpiryTime()); const WString subkeyFpr = m_popupExpiryTime->GetSubkeyFpr();
if (keyFpr == subkeyFpr)
{
e = gpgWorker.SetExpiryTime(keyFpr.toUTF8().c_str(),
m_popupExpiryTime->GetPassphrase(),
m_popupExpiryTime->GetExpiryTime());
}
else
{
e = gpgWorker.SetSubkeyExpiryTime(keyFpr.toUTF8().c_str(),
subkeyFpr.toUTF8().c_str(),
m_popupExpiryTime->GetPassphrase(),
m_popupExpiryTime->GetExpiry());
}
if (e.code() != 0) if (e.code() != 0)
{ {
m_owner->m_tmwMessage->SetText(TR("SetExpirationTimeFailure")); m_owner->m_tmwMessage->SetText(TR("SetExpirationTimeFailure"));

View File

@@ -85,7 +85,8 @@ private:
* @param subkeyNode * @param subkeyNode
* @param keyFpr * @param keyFpr
*/ */
void OnExpiryClicked(WTreeTableNode * subkeyNode, const WString& keyFpr); void OnExpiryClicked(WTreeTableNode * subkeyNode, const WString& keyFpr,
const WString& subkeyFpr);
void OnUidEmailClicked(WTreeTableNode * uidNode, const WString& keyFpr); void OnUidEmailClicked(WTreeTableNode * uidNode, const WString& keyFpr);

View File

@@ -22,6 +22,7 @@ PopupExpiryTime::PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget
m_tmwMessage = txtMessage; m_tmwMessage = txtMessage;
m_cwMain = NULL; m_cwMain = NULL;
m_keyFpr = WString::Empty; m_keyFpr = WString::Empty;
m_subkeyFpr = WString::Empty;
/* /*
* Trade-off. * Trade-off.
* When the calendar of WDateEdit is clicked, this popup gets hidden, * When the calendar of WDateEdit is clicked, this popup gets hidden,
@@ -82,6 +83,11 @@ const string PopupExpiryTime::GetExpiryTime() const
return m_deExpiry->text().toUTF8(); return m_deExpiry->text().toUTF8();
} }
const ulong PopupExpiryTime::GetExpiry() const
{
return ((WDate::currentDate().daysTo(m_deExpiry->date())) * 24 * 3600);
}
void PopupExpiryTime::ShowPassphrase(bool show) void PopupExpiryTime::ShowPassphrase(bool show)
{ {
// See comments in PopupCertifyUserId::ShowPassphrase // See comments in PopupCertifyUserId::ShowPassphrase

View File

@@ -23,9 +23,24 @@ class PopupExpiryTime : public WPopupWidget
{ {
public: public:
PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget * txtMessage, PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget * txtMessage,
const WLength& width = 300); const WLength& width = 300);
virtual ~PopupExpiryTime(); virtual ~PopupExpiryTime();
void Create(const WString& keyFpr); void Create(const WString& keyFpr);
const WString GetKeyFpr()
{
return m_keyFpr;
}
void SetSubkeyFpr(const WString& subkeyFpr)
{
m_subkeyFpr = subkeyFpr;
}
const WString GetSubkeyFpr()
{
return m_subkeyFpr;
}
/** /**
* Controls visibility of passphrase widgets. * Controls visibility of passphrase widgets.
* \n Need not be always visible as the passphrase is cached by gpg-agent. * \n Need not be always visible as the passphrase is cached by gpg-agent.
@@ -34,6 +49,7 @@ public:
* @param show * @param show
*/ */
void ShowPassphrase(bool show = true); void ShowPassphrase(bool show = true);
/** /**
* Used to forward the passphrase to the loopback passphrase provider. * Used to forward the passphrase to the loopback passphrase provider.
* @return * @return
@@ -43,9 +59,15 @@ public:
return m_lePassphrase->text().toUTF8(); return m_lePassphrase->text().toUTF8();
} }
/** /**
* Returns the new expiry date. * Returns the new expiry date, or 0 if date is invalid.
*/ */
const std::string GetExpiryTime() const; const std::string GetExpiryTime() const;
/**
* Number of seconds from now.
* @return
*/
const ulong GetExpiry() const;
/** /**
* Caller binds its function here. * Caller binds its function here.
* @return * @return
@@ -54,7 +76,7 @@ public:
{ {
return m_btnApply; return m_btnApply;
} }
private: private:
TransientMessageWidget * m_tmwMessage; TransientMessageWidget * m_tmwMessage;
WContainerWidget * m_cwMain; WContainerWidget * m_cwMain;
@@ -63,6 +85,7 @@ private:
WPushButton * m_btnApply; WPushButton * m_btnApply;
WText * m_lblPassphrase; WText * m_lblPassphrase;
WString m_keyFpr; WString m_keyFpr;
WString m_subkeyFpr;
}; };