Merge branch 'ikloecker/t7118-revkeys'
This commit is contained in:
commit
f0d1f2c4c7
11
NEWS
11
NEWS
@ -7,6 +7,11 @@ Noteworthy changes in version 1.24.0 (unrelease)
|
|||||||
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
|
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
|
||||||
to allow reading the input data directly from a file. [T6550]
|
to allow reading the input data directly from a file. [T6550]
|
||||||
|
|
||||||
|
* 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]
|
||||||
|
|
||||||
@ -17,8 +22,14 @@ Noteworthy changes in version 1.24.0 (unrelease)
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
GPGME_ENCRYPT_FILE NEW.
|
GPGME_ENCRYPT_FILE NEW.
|
||||||
GPGME_SIG_MODE_FILE NEW.
|
GPGME_SIG_MODE_FILE NEW.
|
||||||
|
gpgme_key_t EXTENDED: New field 'revkeys'.
|
||||||
|
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.
|
||||||
|
@ -3566,6 +3566,10 @@ be missing but this field may be set nevertheless.
|
|||||||
|
|
||||||
Reserved for the time of the last update of this key.
|
Reserved for the time of the last update of this key.
|
||||||
|
|
||||||
|
@item gpgme_revocation_key_t revkeys
|
||||||
|
@since{1.24.0}
|
||||||
|
This is a linked list with the revocation keys for the key.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
@ -3908,6 +3912,37 @@ This is a linked list with the notation data and policy URLs.
|
|||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
|
||||||
|
@deftp {Data type} gpgme_revocation_key_t
|
||||||
|
@since{1.24.0}
|
||||||
|
|
||||||
|
The @code{gpgme_revocation_key_t} type is a pointer to a revocation key
|
||||||
|
structure. Revocation key structures are one component of a
|
||||||
|
@code{gpgme_key_t} object. They provide information about the designated
|
||||||
|
revocation keys for a key.
|
||||||
|
|
||||||
|
The revocation key structure has the following members:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item gpgme_revocation_key_t next
|
||||||
|
This is a pointer to the next revocation key structure in the linked list,
|
||||||
|
or @code{NULL} if this is the last element.
|
||||||
|
|
||||||
|
@item gpgme_pubkey_algo_t pubkey_algo
|
||||||
|
This is the public key algorithm of the revocation key.
|
||||||
|
|
||||||
|
@item char *fpr
|
||||||
|
This is the fingerprint of the revocation_key in hexadecimal digits.
|
||||||
|
|
||||||
|
@item unsigned int key_class
|
||||||
|
This is the class of the revocation key signature subpacket.
|
||||||
|
|
||||||
|
@item unsigned int sensitive : 1
|
||||||
|
This is true if the revocation key is marked as sensitive.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Listing Keys
|
@node Listing Keys
|
||||||
@subsection Listing Keys
|
@subsection Listing Keys
|
||||||
|
@ -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__
|
||||||
|
@ -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 << ')';
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -1024,6 +1024,24 @@ subkey_to_json (gpgme_subkey_t sub)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a revocation key json object */
|
||||||
|
static cjson_t
|
||||||
|
revocation_key_to_json (gpgme_revocation_key_t revkey)
|
||||||
|
{
|
||||||
|
cjson_t result = xjson_CreateObject ();
|
||||||
|
|
||||||
|
xjson_AddBoolToObject (result, "sensitive", revkey->sensitive);
|
||||||
|
|
||||||
|
xjson_AddStringToObject0 (result, "fingerprint", revkey->fpr);
|
||||||
|
xjson_AddStringToObject0 (result, "pubkey_algo_name",
|
||||||
|
gpgme_pubkey_algo_name (revkey->pubkey_algo));
|
||||||
|
|
||||||
|
xjson_AddNumberToObject (result, "pubkey_algo", revkey->pubkey_algo);
|
||||||
|
xjson_AddNumberToObject (result, "key_class", revkey->key_class);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a key json object */
|
/* Create a key json object */
|
||||||
static cjson_t
|
static cjson_t
|
||||||
key_to_json (gpgme_key_t key)
|
key_to_json (gpgme_key_t key)
|
||||||
@ -1075,6 +1093,16 @@ key_to_json (gpgme_key_t key)
|
|||||||
xjson_AddItemToObject (result, "userids", uid_array);
|
xjson_AddItemToObject (result, "userids", uid_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Revocation keys */
|
||||||
|
if (key->revocation_keys)
|
||||||
|
{
|
||||||
|
gpgme_revocation_key_t revkey;
|
||||||
|
cjson_t array = xjson_CreateArray ();
|
||||||
|
for (revkey = key->revocation_keys; revkey; revkey = revkey->next)
|
||||||
|
cJSON_AddItemToArray (array, revocation_key_to_json (revkey));
|
||||||
|
xjson_AddItemToObject (result, "revocation_keys", array);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,6 +763,28 @@ struct _gpgme_user_id
|
|||||||
typedef struct _gpgme_user_id *gpgme_user_id_t;
|
typedef struct _gpgme_user_id *gpgme_user_id_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* A designated revocation key for a key.
|
||||||
|
* This structure shall be considered read-only and an application
|
||||||
|
* must not allocate such a structure on its own. */
|
||||||
|
struct _gpgme_revocation_key
|
||||||
|
{
|
||||||
|
struct _gpgme_revocation_key *next;
|
||||||
|
|
||||||
|
/* The public key algorithm of the revocation key. */
|
||||||
|
gpgme_pubkey_algo_t pubkey_algo;
|
||||||
|
|
||||||
|
/* The fingerprint of the revocation_key in hex digit form. */
|
||||||
|
char *fpr;
|
||||||
|
|
||||||
|
/* The class of the revocation key. */
|
||||||
|
unsigned int key_class;
|
||||||
|
|
||||||
|
/* True if the revocation key should not be exported. */
|
||||||
|
unsigned int sensitive : 1;
|
||||||
|
};
|
||||||
|
typedef struct _gpgme_revocation_key *gpgme_revocation_key_t;
|
||||||
|
|
||||||
|
|
||||||
/* A key from the keyring.
|
/* A key from the keyring.
|
||||||
* This structure shall be considered read-only and an application
|
* This structure shall be considered read-only and an application
|
||||||
* must not allocate such a structure on its own. */
|
* must not allocate such a structure on its own. */
|
||||||
@ -860,6 +882,12 @@ struct _gpgme_key
|
|||||||
|
|
||||||
/* Time of the last refresh of the entire key. 0 if unknown. */
|
/* Time of the last refresh of the entire key. 0 if unknown. */
|
||||||
unsigned long last_update;
|
unsigned long last_update;
|
||||||
|
|
||||||
|
/* The revocation keys of the key. */
|
||||||
|
gpgme_revocation_key_t revocation_keys;
|
||||||
|
|
||||||
|
/* Internal to GPGME, do not use. */
|
||||||
|
gpgme_revocation_key_t _last_revkey;
|
||||||
};
|
};
|
||||||
typedef struct _gpgme_key *gpgme_key_t;
|
typedef struct _gpgme_key *gpgme_key_t;
|
||||||
|
|
||||||
|
38
src/key.c
38
src/key.c
@ -304,6 +304,35 @@ _gpgme_key_add_sig (gpgme_key_t key, char *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_error_t
|
||||||
|
_gpgme_key_add_rev_key (gpgme_key_t key, const char *src)
|
||||||
|
{
|
||||||
|
gpgme_revocation_key_t revkey;
|
||||||
|
int src_len = src ? strlen (src) : 0;
|
||||||
|
|
||||||
|
assert (key);
|
||||||
|
/* malloc a buffer for the revocation key and the fingerprint. */
|
||||||
|
revkey = malloc (sizeof (*revkey) + src_len + 1);
|
||||||
|
if (!revkey)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
memset (revkey, 0, sizeof *revkey);
|
||||||
|
|
||||||
|
revkey->fpr = ((char *) revkey) + sizeof (*revkey);
|
||||||
|
if (src)
|
||||||
|
memcpy (revkey->fpr, src, src_len + 1);
|
||||||
|
else
|
||||||
|
revkey->fpr[0] = '\0';
|
||||||
|
|
||||||
|
if (!key->revocation_keys)
|
||||||
|
key->revocation_keys = revkey;
|
||||||
|
if (key->_last_revkey)
|
||||||
|
key->_last_revkey->next = revkey;
|
||||||
|
key->_last_revkey = revkey;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Acquire a reference to KEY. */
|
/* Acquire a reference to KEY. */
|
||||||
void
|
void
|
||||||
gpgme_key_ref (gpgme_key_t key)
|
gpgme_key_ref (gpgme_key_t key)
|
||||||
@ -324,6 +353,7 @@ gpgme_key_unref (gpgme_key_t key)
|
|||||||
{
|
{
|
||||||
gpgme_user_id_t uid;
|
gpgme_user_id_t uid;
|
||||||
gpgme_subkey_t subkey;
|
gpgme_subkey_t subkey;
|
||||||
|
gpgme_revocation_key_t revkey;
|
||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
return;
|
return;
|
||||||
@ -392,6 +422,14 @@ gpgme_key_unref (gpgme_key_t key)
|
|||||||
uid = next_uid;
|
uid = next_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revkey = key->revocation_keys;
|
||||||
|
while (revkey)
|
||||||
|
{
|
||||||
|
gpgme_revocation_key_t next = revkey->next;
|
||||||
|
free (revkey);
|
||||||
|
revkey = next;
|
||||||
|
}
|
||||||
|
|
||||||
free (key->issuer_serial);
|
free (key->issuer_serial);
|
||||||
free (key->issuer_name);
|
free (key->issuer_name);
|
||||||
free (key->chain_id);
|
free (key->chain_id);
|
||||||
|
@ -603,7 +603,7 @@ keylist_colon_handler (void *priv, char *line)
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_FP2, RT_GRP,
|
RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_FP2, RT_GRP,
|
||||||
RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
|
RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK, RT_RVK
|
||||||
}
|
}
|
||||||
rectype = RT_NONE;
|
rectype = RT_NONE;
|
||||||
#define NR_FIELDS 20
|
#define NR_FIELDS 20
|
||||||
@ -669,6 +669,8 @@ keylist_colon_handler (void *priv, char *line)
|
|||||||
rectype = RT_SSB;
|
rectype = RT_SSB;
|
||||||
else if (!strcmp (field[0], "spk") && key)
|
else if (!strcmp (field[0], "spk") && key)
|
||||||
rectype = RT_SPK;
|
rectype = RT_SPK;
|
||||||
|
else if (!strcmp (field[0], "rvk") && key)
|
||||||
|
rectype = RT_RVK;
|
||||||
else
|
else
|
||||||
rectype = RT_NONE;
|
rectype = RT_NONE;
|
||||||
|
|
||||||
@ -1124,6 +1126,39 @@ keylist_colon_handler (void *priv, char *line)
|
|||||||
keysig->_last_notation = notation;
|
keysig->_last_notation = notation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RT_RVK:
|
||||||
|
/* Ignore revocation keys without fingerprint */
|
||||||
|
if (fields >= 10 && *field[9])
|
||||||
|
{
|
||||||
|
gpgme_revocation_key_t revkey = NULL;
|
||||||
|
|
||||||
|
err = _gpgme_key_add_rev_key (key, field[9]);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
revkey = key->_last_revkey;
|
||||||
|
assert (revkey);
|
||||||
|
|
||||||
|
/* Field 4 has the public key algorithm. */
|
||||||
|
{
|
||||||
|
int i = atoi (field[3]);
|
||||||
|
if (i >= 1 && i < 128)
|
||||||
|
revkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Field 11 has the class (eg, 0x40 means sensitive). */
|
||||||
|
if (fields >= 11 && field[10][0] && field[10][1])
|
||||||
|
{
|
||||||
|
int key_class = _gpgme_hextobyte (field[10]);
|
||||||
|
if (key_class >= 0)
|
||||||
|
revkey->key_class = key_class;
|
||||||
|
if (field[10][2] == 's')
|
||||||
|
revkey->sensitive = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case RT_NONE:
|
case RT_NONE:
|
||||||
/* Unknown record. */
|
/* Unknown record. */
|
||||||
|
@ -145,6 +145,7 @@ gpgme_error_t _gpgme_key_add_subkey (gpgme_key_t key,
|
|||||||
gpgme_error_t _gpgme_key_append_name (gpgme_key_t key,
|
gpgme_error_t _gpgme_key_append_name (gpgme_key_t key,
|
||||||
const char *src, int convert);
|
const char *src, int convert);
|
||||||
gpgme_key_sig_t _gpgme_key_add_sig (gpgme_key_t key, char *src);
|
gpgme_key_sig_t _gpgme_key_add_sig (gpgme_key_t key, char *src);
|
||||||
|
gpgme_error_t _gpgme_key_add_rev_key (gpgme_key_t key, const char *src);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,9 +88,13 @@ gpg-sample.stamp: $(private_keys)
|
|||||||
done
|
done
|
||||||
echo x > ./gpg-sample.stamp
|
echo x > ./gpg-sample.stamp
|
||||||
|
|
||||||
pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc gpg-sample.stamp
|
pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc \
|
||||||
|
$(top_srcdir)/tests/json/key-with-revokers.asc \
|
||||||
|
gpg-sample.stamp
|
||||||
$(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
|
$(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
|
||||||
--import $(top_srcdir)/tests/gpg/pubdemo.asc
|
--import $(top_srcdir)/tests/gpg/pubdemo.asc
|
||||||
|
$(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
|
||||||
|
--import $(top_srcdir)/tests/json/key-with-revokers.asc
|
||||||
-$(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
|
-$(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
|
||||||
--import $(top_srcdir)/tests/gpg/secdemo.asc
|
--import $(top_srcdir)/tests/gpg/secdemo.asc
|
||||||
-$(TESTS_ENVIRONMENT) gpgconf --kill all
|
-$(TESTS_ENVIRONMENT) gpgconf --kill all
|
||||||
|
19
tests/json/key-with-revokers.asc
Normal file
19
tests/json/key-with-revokers.asc
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
mDMEZkTFQxYJKwYBBAHaRw8BAQdATFay6x2u19PsF5P7YDj2WW9KproKIqAMAqHR
|
||||||
|
cnkiebiIkAQfFgoAOBYhBMlchkt3X3HQL1LO9r0HuCiy91BxBQJmRMVDFwzAEaD/
|
||||||
|
RZC7YSLt7248VC1yfMdoaXc0AgcAAAoJEL0HuCiy91BxhCMBAKtymj/0Q/XDKO3c
|
||||||
|
9mlz5ycll8MfT/a6H2WFWGV6L9SEAPwN3/n4qR9bBiReT9Xo3q58e2efoXoFXz86
|
||||||
|
BXv1rCYJAYiQBB8WCgA4FiEEyVyGS3dfcdAvUs72vQe4KLL3UHEFAmZExUMXDIAR
|
||||||
|
I/00ekGUKbrM1ecta8R3gFSs0kYCBwAACgkQvQe4KLL3UHFlBwEA1JL4yE/sWOKr
|
||||||
|
BfbHbUI4ffS6s+oh7sQxHEQy0pJN7LoA/RSKUIThOl5apOVhd/dYOPj+4aGZ9ZP1
|
||||||
|
ARqeXIWYxpwCtB1rZXktd2l0aC1yZXZva2Vyc0BleGFtcGxlLm5ldIiZBBMWCgBB
|
||||||
|
FiEEyVyGS3dfcdAvUs72vQe4KLL3UHEFAmZExUMCGwMFCQWjmoAFCwkIBwICIgIG
|
||||||
|
FQoJCAsCBBYCAwECHgcCF4AACgkQvQe4KLL3UHFcjwD/ZpSNHKpGV99sKlxbzABg
|
||||||
|
msIGKLgcuFLUsT1QCV3yE4cA/iS4NW9Y508uUqoJfFH0lBpJ4+US6VQevVpRNe6N
|
||||||
|
KqYEuDgEZkTFQxIKKwYBBAGXVQEFAQEHQFDZXf9Y1Y6A00CDcYw8RO73idcn/d7B
|
||||||
|
ifTuBfYpXVJjAwEIB4h4BBgWCgAgFiEEyVyGS3dfcdAvUs72vQe4KLL3UHEFAmZE
|
||||||
|
xUMCGwwACgkQvQe4KLL3UHEZrQD/SWYkwCFtqaxbYQUcSJ+v2+wA28RUm7KrgJ+A
|
||||||
|
PsdiNJsBAIjUUsYlf+J/d4Ia0tccfzPBqVpyeWZ52bBD0pH/Eu8N
|
||||||
|
=JTll
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
@ -41,6 +41,7 @@ static const char*tests[] = { "t-config", "t-version",
|
|||||||
"t-encrypt", "t-encrypt-sign", "t-sign", "t-verify",
|
"t-encrypt", "t-encrypt-sign", "t-sign", "t-verify",
|
||||||
"t-decrypt-verify", "t-export", "t-createkey",
|
"t-decrypt-verify", "t-export", "t-createkey",
|
||||||
"t-export-secret-info", "t-chunking", "t-sig-notations",
|
"t-export-secret-info", "t-chunking", "t-sig-notations",
|
||||||
|
"t-keylist-revokers",
|
||||||
/* For these two the order is important
|
/* For these two the order is important
|
||||||
* as t-import imports the deleted key from t-delete */
|
* as t-import imports the deleted key from t-delete */
|
||||||
"t-delete", "t-import",
|
"t-delete", "t-import",
|
||||||
|
5
tests/json/t-keylist-revokers.in.json
Normal file
5
tests/json/t-keylist-revokers.in.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"op": "keylist",
|
||||||
|
"keys": [ "key-with-revokers@example.net" ],
|
||||||
|
"with-secret": false
|
||||||
|
}
|
97
tests/json/t-keylist-revokers.out.json
Normal file
97
tests/json/t-keylist-revokers.out.json
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"revoked": false,
|
||||||
|
"expired": false,
|
||||||
|
"disabled": false,
|
||||||
|
"invalid": false,
|
||||||
|
"can_encrypt": true,
|
||||||
|
"can_sign": true,
|
||||||
|
"can_certify": true,
|
||||||
|
"can_authenticate": false,
|
||||||
|
"secret": false,
|
||||||
|
"is_qualified": false,
|
||||||
|
"protocol": "OpenPGP",
|
||||||
|
"fingerprint": "C95C864B775F71D02F52CEF6BD07B828B2F75071",
|
||||||
|
"owner_trust": "unknown",
|
||||||
|
"origin": 0,
|
||||||
|
"last_update": 0,
|
||||||
|
"subkeys": [
|
||||||
|
{
|
||||||
|
"revoked": false,
|
||||||
|
"expired": false,
|
||||||
|
"disabled": false,
|
||||||
|
"invalid": false,
|
||||||
|
"can_encrypt": false,
|
||||||
|
"can_sign": true,
|
||||||
|
"can_certify": true,
|
||||||
|
"can_authenticate": false,
|
||||||
|
"secret": false,
|
||||||
|
"is_qualified": false,
|
||||||
|
"is_cardkey": false,
|
||||||
|
"is_de_vs": false,
|
||||||
|
"pubkey_algo_name": "EdDSA",
|
||||||
|
"pubkey_algo_string": "ed25519",
|
||||||
|
"keyid": "BD07B828B2F75071",
|
||||||
|
"curve": "ed25519",
|
||||||
|
"pubkey_algo": 303,
|
||||||
|
"length": 255,
|
||||||
|
"timestamp": 1715782979,
|
||||||
|
"expires": 1810390979
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"revoked": false,
|
||||||
|
"expired": false,
|
||||||
|
"disabled": false,
|
||||||
|
"invalid": false,
|
||||||
|
"can_encrypt": true,
|
||||||
|
"can_sign": false,
|
||||||
|
"can_certify": false,
|
||||||
|
"can_authenticate": false,
|
||||||
|
"secret": false,
|
||||||
|
"is_qualified": false,
|
||||||
|
"is_cardkey": false,
|
||||||
|
"is_de_vs": false,
|
||||||
|
"pubkey_algo_name": "ECDH",
|
||||||
|
"pubkey_algo_string": "cv25519",
|
||||||
|
"keyid": "94C2E4C722CADAF9",
|
||||||
|
"curve": "cv25519",
|
||||||
|
"pubkey_algo": 302,
|
||||||
|
"length": 255,
|
||||||
|
"timestamp": 1715782979,
|
||||||
|
"expires": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"userids": [
|
||||||
|
{
|
||||||
|
"revoked": false,
|
||||||
|
"invalid": false,
|
||||||
|
"validity": "unknown",
|
||||||
|
"uid": "key-with-revokers@example.net",
|
||||||
|
"name": "",
|
||||||
|
"email": "key-with-revokers@example.net",
|
||||||
|
"comment": "",
|
||||||
|
"address": "key-with-revokers@example.net",
|
||||||
|
"origin": 0,
|
||||||
|
"last_update": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"revocation_keys": [
|
||||||
|
{
|
||||||
|
"sensitive": true,
|
||||||
|
"fingerprint": "A0FF4590BB6122EDEF6E3C542D727CC768697734",
|
||||||
|
"pubkey_algo_name": "DSA",
|
||||||
|
"pubkey_algo": 17,
|
||||||
|
"key_class": 192
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sensitive": false,
|
||||||
|
"fingerprint": "23FD347A419429BACCD5E72D6BC4778054ACD246",
|
||||||
|
"pubkey_algo_name": "DSA",
|
||||||
|
"pubkey_algo": 17,
|
||||||
|
"key_class": 128
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -308,9 +308,11 @@ main (int argc, char **argv)
|
|||||||
gpgme_user_id_t uid;
|
gpgme_user_id_t uid;
|
||||||
gpgme_tofu_info_t ti;
|
gpgme_tofu_info_t ti;
|
||||||
gpgme_key_sig_t ks;
|
gpgme_key_sig_t ks;
|
||||||
|
gpgme_revocation_key_t revkey;
|
||||||
int nuids;
|
int nuids;
|
||||||
int nsub;
|
int nsub;
|
||||||
int nsigs;
|
int nsigs;
|
||||||
|
int nrevkeys;
|
||||||
|
|
||||||
printf ("keyid : %s\n", key->subkeys?nonnull (key->subkeys->keyid):"?");
|
printf ("keyid : %s\n", key->subkeys?nonnull (key->subkeys->keyid):"?");
|
||||||
printf ("can_cap : %s%s%s%s\n",
|
printf ("can_cap : %s%s%s%s\n",
|
||||||
@ -425,6 +427,13 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revkey = key->revocation_keys;
|
||||||
|
for (nrevkeys=0; revkey; revkey = revkey->next, nrevkeys++)
|
||||||
|
{
|
||||||
|
printf ("revkey%2d: %s\n", nrevkeys, revkey->fpr);
|
||||||
|
printf (" class: %x\n", revkey->key_class);
|
||||||
|
}
|
||||||
|
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
|
|
||||||
if (import)
|
if (import)
|
||||||
|
Loading…
Reference in New Issue
Block a user