cpp: Add convenience API to obtain remarks
authorAndre Heinecke <aheinecke@gnupg.org>
Tue, 29 Oct 2019 15:24:01 +0000 (16:24 +0100)
committerAndre Heinecke <aheinecke@gnupg.org>
Tue, 29 Oct 2019 15:24:01 +0000 (16:24 +0100)
* lang/cpp/src/key.h, lang/cpp/src/key.cpp (UserID::remark): New.

--
A remark made by one key on another is a signature notation on
a user id certification signature with the name "rem@gnupg.org".

This helps with:
GnuPG-Bug-Id: T4734

lang/cpp/src/key.cpp
lang/cpp/src/key.h

index 4b37020..eb7a503 100644 (file)
@@ -723,6 +723,56 @@ TofuInfo UserID::tofuInfo() const
     return TofuInfo(uid->tofu);
 }
 
+static gpgme_key_sig_t find_last_valid_sig_for_keyid (gpgme_user_id_t uid,
+                                                      const char *keyid)
+{
+    if (!keyid) {
+        return nullptr;
+    }
+    gpgme_key_sig_t ret = NULL;
+    for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
+        if (s->keyid && !strcmp(keyid, s->keyid)) {
+            if (!s->expired && !s->revoked && !s->invalid && !s->status) {
+                if (!ret) {
+                    ret = s;
+                } else if (ret && ret->timestamp <= s->timestamp) {
+                    /* Equals because when the timestamps are the same we prefer
+                       the last in the list */
+                    ret = s;
+                }
+            }
+        }
+    }
+    return ret;
+}
+
+const char *UserID::remark(const Key &remarker, Error &err) const
+{
+    if (!uid || remarker.isNull()) {
+        err = Error::fromCode(GPG_ERR_GENERAL);
+        return nullptr;
+    }
+
+    if (!(parent().keyListMode() & GPGME_KEYLIST_MODE_SIG_NOTATIONS) ||
+        !(parent().keyListMode() & GPGME_KEYLIST_MODE_SIGS)) {
+        err = Error::fromCode(GPG_ERR_NO_DATA);
+        return nullptr;
+    }
+
+    gpgme_key_sig_t s = find_last_valid_sig_for_keyid(uid, remarker.keyID());
+
+    if (!s) {
+        return nullptr;
+    }
+
+    for (gpgme_sig_notation_t n = s->notations; n ; n = n->next) {
+        if (n->name && !strcmp(n->name, "rem@gnupg.org")) {
+            return n->value;
+        }
+    }
+    return nullptr;
+}
+
 //
 //
 // class Signature
index dd855ae..cca3c7a 100644 (file)
@@ -413,6 +413,23 @@ public:
      *
      * @returns the last update time. */
     time_t lastUpdate() const;
+
+    /*! Get a remark made by the key provided.
+     * A remark is a signature notation on
+     * this user id made by the key with the
+     * name "rem@gnupg.org". Returns an error if the
+     * parent key of this user id was not listed with the
+     * keylist mode flags for signatures and signature notations.
+     *
+     * @param key The key for which comments should be searched.
+     * @param error Set to GPG_ERR_NO_DATA if the keylist did
+     *              not include signature notations.
+     *
+     * @returns The value of the comment or NULL if none exists.
+     **/
+    const char *remark(const Key &key,
+                       Error &error) const;
+
 private:
     shared_gpgme_key_t key;
     gpgme_user_id_t uid;