[gmime: 5/23] GPGME: report highest-validity User ID



commit d6701744522167728e074c44800e1714a39ea562
Author: Daniel Kahn Gillmor <dkg fifthhorseman net>
Date:   Mon Oct 16 00:12:25 2017 -0400

    GPGME: report highest-validity User ID
    
    An OpenPGP certificate can have multiple User IDs in it.  Some of
    those User IDs can have a different calculated validity level than
    others, depending on which ones have been certified by which third
    parties, and which third parties are trusted.  For example:
    
    pub   rsa4096 2010-08-03 [SC] [expires: 2018-03-02]
          A405E58AB3725B396ED1B85C1318EFAC5FBBDBCE
    uid           [marginal] Ximin Luo <infinity0 freenetproject org>
    uid           [ unknown] Satoshi Nakamoto (www.bitcoin.org) <satoshin gmx com>
    uid           [  full  ] Ximin Luo <infinity0 pwned gg>
    
    When selecting a single User ID (and name, and e-mail) to report out
    of GMime, we should choose the first UID of the highest-known
    validity, not just the first User ID.
    
    A more complete fix would probably include reporting all the User IDs
    of a given certificate.
    
    Or, an approach geared toward building a sensible MUA could provide a
    way to report the highest-validity User ID which happens to match the
    From: address of the e-mail message being evaluated.  But for now
    we'll just improve the behavior within the existing API.

 gmime/gmime-gpgme-utils.c |   77 +++++++++++++++++++++++++++++++++++++-------
 1 files changed, 64 insertions(+), 13 deletions(-)
---
diff --git a/gmime/gmime-gpgme-utils.c b/gmime/gmime-gpgme-utils.c
index 15ceabc..28b2b28 100644
--- a/gmime/gmime-gpgme-utils.c
+++ b/gmime/gmime-gpgme-utils.c
@@ -260,6 +260,44 @@ g_mime_gpgme_sign (gpgme_ctx_t ctx, gpgme_sig_mode_t mode, const char *userid,
        return (GMimeDigestAlgo) result->signatures->hash_algo;
 }
 
+
+/* return TRUE iff a < b */
+static gboolean
+_gpgv_lt(gpgme_validity_t a, gpgme_validity_t b) {
+       switch (a) {
+       case GPGME_VALIDITY_NEVER:
+               return b != GPGME_VALIDITY_NEVER;
+       case GPGME_VALIDITY_UNKNOWN:
+       case GPGME_VALIDITY_UNDEFINED:
+               switch (b) {
+               case GPGME_VALIDITY_NEVER:
+               case GPGME_VALIDITY_UNKNOWN:
+               case GPGME_VALIDITY_UNDEFINED:
+                       return FALSE;
+               default:
+                       return TRUE;
+               }
+       case GPGME_VALIDITY_MARGINAL:
+               switch (b) {
+               case GPGME_VALIDITY_NEVER:
+               case GPGME_VALIDITY_UNKNOWN:
+               case GPGME_VALIDITY_UNDEFINED:
+               case GPGME_VALIDITY_MARGINAL:
+                       return FALSE;
+               default:
+                       return TRUE;
+               }
+       case GPGME_VALIDITY_FULL:
+               return b == GPGME_VALIDITY_ULTIMATE;
+       case GPGME_VALIDITY_ULTIMATE:
+               return FALSE;
+       default:
+               g_assert_not_reached();
+               return FALSE;
+       }
+}
+
+
 static GMimeSignatureList *
 g_mime_gpgme_get_signatures (gpgme_ctx_t ctx, gboolean verify)
 {
@@ -298,21 +336,34 @@ g_mime_gpgme_get_signatures (gpgme_ctx_t ctx, gboolean verify)
                        g_mime_certificate_set_issuer_serial (signature->cert, key->issuer_serial);
                        g_mime_certificate_set_issuer_name (signature->cert, key->issuer_name);
                        
-                       /* get the name, email address, and full user id */
+                       gpgme_validity_t validity = GPGME_VALIDITY_NEVER;
+                       gboolean founduid = FALSE;
+                       
+                       /* get the most valid name, email address, and full user id */
                        uid = key->uids;
                        while (uid) {
-                               if (uid->name && *uid->name)
-                                       g_mime_certificate_set_name (signature->cert, uid->name);
-                               
-                               if (uid->email && *uid->email)
-                                       g_mime_certificate_set_email (signature->cert, uid->email);
-                               
-                               if (uid->uid && *uid->uid)
-                                       g_mime_certificate_set_user_id (signature->cert, uid->uid);
-                               
-                               if (signature->cert->name && signature->cert->email && 
signature->cert->user_id)
-                                       break;
-                               
+                               if (!founduid || !_gpgv_lt (uid->validity, validity)) {
+                                       /* this is as good as the best UID we've found so far */
+                                       founduid = TRUE;
+                                       if (_gpgv_lt (validity, uid->validity)) {
+                                               /* this is actually better than the last best,
+                                                  so clear all the previously-found uids */
+                                               g_mime_certificate_set_name (signature->cert, NULL);
+                                               g_mime_certificate_set_email (signature->cert, NULL);
+                                               g_mime_certificate_set_user_id (signature->cert, NULL);
+                                       }
+                                       validity = uid->validity;
+
+                                       if (uid->name && *uid->name && !g_mime_certificate_get_name 
(signature->cert))
+                                               g_mime_certificate_set_name (signature->cert, uid->name);
+                                       
+                                       if (uid->email && *uid->email && !g_mime_certificate_get_email 
(signature->cert))
+                                               g_mime_certificate_set_email (signature->cert, uid->email);
+                                       
+                                       if (uid->uid && *uid->uid && !g_mime_certificate_get_user_id 
(signature->cert))
+                                               g_mime_certificate_set_user_id (signature->cert, uid->uid);
+                                       
+                               }
                                uid = uid->next;
                        }
                        


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]