cpp: Add information about revocation keys to Key

* lang/cpp/src/gpgmefw.h (gpgme_revocation_key_t): New forward
declaration.
* lang/cpp/src/key.cpp, lang/cpp/src/key.h (class Key): New methods
revocationKey, numRevocationKeys, revocationKeys.
(class RevocationKey): New.
(swap): New overload for RevocationKey.
(operator<<): New overload for RevocationKey.
* lang/cpp/src/key.cpp (operator<<): Add information about revocation
keys to the output stream for Key.

* lang/cpp/tests/run-keylist.cpp (main): Don't output Key if nextKey
failed, e.g. at the end of the key listing.
--

GnuPG-bug-id: 7118
This commit is contained in:
Ingo Klöcker 2024-05-21 16:32:23 +02:00
parent f2575b6313
commit 90eb80134b
No known key found for this signature in database
GPG Key ID: F5A5D1692277A1E9
5 changed files with 170 additions and 1 deletions

7
NEWS
View File

@ -9,6 +9,9 @@ Noteworthy changes in version 1.24.0 (unrelease)
* Add information about designated revocation keys. [T7118] * Add information about designated revocation keys. [T7118]
* cpp: Provide information about designated revocation keys for a Key.
[T7118]
* qt: Allow reading the data to decrypt/encrypt/sign/verify directly from * qt: Allow reading the data to decrypt/encrypt/sign/verify directly from
files. [T6550] files. [T6550]
@ -23,6 +26,10 @@ Noteworthy changes in version 1.24.0 (unrelease)
gpgme_revocation_key_t NEW. gpgme_revocation_key_t NEW.
cpp: Context::EncryptFile NEW. cpp: Context::EncryptFile NEW.
cpp: SignatureMode::SignFile NEW. cpp: SignatureMode::SignFile NEW.
cpp: RevocationKey NEW.
cpp: Key::revocationKey NEW.
cpp: Key::numRevocationKeys NEW.
cpp: Key::revocationKeys NEW.
qt: DecryptVerifyJob::setInputFile NEW. qt: DecryptVerifyJob::setInputFile NEW.
qt: DecryptVerifyJob::inputFile NEW. qt: DecryptVerifyJob::inputFile NEW.
qt: DecryptVerifyJob::setOutputFile NEW. qt: DecryptVerifyJob::setOutputFile NEW.

View File

@ -75,4 +75,7 @@ typedef struct _gpgme_tofu_info *gpgme_tofu_info_t;
struct _gpgme_op_query_swdb_result; struct _gpgme_op_query_swdb_result;
typedef struct _gpgme_op_query_swdb_result *gpgme_query_swdb_result_t; typedef struct _gpgme_op_query_swdb_result *gpgme_query_swdb_result_t;
struct _gpgme_revocation_key;
typedef struct _gpgme_revocation_key *gpgme_revocation_key_t;
#endif // __GPGMEPP_GPGMEFW_H__ #endif // __GPGMEPP_GPGMEFW_H__

View File

@ -122,6 +122,37 @@ std::vector<Subkey> Key::subkeys() const
return v; return v;
} }
RevocationKey Key::revocationKey(unsigned int index) const
{
return RevocationKey(key, index);
}
unsigned int Key::numRevocationKeys() const
{
if (!key) {
return 0;
}
unsigned int count = 0;
for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) {
++count;
}
return count;
}
std::vector<RevocationKey> Key::revocationKeys() const
{
if (!key) {
return std::vector<RevocationKey>();
}
std::vector<RevocationKey> v;
v.reserve(numRevocationKeys());
for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) {
v.push_back(RevocationKey(key, revkey));
}
return v;
}
Key::OwnerTrust Key::ownerTrust() const Key::OwnerTrust Key::ownerTrust() const
{ {
if (!key) { if (!key) {
@ -1256,6 +1287,68 @@ bool UserID::Signature::isBad() const
return isNull() || isExpired() || isInvalid(); return isNull() || isExpired() || isInvalid();
} }
//
//
// class RevocationKey
//
//
static gpgme_revocation_key_t find_revkey(const shared_gpgme_key_t &key, unsigned int idx)
{
if (key) {
for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next, --idx) {
if (idx == 0) {
return s;
}
}
}
return nullptr;
}
static gpgme_revocation_key_t verify_revkey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey)
{
if (key) {
for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next) {
if (s == revkey) {
return revkey;
}
}
}
return nullptr;
}
RevocationKey::RevocationKey() : key(), revkey(nullptr) {}
RevocationKey::RevocationKey(const shared_gpgme_key_t &k, unsigned int idx)
: key(k), revkey(find_revkey(k, idx))
{
}
RevocationKey::RevocationKey(const shared_gpgme_key_t &k, gpgme_revocation_key_t sk)
: key(k), revkey(verify_revkey(k, sk))
{
}
Key RevocationKey::parent() const
{
return Key(key);
}
const char *RevocationKey::fingerprint() const
{
return revkey ? revkey->fpr : nullptr;
}
bool RevocationKey::isSensitive() const
{
return revkey ? revkey->sensitive : false;
}
int RevocationKey::algorithm() const
{
return revkey ? revkey->pubkey_algo : 0;
}
std::ostream &operator<<(std::ostream &os, const UserID &uid) std::ostream &operator<<(std::ostream &os, const UserID &uid)
{ {
os << "GpgME::UserID("; os << "GpgME::UserID(";
@ -1325,6 +1418,20 @@ std::ostream &operator<<(std::ostream &os, const Key &key)
const std::vector<Subkey> subkeys = key.subkeys(); const std::vector<Subkey> subkeys = key.subkeys();
std::copy(subkeys.begin(), subkeys.end(), std::copy(subkeys.begin(), subkeys.end(),
std::ostream_iterator<Subkey>(os, "\n")); std::ostream_iterator<Subkey>(os, "\n"));
os << " revocationKeys:\n";
const std::vector<RevocationKey> revkeys = key.revocationKeys();
std::copy(revkeys.begin(), revkeys.end(),
std::ostream_iterator<RevocationKey>(os, "\n"));
}
return os << ')';
}
std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey)
{
os << "GpgME::RevocationKey(";
if (!revkey.isNull()) {
os << "\n fingerprint: " << protect(revkey.fingerprint())
<< "\n isSensitive: " << revkey.isSensitive();
} }
return os << ')'; return os << ')';
} }

View File

@ -44,6 +44,7 @@ class Context;
class Subkey; class Subkey;
class UserID; class UserID;
class TofuInfo; class TofuInfo;
class RevocationKey;
typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t; typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t;
@ -100,6 +101,10 @@ public:
std::vector<UserID> userIDs() const; std::vector<UserID> userIDs() const;
std::vector<Subkey> subkeys() const; std::vector<Subkey> subkeys() const;
RevocationKey revocationKey(unsigned int index) const;
unsigned int numRevocationKeys() const;
std::vector<RevocationKey> revocationKeys() const;
bool isRevoked() const; bool isRevoked() const;
bool isExpired() const; bool isExpired() const;
bool isDisabled() const; bool isDisabled() const;
@ -547,9 +552,53 @@ private:
gpgme_key_sig_t sig; gpgme_key_sig_t sig;
}; };
//
// class RevocationKey
//
class GPGMEPP_EXPORT RevocationKey
{
public:
RevocationKey();
RevocationKey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey);
RevocationKey(const shared_gpgme_key_t &key, unsigned int idx);
// Rule of Zero
void swap(RevocationKey &other)
{
using std::swap;
swap(this->key, other.key);
swap(this->revkey, other.revkey);
}
bool isNull() const
{
return !key || !revkey;
}
Key parent() const;
const char *fingerprint() const;
bool isSensitive() const;
int algorithm() const;
private:
shared_gpgme_key_t key;
gpgme_revocation_key_t revkey;
};
inline void swap(RevocationKey& v1, RevocationKey& v2)
{
v1.swap(v2);
}
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid);
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Subkey &subkey); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Subkey &subkey);
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key);
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey);
} // namespace GpgME } // namespace GpgME

View File

@ -160,7 +160,10 @@ main (int argc, char **argv)
std::stringstream ss; std::stringstream ss;
do { do {
key = ctx->nextKey(err); key = ctx->nextKey(err);
if (!err)
{
ss << key << "\n\n"; ss << key << "\n\n";
}
} while (!err && !key.isNull()); } while (!err && !key.isNull());
std::cout << ss.str(); std::cout << ss.str();