diff --git a/GpgMEWorker.cpp b/GpgMEWorker.cpp index afe35b3..a1919ce 100644 --- a/GpgMEWorker.cpp +++ b/GpgMEWorker.cpp @@ -145,6 +145,42 @@ const Error GpgMEWorker::CertifyKey(const char* fprSigningKey, 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 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 string& passphrase, const string& timeString) @@ -168,7 +204,7 @@ const Error GpgMEWorker::SetExpiryTime(const char * keyFpr, GpgME::Data d; e = m_ctx->edit(k, std::unique_ptr (interactor), d); m_ctx->clearSigningKeys(); - + // NB : with a wrong passphrase, e.code() is 0 ! return e; } diff --git a/GpgMEWorker.h b/GpgMEWorker.h index d2fb62d..44d5404 100644 --- a/GpgMEWorker.h +++ b/GpgMEWorker.h @@ -77,6 +77,10 @@ public: const char * fprKeyToSign, vector& userIDsToSign, int options, 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. * @param timeString @@ -111,8 +115,8 @@ public: * @return */ const Error RevokeUserID(const char * keyFpr, const string& passphrase, - const string& name, const string& email, - const string& comment); + const string& name, const string& email, + const string& comment); /** * Creates a pair of secret and public keys with the default engine * algorithms. Default expiry time is 2 * 365 days. diff --git a/K7Main.cpp b/K7Main.cpp index 53394cf..502d383 100644 --- a/K7Main.cpp +++ b/K7Main.cpp @@ -428,7 +428,10 @@ void K7Main::DisplaySubKeys(const WString& fullKeyID, bool secret) if (canEditExpiry) { 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 (lblExpiry)); WString usage = sk.canAuthenticate() ? WString("A") : WString::Empty; diff --git a/KeyEdit.cpp b/KeyEdit.cpp index acfe565..0096ef1 100644 --- a/KeyEdit.cpp +++ b/KeyEdit.cpp @@ -170,7 +170,8 @@ void KeyEdit::CertifyKey() 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) { @@ -181,15 +182,29 @@ void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr) m_expiryEditedKeyFpr = keyFpr; m_popupExpiryTime->GetApplyButton()->clicked().connect(this, &KeyEdit::SetExpiryTime); } + m_popupExpiryTime->SetSubkeyFpr(subkeyFpr); m_popupExpiryTime->show(); } void KeyEdit::SetExpiryTime() { GpgMEWorker gpgWorker; - GpgME::Error e = gpgWorker.SetExpiryTime(m_expiryEditedKeyFpr.toUTF8().c_str(), - m_popupExpiryTime->GetPassphrase(), - m_popupExpiryTime->GetExpiryTime()); + GpgME::Error e; + const WString keyFpr = m_popupExpiryTime->GetKeyFpr(); + 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) { m_owner->m_tmwMessage->SetText(TR("SetExpirationTimeFailure")); diff --git a/KeyEdit.h b/KeyEdit.h index 62744b2..cfb7525 100644 --- a/KeyEdit.h +++ b/KeyEdit.h @@ -85,7 +85,8 @@ private: * @param subkeyNode * @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); diff --git a/PopupExpiryTime.cpp b/PopupExpiryTime.cpp index 7b47893..dfb6331 100644 --- a/PopupExpiryTime.cpp +++ b/PopupExpiryTime.cpp @@ -22,6 +22,7 @@ PopupExpiryTime::PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget m_tmwMessage = txtMessage; m_cwMain = NULL; m_keyFpr = WString::Empty; + m_subkeyFpr = WString::Empty; /* * Trade-off. * 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(); } +const ulong PopupExpiryTime::GetExpiry() const +{ + return ((WDate::currentDate().daysTo(m_deExpiry->date())) * 24 * 3600); +} + void PopupExpiryTime::ShowPassphrase(bool show) { // See comments in PopupCertifyUserId::ShowPassphrase diff --git a/PopupExpiryTime.h b/PopupExpiryTime.h index 78ec676..dde804b 100644 --- a/PopupExpiryTime.h +++ b/PopupExpiryTime.h @@ -23,9 +23,24 @@ class PopupExpiryTime : public WPopupWidget { public: PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget * txtMessage, - const WLength& width = 300); + const WLength& width = 300); virtual ~PopupExpiryTime(); 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. * \n Need not be always visible as the passphrase is cached by gpg-agent. @@ -34,6 +49,7 @@ public: * @param show */ void ShowPassphrase(bool show = true); + /** * Used to forward the passphrase to the loopback passphrase provider. * @return @@ -43,9 +59,15 @@ public: 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; + /** + * Number of seconds from now. + * @return + */ + const ulong GetExpiry() const; + /** * Caller binds its function here. * @return @@ -54,7 +76,7 @@ public: { return m_btnApply; } - + private: TransientMessageWidget * m_tmwMessage; WContainerWidget * m_cwMain; @@ -63,6 +85,7 @@ private: WPushButton * m_btnApply; WText * m_lblPassphrase; WString m_keyFpr; + WString m_subkeyFpr; };