diff options
author | Milan Crha <mcrha@redhat.com> | 2023-05-03 12:42:57 +0200 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2023-05-03 12:43:46 +0200 |
commit | 91c5abd42afb5d79ff220d834bdc27f3f4c3c3d4 (patch) | |
tree | 3eeb8371fc679dda842c85bb1e500accbce7bd33 | |
parent | da3bd1fe23258a8a4c4fea3c5bca58c038e54e3f (diff) | |
download | evolution-91c5abd42afb5d79ff220d834bdc27f3f4c3c3d4.tar.gz |
I#2345 - Wrong S/MIME certificate selection for encrypted email
Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/2345
-rw-r--r-- | src/composer/e-msg-composer.c | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c index 19d753d948..4bc1ceead8 100644 --- a/src/composer/e-msg-composer.c +++ b/src/composer/e-msg-composer.c @@ -35,6 +35,10 @@ #include <fcntl.h> #include <enchant.h> +#ifdef ENABLE_SMIME +#include <cert.h> +#endif + #include "e-composer-from-header.h" #include "e-composer-text-header.h" #include "e-composer-private.h" @@ -855,7 +859,7 @@ composer_get_recipient_certificate_cb (EMailSession *session, gpointer user_data) { AsyncContext *context = user_data; - EContactField field_id; + const gchar *field_type; GSList *link; gchar *base64_cert = NULL; @@ -865,33 +869,67 @@ composer_get_recipient_certificate_cb (EMailSession *session, return NULL; if ((flags & CAMEL_RECIPIENT_CERTIFICATE_SMIME) != 0) - field_id = E_CONTACT_X509_CERT; + field_type = "X509"; else - field_id = E_CONTACT_PGP_CERT; + field_type = "PGP"; for (link = context->recipients_with_certificate; link && !base64_cert; link = g_slist_next (link)) { EContact *contact = link->data; GList *emails, *elink; - EContactCert *cert; + gboolean email_matches = FALSE; - cert = e_contact_get (contact, field_id); - if (!cert || !cert->data || !cert->length) { - e_contact_cert_free (cert); - continue; + emails = e_contact_get (contact, E_CONTACT_EMAIL); + for (elink = emails; elink && !email_matches; elink = g_list_next (elink)) { + const gchar *contact_email = elink->data; + + email_matches = contact_email && g_ascii_strcasecmp (contact_email, email_address) == 0; } - emails = e_contact_get (contact, E_CONTACT_EMAIL); + if (email_matches) { + GList *attrs, *alink; - for (elink = emails; elink && !base64_cert; elink = g_list_next (elink)) { - const gchar *contact_email = elink->data; + attrs = e_vcard_get_attributes (E_VCARD (contact)); + for (alink = attrs; alink && !base64_cert; alink = g_list_next (alink)) { + EVCardAttribute *attr = alink->data; + GString *value; + + if (!e_vcard_attribute_has_type (attr, field_type)) + continue; + + value = e_vcard_attribute_get_value_decoded (attr); + if (!value || !value->len) { + if (value) + g_string_free (value, TRUE); + continue; + } + + /* Looking for an encryption certificate, while S/MIME can have + disabled usage for encryption, thus verify this will skip + such certificates. */ + #ifdef ENABLE_SMIME + if ((flags & CAMEL_RECIPIENT_CERTIFICATE_SMIME) != 0) { + CERTCertificate *nss_cert; + gboolean usable; + + nss_cert = CERT_DecodeCertFromPackage (value->str, value->len); + usable = nss_cert && (nss_cert->keyUsage & certificateUsageEmailRecipient) != 0; + if (nss_cert) + CERT_DestroyCertificate (nss_cert); + + if (!usable) { + g_string_free (value, TRUE); + continue; + } + } + #endif + + base64_cert = g_base64_encode ((const guchar *) value->str, value->len); - if (contact_email && g_ascii_strcasecmp (contact_email, email_address) == 0) { - base64_cert = g_base64_encode ((const guchar *) cert->data, cert->length); + g_string_free (value, TRUE); } } g_list_free_full (emails, g_free); - e_contact_cert_free (cert); } return base64_cert; |