[balsa] Autocrypt: fix faulty error messages



commit c9949e6b49503761e74ef77af8846272fef00d4d
Author: Albrecht Dreß <albrecht dress netcologne de>
Date:   Sun Jun 6 16:25:24 2021 +0200

    Autocrypt: fix faulty error messages
    
    Fix faulty Autocrypt error messages (false positives) which occur on the
    following conditions:
    
    (1) As g_mime_message_get_autocrypt_header() will return an object even
    if the message does *not* include an Autocrypt: header,
    balsa_mime_widget_signature_widget() will report an error for a signed
    message without such a header, but no key being available.  This is
    fixed by remembering if the message actually contains the header or not.
    (2) The Autocrypt key material must include a signing-capable subkey,
    but it is not necessarily the first subkey.  In the latter case, the
    wrong fingerprint is stored in the database.  Note that the user must
    manually remove the entry from the Autocrypt database to get rid of the
    faulty error in this case.
    
    Details:
    - libbalsa/message.[ch]: remember if the message contains an Autocrypt:
    header
    - libbalsa/autocrypt.c: loop over all Autocrypt subkeys, and return the
    fingerprint of the first signing subkey instead of the first subkey
    - src/balsa_mime_widget_crypto: emit error message about a broken
    Autocrypt header iff the message actually contains it.
    
    Signed-off-by: Albrecht Dreß <albrecht dress netcologne de>

 libbalsa/autocrypt.c           | 17 ++++++++++++++---
 libbalsa/message.c             |  6 ++++++
 libbalsa/message.h             |  6 +++++-
 src/balsa-mime-widget-crypto.c |  2 +-
 4 files changed, 26 insertions(+), 5 deletions(-)
---
diff --git a/libbalsa/autocrypt.c b/libbalsa/autocrypt.c
index c5d2ee1c4..8fab2305e 100644
--- a/libbalsa/autocrypt.c
+++ b/libbalsa/autocrypt.c
@@ -719,9 +719,20 @@ extract_ac_keydata(GMimeAutocryptHeader *autocrypt_header, ac_key_data_t *dest)
                                if (success && (keys != NULL) && (keys->next == NULL)) {
                                        gpgme_key_t key = (gpgme_key_t) keys->data;
 
-                                       if ((key != NULL) && (key->subkeys != NULL)) {
-                                               dest->fingerprint = g_strdup(key->subkeys->fpr);
-                                               dest->expires = key->subkeys->expires;
+                                       if (key != NULL) {
+                                               gpgme_subkey_t sign_subkey;
+
+                                               for (sign_subkey = key->subkeys;
+                                                        (sign_subkey != NULL) && (sign_subkey->can_sign == 
0);
+                                                        sign_subkey = sign_subkey->next);
+                                               if (sign_subkey != NULL) {
+                                                       dest->fingerprint = g_strdup(sign_subkey->fpr);
+                                                       dest->expires = sign_subkey->expires;
+                                               } else {
+                                                       g_warning("Autocrypt key for '%s' does not contain a 
signing-capable subkey",
+                                                               
g_mime_autocrypt_header_get_address_as_string(autocrypt_header));
+                                                       success = FALSE;
+                                               }
                                        } else {
                                                success = FALSE;
                                        }
diff --git a/libbalsa/message.c b/libbalsa/message.c
index ca444db8f..260dea9da 100644
--- a/libbalsa/message.c
+++ b/libbalsa/message.c
@@ -1101,6 +1101,12 @@ libbalsa_message_headers_from_gmime(LibBalsaMessageHeaders *headers,
        /* set the reference date far in the future so we can ignore messages w/o Date: header */
        reftime = g_date_time_new_from_unix_utc(time(NULL) + (365 * 24 * 60 * 60));
        headers->autocrypt_hdr = g_mime_message_get_autocrypt_header(mime_msg, reftime);
+       /* remember if the message really included an Autocrypt header, or if GMime
+        * returned an incomplete one (see
+        * https://developer.gnome.org/gmime/stable/GMimeMessage.html#g-mime-message-get-autocrypt-header).
+        */
+       headers->autocrypt_hdr_present =
+               (g_mime_object_get_header(GMIME_OBJECT(mime_msg), "autocrypt") != NULL);
        g_date_time_unref(reftime);
     }
 #endif
diff --git a/libbalsa/message.h b/libbalsa/message.h
index 519e1da47..48549b7fe 100644
--- a/libbalsa/message.h
+++ b/libbalsa/message.h
@@ -146,8 +146,12 @@ struct _LibBalsaMessageHeaders {
     GList *user_hdrs;
 
 #if defined ENABLE_AUTOCRYPT
-    /* received Autocrypt header */
+    /* received Autocrypt header data
+     * Note that g_mime_message_get_autocrypt_header() will return an object
+     * even if there is no Autocrypt: header, so we must remember if there
+     * hase been one */
     GMimeAutocryptHeader *autocrypt_hdr;
+    gboolean autocrypt_hdr_present;
 #endif
 };
 
diff --git a/src/balsa-mime-widget-crypto.c b/src/balsa-mime-widget-crypto.c
index 71878363a..fd12095e8 100644
--- a/src/balsa-mime-widget-crypto.c
+++ b/src/balsa-mime-widget-crypto.c
@@ -143,7 +143,7 @@ balsa_mime_widget_signature_widget(LibBalsaMessageBody * mime_body,
                        g_object_set_data_full(G_OBJECT(button), "autocrypt_key", autocrypt_key, 
(GDestroyNotify) g_bytes_unref);
                        g_signal_connect(button, "clicked", G_CALLBACK(on_key_import_button), NULL);
                        gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
-               } else if (libbalsa_message_get_headers(mime_body->message)->autocrypt_hdr != NULL) {
+               } else if (libbalsa_message_get_headers(mime_body->message)->autocrypt_hdr_present) {
                        libbalsa_information(LIBBALSA_INFORMATION_WARNING,
                                _("The message contains an Autocrypt header, but it is either broken "
                                  "or the signature has been created using a different key."));


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