[balsa/wip/gmime3: 173/197] Crypto performance improvements
- From: Peter Bloomfield <peterb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [balsa/wip/gmime3: 173/197] Crypto performance improvements
- Date: Wed, 23 May 2018 21:26:55 +0000 (UTC)
commit 53ef712defb8a4244868bcc939259a65389f5cff
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date: Mon Feb 12 17:59:00 2018 -0500
Crypto performance improvements
* libbalsa/body.c: calculate protection state without the key
* libbalsa/gmime-gpgme-signature.[ch]: do not try to load the key when
creating the signature object, add and rename some signature-only
related functions from rfc3156.[hc], set 'crypto' log domain
* libbalsa/libbalsa-gpgme-keys.[ch]: add function to load a public key,
properly restore the context attributes when listing keys, set 'crypto'
log domain
* libbalsa/libbalsa-gpgme-widgets.[ch]: improved function for creating a
string from the key data (shifted from rfc3156.[hc]), set 'crypto' log
domain
* libbalsa/rfc3156.[ch]: refoctoring; shift some signature-only related
functions to gmime-gpgme-signature.[ch], set 'crypto' log domain
* src/balsa-message.c: use renamed signature info functions, calculate
protection state without the key
* src/balsa-mime-widget-crypto.c: add callback to load the key when the
user wants to show it, drop condition which cannot be TRUE, use renamed
signature info functions
* src/balsa-mime-widget-message.c: use renamed signature info functions
* src/balsa-print-object-header.c: try to load the key before printing,
use renamed signature info functions
* README, configure.ac, meson.build: require gpgme ≥ 1.5.0
* libbalsa/libbalsa-gpgme.c: set 'crypto' log domain, adjust debug
messages
* libbalsa/gmime-application-pkcs7.c, libbalsa/gmime-multipart-crypt.c,
libbalsa/gmime-part-rfc2440.c, libbalsa/libbalsa-gpgme-cb.c: set
'crypto' log domain
ChangeLog | 31 ++++++
README | 1 +
configure.ac | 4 +-
libbalsa/body.c | 31 +++---
libbalsa/gmime-application-pkcs7.c | 6 +
libbalsa/gmime-gpgme-signature.c | 131 +++++++++++++++++------
libbalsa/gmime-gpgme-signature.h | 18 +++-
libbalsa/gmime-multipart-crypt.c | 6 +
libbalsa/gmime-part-rfc2440.c | 6 +
libbalsa/libbalsa-gpgme-cb.c | 6 +
libbalsa/libbalsa-gpgme-keys.c | 75 ++++++++++---
libbalsa/libbalsa-gpgme-keys.h | 15 +++
libbalsa/libbalsa-gpgme-widgets.c | 208 ++++++++++++++++++++++++++++++++----
libbalsa/libbalsa-gpgme-widgets.h | 19 +++-
libbalsa/libbalsa-gpgme.c | 30 +++---
libbalsa/rfc3156.c | 183 ++------------------------------
libbalsa/rfc3156.h | 7 --
meson.build | 4 +-
src/balsa-message.c | 13 +--
src/balsa-mime-widget-crypto.c | 66 ++++++++----
src/balsa-mime-widget-message.c | 2 +-
src/balsa-print-object-header.c | 14 ++-
22 files changed, 548 insertions(+), 328 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index fccb175..51d738b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2018-02-12 Peter Bloomfield <pbloomfield bellsouth net>
+
+ Crypto performance improvements
+
+ * libbalsa/body.c: calculate protection state without the key
+ * libbalsa/gmime-gpgme-signature.[ch]: do not try to load the key when
+ creating the signature object, add and rename some signature-only
+ related functions from rfc3156.[hc], set 'crypto' log domain
+ * libbalsa/libbalsa-gpgme-keys.[ch]: add function to load a public key,
+ properly restore the context attributes when listing keys, set 'crypto'
+ log domain
+ * libbalsa/libbalsa-gpgme-widgets.[ch]: improved function for creating a
+ string from the key data (shifted from rfc3156.[hc]), set 'crypto' log
+ domain
+ * libbalsa/rfc3156.[ch]: refoctoring; shift some signature-only related
+ functions to gmime-gpgme-signature.[ch], set 'crypto' log domain
+ * src/balsa-message.c: use renamed signature info functions, calculate
+ protection state without the key
+ * src/balsa-mime-widget-crypto.c: add callback to load the key when the
+ user wants to show it, drop condition which cannot be TRUE, use renamed
+ signature info functions
+ * src/balsa-mime-widget-message.c: use renamed signature info functions
+ * src/balsa-print-object-header.c: try to load the key before printing,
+ use renamed signature info functions
+ * README, configure.ac, meson.build: require gpgme ≥ 1.5.0
+ * libbalsa/libbalsa-gpgme.c: set 'crypto' log domain, adjust debug
+ messages
+ * libbalsa/gmime-application-pkcs7.c, libbalsa/gmime-multipart-crypt.c,
+ libbalsa/gmime-part-rfc2440.c, libbalsa/libbalsa-gpgme-cb.c: set
+ 'crypto' log domain
+
2018-02-10 Peter Bloomfield <pbloomfield bellsouth net>
Clean up generated marshalling files
diff --git a/README b/README
index 0fd5d09..3fef72e 100644
--- a/README
+++ b/README
@@ -59,6 +59,7 @@ The path of the gpgme-config tool must be specified only if it is
installed in an uncommon place. See the (rather outdated) web page
http://home.arcor.de/dralbrecht.dress/balsa/UsingGnuPG.html#FAQ
for more details.
+Note: requires GpgME version >= 1.5.0
--with-gss[=/usr/kerberos]
This enables GSSAPI Kerberos based authentication scheme.
diff --git a/configure.ac b/configure.ac
index 80ea286..6ee9c78 100644
--- a/configure.ac
+++ b/configure.ac
@@ -359,7 +359,7 @@ if test x"$gpgmecfg" != xno ; then
if test $gpgme_ve -lt 1; then
gpgmecfg=no
fi
- if test \( $gpgme_ve -eq 1 \) -a \( $gpgme_ma -lt 2 \) ; then
+ if test \( $gpgme_ve -eq 1 \) -a \( $gpgme_ma -lt 5 \) ; then
gpgmecfg=no
fi
if test x"$gpgmecfg" != xno ; then
@@ -375,7 +375,7 @@ if test x"$gpgmecfg" != xno ; then
BALSA_CFLAGS="$BALSA_CFLAGS `$gpgmecfg --cflags`"
gpgmecfg=yes
else
- AC_MSG_WARN([sorry, you need at least gpgme version 1.2.0])
+ AC_MSG_WARN([sorry, you need at least gpgme version 1.5.0])
fi
fi
AM_CONDITIONAL([BUILD_WITH_GPGME], [test $gpgmecfg = "yes"])
diff --git a/libbalsa/body.c b/libbalsa/body.c
index 609fcd6..3ab281e 100644
--- a/libbalsa/body.c
+++ b/libbalsa/body.c
@@ -883,22 +883,19 @@ libbalsa_message_body_get_by_id(LibBalsaMessageBody * body,
LibBalsaMsgProtectState
libbalsa_message_body_protect_state(LibBalsaMessageBody *body)
{
- if (!body || !body->sig_info ||
- body->sig_info->status == GPG_ERR_NOT_SIGNED ||
- body->sig_info->status == GPG_ERR_CANCELED)
- return LIBBALSA_MSG_PROTECT_NONE;
-
- if (body->sig_info->status == GPG_ERR_NO_ERROR) {
- /* good signature, check if the validity and trust (OpenPGP only) are
- at least marginal */
- if (body->sig_info->validity >= GPGME_VALIDITY_MARGINAL &&
- (body->sig_info->protocol == GPGME_PROTOCOL_CMS ||
- body->sig_info->key->owner_trust >= GPGME_VALIDITY_MARGINAL))
- return LIBBALSA_MSG_PROTECT_SIGN_GOOD;
- else
- return LIBBALSA_MSG_PROTECT_SIGN_NOTRUST;
- }
-
- return LIBBALSA_MSG_PROTECT_SIGN_BAD;
+ LibBalsaMsgProtectState state;
+
+ if ((body == NULL) || (body->sig_info == NULL) || (body->sig_info->status == GPG_ERR_NOT_SIGNED) ||
+ (body->sig_info->status == GPG_ERR_CANCELED)) {
+ state = LIBBALSA_MSG_PROTECT_NONE;
+ } else if (body->sig_info->status != GPG_ERR_NO_ERROR) {
+ state = LIBBALSA_MSG_PROTECT_SIGN_BAD;
+ } else if ((body->sig_info->summary & GPGME_SIGSUM_VALID) == GPGME_SIGSUM_VALID) {
+ state = LIBBALSA_MSG_PROTECT_SIGN_GOOD;
+ } else {
+ state = LIBBALSA_MSG_PROTECT_SIGN_NOTRUST;
+ }
+
+ return state;
}
#endif
diff --git a/libbalsa/gmime-application-pkcs7.c b/libbalsa/gmime-application-pkcs7.c
index 6d38130..44f8c04 100644
--- a/libbalsa/gmime-application-pkcs7.c
+++ b/libbalsa/gmime-application-pkcs7.c
@@ -30,6 +30,12 @@
#include <glib/gi18n.h>
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
#define GMIME_PKCS7_ERR_QUARK (g_quark_from_static_string ("gmime-app-pkcs7"))
diff --git a/libbalsa/gmime-gpgme-signature.c b/libbalsa/gmime-gpgme-signature.c
index 0d49aed..7d86530 100644
--- a/libbalsa/gmime-gpgme-signature.c
+++ b/libbalsa/gmime-gpgme-signature.c
@@ -25,10 +25,19 @@
#include <gpgme.h>
#include <string.h>
#include <glib.h>
+#include <glib/gi18n.h>
#include "libbalsa-gpgme.h"
#include "misc.h"
+#include "libbalsa.h"
+#include "libbalsa-gpgme-keys.h"
+#include "libbalsa-gpgme-widgets.h"
#include "gmime-gpgme-signature.h"
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
/* stuff for the signature status as returned by gpgme as an GObject */
static GObjectClass *g_mime_gpgme_sigstat_parent_class = NULL;
@@ -36,7 +45,6 @@ static GObjectClass *g_mime_gpgme_sigstat_parent_class = NULL;
static void g_mime_gpgme_sigstat_class_init(GMimeGpgmeSigstatClass *
klass);
static void g_mime_gpgme_sigstat_finalize(GMimeGpgmeSigstat * self);
-static void g_mime_gpgme_sigstat_init(GMimeGpgmeSigstat * self);
/* GMimeGpgmeSigstat related stuff */
@@ -55,7 +63,7 @@ g_mime_gpgme_sigstat_get_type(void)
NULL, /* class_data */
sizeof(GMimeGpgmeSigstat), /* instance_size */
0, /* n_preallocs */
- (GInstanceInitFunc) g_mime_gpgme_sigstat_init, /* instance_init */
+ NULL, /* instance_init */
/* no value_table */
};
@@ -69,11 +77,14 @@ g_mime_gpgme_sigstat_get_type(void)
GMimeGpgmeSigstat *
-g_mime_gpgme_sigstat_new(void)
+g_mime_gpgme_sigstat_new(gpgme_ctx_t ctx)
{
+ GMimeGpgmeSigstat *result;
- return
- GMIME_GPGME_SIGSTAT(g_object_new(GMIME_TYPE_GPGME_SIGSTAT, NULL));
+ result = GMIME_GPGME_SIGSTAT(g_object_new(GMIME_TYPE_GPGME_SIGSTAT, NULL));
+ result->protocol = gpgme_get_protocol(ctx);
+ result->status = GPG_ERR_NOT_SIGNED;
+ return result;
}
@@ -82,37 +93,95 @@ g_mime_gpgme_sigstat_new_from_gpgme_ctx(gpgme_ctx_t ctx)
{
GMimeGpgmeSigstat *sig_stat;
gpgme_verify_result_t result;
- gpgme_error_t err;
g_return_val_if_fail(ctx, NULL);
- if (!(sig_stat = g_mime_gpgme_sigstat_new()))
- return NULL;
-
- sig_stat->status = GPG_ERR_NOT_SIGNED; /* no signature available */
- sig_stat->protocol = gpgme_get_protocol(ctx);
+ sig_stat = g_mime_gpgme_sigstat_new(ctx);
+
+ /* try to retrieve the result of a verify operation */
+ result = gpgme_op_verify_result(ctx);
+ if ((result != NULL) && (result->signatures != NULL)) {
+ /* there is at least one signature */
+ sig_stat->fingerprint = g_strdup(result->signatures->fpr);
+ sig_stat->sign_time = result->signatures->timestamp;
+ sig_stat->summary = result->signatures->summary;
+ sig_stat->status = gpgme_err_code(result->signatures->status);
+ sig_stat->validity = result->signatures->validity;
+ }
- /* try to retreive the result of a verify operation */
- if (!(result = gpgme_op_verify_result(ctx))
- || result->signatures == NULL)
return sig_stat;
+}
+
+void
+g_mime_gpgme_sigstat_load_key(GMimeGpgmeSigstat *sigstat)
+{
+ g_return_if_fail(GMIME_IS_GPGME_SIGSTAT(sigstat));
- /* there is at least one signature */
- sig_stat->fingerprint = g_strdup(result->signatures->fpr);
- sig_stat->sign_time = result->signatures->timestamp;
- sig_stat->status = gpgme_err_code(result->signatures->status);
- sig_stat->validity = result->signatures->validity;
+ if ((sigstat->key == NULL) && ((sigstat->summary & GPGME_SIGSUM_KEY_MISSING) == 0)) {
+ gpgme_ctx_t ctx;
- /* try to get the related key */
- err = gpgme_get_key(ctx, sig_stat->fingerprint, &sig_stat->key, 0);
- if (err != GPG_ERR_NO_ERROR) {
- gchar errbuf[4096]; /* should be large enough... */
+ ctx = libbalsa_gpgme_new_with_proto(sigstat->protocol, NULL, NULL, NULL);
+ sigstat->key = libbalsa_gpgme_load_key(ctx, sigstat->fingerprint, NULL);
+ gpgme_release(ctx);
+ }
+}
- gpgme_strerror_r(err, errbuf, sizeof(errbuf));
- g_message("could not retrieve the key with fingerprint %s: %s: %s",
- sig_stat->fingerprint, gpgme_strsource(err), errbuf);
+const gchar *
+g_mime_gpgme_sigstat_protocol_name(const GMimeGpgmeSigstat *sigstat)
+{
+ g_return_val_if_fail(GMIME_IS_GPGME_SIGSTAT(sigstat), NULL);
+
+ switch (sigstat->protocol) {
+ case GPGME_PROTOCOL_OpenPGP:
+ return _("PGP signature: ");
+ case GPGME_PROTOCOL_CMS:
+ return _("S/MIME signature: ");
+ default:
+ return _("(unknown protocol) ");
}
+}
- return sig_stat;
+static inline void
+append_time_t(GString *str,
+ const gchar *format,
+ time_t when,
+ const gchar *date_string)
+{
+ if (when != (time_t) 0) {
+ gchar *tbuf = libbalsa_date_to_utf8(when, date_string);
+ g_string_append_printf(str, format, tbuf);
+ g_free(tbuf);
+ } else {
+ g_string_append_printf(str, format, _("never"));
+ }
+}
+
+gchar *
+g_mime_gpgme_sigstat_to_gchar(const GMimeGpgmeSigstat *info,
+ gboolean full_details,
+ const gchar *date_string)
+{
+ GString *msg;
+
+ g_return_val_if_fail(GMIME_IS_GPGME_SIGSTAT(info), NULL);
+ g_return_val_if_fail(date_string != NULL, NULL);
+ msg = g_string_new(g_mime_gpgme_sigstat_protocol_name(info));
+ msg = g_string_append(msg, libbalsa_gpgme_sig_stat_to_gchar(info->status));
+ g_string_append_printf(msg, _("\nSignature validity: %s"), libbalsa_gpgme_validity_to_gchar(info->
validity));
+ append_time_t(msg, _("\nSigned on: %s"), info->sign_time, date_string);
+ if (info->fingerprint) {
+ g_string_append_printf(msg, _("\nKey fingerprint: %s"), info->fingerprint);
+ }
+
+ /* append key data */
+ if (full_details && (info->key != NULL)) {
+ gchar *key_data;
+
+ key_data = libbalsa_gpgme_key_to_gchar(info->key, info->fingerprint);
+ g_string_append_printf(msg, "\n%s", key_data);
+ g_free(key_data);
+ }
+
+ return g_string_free(msg, FALSE);
}
@@ -225,11 +294,3 @@ libbalsa_cert_subject_readable(const gchar *subject)
libbalsa_utf8_sanitize(&readable_subject, TRUE, NULL);
return readable_subject;
}
-
-static void
-g_mime_gpgme_sigstat_init(GMimeGpgmeSigstat * self)
-{
- self->status = GPG_ERR_NOT_SIGNED;
- self->key = NULL;
- self->fingerprint = NULL;
-}
diff --git a/libbalsa/gmime-gpgme-signature.h b/libbalsa/gmime-gpgme-signature.h
index 06d2d10..7fde9d0 100644
--- a/libbalsa/gmime-gpgme-signature.h
+++ b/libbalsa/gmime-gpgme-signature.h
@@ -42,6 +42,7 @@ struct _GMimeGpgmeSigstat {
/* results form gpgme's verify operation */
gpgme_protocol_t protocol;
+ gpgme_sigsum_t summary;
gpgme_error_t status;
gpgme_validity_t validity;
gchar *fingerprint;
@@ -57,11 +58,20 @@ struct _GMimeGpgmeSigstatClass {
GType g_mime_gpgme_sigstat_get_type(void);
-GMimeGpgmeSigstat *g_mime_gpgme_sigstat_new(void);
-GMimeGpgmeSigstat *g_mime_gpgme_sigstat_new_from_gpgme_ctx(gpgme_ctx_t
- ctx);
+GMimeGpgmeSigstat *g_mime_gpgme_sigstat_new(gpgme_ctx_t ctx)
+ G_GNUC_WARN_UNUSED_RESULT;
+GMimeGpgmeSigstat *g_mime_gpgme_sigstat_new_from_gpgme_ctx(gpgme_ctx_t ctx)
+ G_GNUC_WARN_UNUSED_RESULT;
+void g_mime_gpgme_sigstat_load_key(GMimeGpgmeSigstat *sigstat);
-gchar *libbalsa_cert_subject_readable(const gchar *subject);
+const gchar *g_mime_gpgme_sigstat_protocol_name(const GMimeGpgmeSigstat *sigstat);
+gchar *g_mime_gpgme_sigstat_to_gchar(const GMimeGpgmeSigstat *info,
+ gboolean
full_details,
+ const gchar *date_string)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+gchar *libbalsa_cert_subject_readable(const gchar *subject)
+ G_GNUC_WARN_UNUSED_RESULT;
G_END_DECLS
diff --git a/libbalsa/gmime-multipart-crypt.c b/libbalsa/gmime-multipart-crypt.c
index 3487354..3afd965 100644
--- a/libbalsa/gmime-multipart-crypt.c
+++ b/libbalsa/gmime-multipart-crypt.c
@@ -37,6 +37,12 @@
#include "libbalsa.h"
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
/**
* sign_prepare:
* @mime_part: MIME part
diff --git a/libbalsa/gmime-part-rfc2440.c b/libbalsa/gmime-part-rfc2440.c
index 76a5ef2..586deed 100644
--- a/libbalsa/gmime-part-rfc2440.c
+++ b/libbalsa/gmime-part-rfc2440.c
@@ -29,6 +29,12 @@
#include "gmime-part-rfc2440.h"
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
#define RFC2440_BUF_LEN 4096
diff --git a/libbalsa/libbalsa-gpgme-cb.c b/libbalsa/libbalsa-gpgme-cb.c
index 4c18fb1..ce45566 100644
--- a/libbalsa/libbalsa-gpgme-cb.c
+++ b/libbalsa/libbalsa-gpgme-cb.c
@@ -40,6 +40,12 @@
#include "libbalsa-gpgme-cb.h"
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
/* stuff to get a key fingerprint from a selection list */
enum {
GPG_KEY_USER_ID_COLUMN = 0,
diff --git a/libbalsa/libbalsa-gpgme-keys.c b/libbalsa/libbalsa-gpgme-keys.c
index 6025219..f45566e 100644
--- a/libbalsa/libbalsa-gpgme-keys.c
+++ b/libbalsa/libbalsa-gpgme-keys.c
@@ -27,6 +27,12 @@
#include "libbalsa-gpgme.h"
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
/* key server thread data */
typedef struct _keyserver_op_t {
gpgme_ctx_t gpgme_ctx;
@@ -64,19 +70,18 @@ libbalsa_gpgme_list_keys(gpgme_ctx_t ctx,
gboolean on_keyserver,
GError **error)
{
- gpgme_error_t gpgme_err = GPG_ERR_NO_ERROR;
+ gpgme_error_t gpgme_err;
+ gpgme_keylist_mode_t kl_save;
gpgme_keylist_mode_t kl_mode;
g_return_val_if_fail((ctx != NULL) && (keys != NULL), FALSE);
/* set key list mode to external if we want to search a remote key server, or to the local key ring */
- kl_mode = gpgme_get_keylist_mode(ctx);
+ kl_save = gpgme_get_keylist_mode(ctx);
if (on_keyserver) {
- kl_mode &= ~GPGME_KEYLIST_MODE_LOCAL;
- kl_mode |= GPGME_KEYLIST_MODE_EXTERN;
+ kl_mode = (kl_save & ~GPGME_KEYLIST_MODE_LOCAL) | GPGME_KEYLIST_MODE_EXTERN;
} else {
- kl_mode &= ~GPGME_KEYLIST_MODE_EXTERN;
- kl_mode |= GPGME_KEYLIST_MODE_LOCAL;
+ kl_mode = (kl_save & ~GPGME_KEYLIST_MODE_EXTERN) | GPGME_KEYLIST_MODE_LOCAL;
}
gpgme_err = gpgme_set_keylist_mode(ctx, kl_mode);
if (gpgme_err != GPG_ERR_NO_ERROR) {
@@ -127,11 +132,58 @@ libbalsa_gpgme_list_keys(gpgme_ctx_t ctx,
}
}
}
+ gpgme_set_keylist_mode(ctx, kl_save);
return (gpgme_err_code(gpgme_err) == GPG_ERR_EOF);
}
+gpgme_key_t
+libbalsa_gpgme_load_key(gpgme_ctx_t ctx,
+ const gchar *fingerprint,
+ GError **error)
+{
+ gpgme_key_t key = NULL;
+ gpgme_error_t gpgme_err;
+ gpgme_keylist_mode_t kl_mode;
+
+ g_return_val_if_fail((ctx != NULL) && (fingerprint != NULL), NULL);
+
+ /* only use the local key ring */
+ kl_mode = gpgme_get_keylist_mode(ctx);
+ gpgme_err = gpgme_set_keylist_mode(ctx, (kl_mode & ~GPGME_KEYLIST_MODE_EXTERN) |
GPGME_KEYLIST_MODE_LOCAL);
+ if (gpgme_err != GPG_ERR_NO_ERROR) {
+ libbalsa_gpgme_set_error(error, gpgme_err, _("error setting key list mode"));
+ }
+
+ if (gpgme_err == GPG_ERR_NO_ERROR) {
+ gpgme_err = gpgme_op_keylist_start(ctx, fingerprint, 0);
+ if (gpgme_err != GPG_ERR_NO_ERROR) {
+ libbalsa_gpgme_set_error(error, gpgme_err, _("could not list keys for “%s”"),
fingerprint);
+ } else {
+ gpgme_err = gpgme_op_keylist_next(ctx, &key);
+ if (gpgme_err != GPG_ERR_NO_ERROR) {
+ libbalsa_gpgme_set_error(error, gpgme_err, _("could not list keys for “%s”"),
fingerprint);
+ } else {
+ gpgme_key_t next_key;
+
+ /* verify this is the only one */
+ gpgme_err = gpgme_op_keylist_next(ctx, &next_key);
+ if (gpgme_err == GPG_ERR_NO_ERROR) {
+ libbalsa_gpgme_set_error(error, GPG_ERR_AMBIGUOUS, _("ambiguous keys
for “%s”"), fingerprint);
+ gpgme_key_unref(next_key);
+ gpgme_key_unref(key);
+ key = NULL;
+ }
+ }
+ }
+ }
+ gpgme_set_keylist_mode(ctx, kl_mode);
+
+ return key;
+}
+
+
/* documentation: see header file */
gboolean
libbalsa_gpgme_keyserver_op(const gchar *fingerprint,
@@ -412,16 +464,7 @@ gpgme_import_key(gpgme_ctx_t ctx,
/* the key has been considered: load the possibly changed key from the local ring, ignoring
any errors */
if ((import_result->considered != 0) && (key->subkeys != NULL)) {
- gpgme_keylist_mode_t kl_mode;
-
- /* ensure local key list mode */
- kl_mode = gpgme_get_keylist_mode(ctx);
- kl_mode &= ~GPGME_KEYLIST_MODE_EXTERN;
- kl_mode |= GPGME_KEYLIST_MODE_LOCAL;
- gpgme_err = gpgme_set_keylist_mode(ctx, kl_mode);
- if (gpgme_err == GPG_ERR_NO_ERROR) {
- (void) gpgme_get_key(ctx, key->subkeys->fpr, imported_key, 0);
- }
+ *imported_key = libbalsa_gpgme_load_key(ctx, key->subkeys->fpr, error);
}
result = TRUE;
diff --git a/libbalsa/libbalsa-gpgme-keys.h b/libbalsa/libbalsa-gpgme-keys.h
index aee10b8..dcef961 100644
--- a/libbalsa/libbalsa-gpgme-keys.h
+++ b/libbalsa/libbalsa-gpgme-keys.h
@@ -63,6 +63,21 @@ gboolean libbalsa_gpgme_list_keys(gpgme_ctx_t ctx,
gboolean on_keyserver,
GError **error);
+/** \brief Load a key
+ *
+ * \param ctx GpgME context
+ * \param fingerprint key fingerprint to search for
+ * \param error filled with error information on error, may be NULL
+ * \return the key matching the passed fingerprint, or NULL on error
+ *
+ * Return the key matching the passed fingerprint from the local key ring. The function returns NULL if
either no or more than one
+ * key is available.
+ */
+gpgme_key_t libbalsa_gpgme_load_key(gpgme_ctx_t ctx,
+ const gchar *fingerprint,
+ GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+
/** \brief Search the key server for a key
*
* \param fingerprint key fingerprint to search for
diff --git a/libbalsa/libbalsa-gpgme-widgets.c b/libbalsa/libbalsa-gpgme-widgets.c
index 87967a6..58747e4 100644
--- a/libbalsa/libbalsa-gpgme-widgets.c
+++ b/libbalsa/libbalsa-gpgme-widgets.c
@@ -2,7 +2,7 @@
/*
* Balsa E-Mail Client
*
- * gpgme -related widgets
+ * gpgme key related widgets and display functions
* Copyright (C) 2017 Albrecht Dreß <albrecht dress arcor de>
*
* This program is free software; you can redistribute it and/or modify
@@ -26,11 +26,25 @@
#include "rfc3156.h"
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
+
+#define BULLET_STR "\302\240\342\200\242\302\240"
+
+
static gchar *create_status_str(gboolean revoked,
gboolean expired,
gboolean disabled,
gboolean invalid)
G_GNUC_WARN_UNUSED_RESULT;
+static gchar *create_uid_str(const gpgme_user_id_t uid,
+ gboolean *warn)
+ G_GNUC_WARN_UNUSED_RESULT;
+
static gint create_key_grid_row(GtkGrid *grid,
gint row,
const gchar *key,
@@ -195,6 +209,134 @@ libbalsa_gpgme_key(gpgme_key_t key,
}
+/* documentation: see header file */
+gchar *
+libbalsa_gpgme_key_to_gchar(gpgme_key_t key,
+ const gchar *fingerprint)
+{
+ GString *result;
+ gchar *status_str;
+
+ g_return_val_if_fail((key != NULL) && (fingerprint != NULL), NULL);
+
+ result = g_string_new(NULL);
+
+ /* print a warning for a bad key status */
+ status_str = create_status_str(key->expired != 0U, key->revoked != 0U, key->disabled != 0U,
key->invalid != 0U);
+ if (strlen(status_str) > 0U) {
+ g_string_append_printf(result, "%s %s\n", _("Key status:"), status_str);
+ }
+ g_free(status_str);
+
+ /* primary User ID */
+ if (key->uids == NULL) {
+ g_string_append_printf(result, "%s %s", _("User ID:"), _("None"));
+ } else {
+ gchar *uid_str;
+
+ uid_str = create_uid_str(key->uids, NULL);
+ if (key->uids->next != NULL) {
+ g_string_append_printf(result, "%s %s", _("Primary user ID:"), uid_str);
+ } else {
+ g_string_append_printf(result, "%s %s", _("User ID:"), uid_str);
+ }
+ g_free(uid_str);
+ }
+
+ /* owner trust is valid for OpenPGP only */
+ if (key->protocol == GPGME_PROTOCOL_OpenPGP) {
+ g_string_append_printf(result, "\n%s %s", _("Key owner trust:"),
libbalsa_gpgme_validity_to_gchar_short(key->owner_trust));
+ }
+
+ /* add additional UID's (if any) */
+ if ((key->uids != NULL) && (key->uids->next != NULL)) {
+ gpgme_user_id_t uid;
+
+ g_string_append_printf(result, "\n%s", _("Additional User IDs"));
+ for (uid = key->uids->next; uid != NULL; uid = uid->next) {
+ gchar *uid_str;
+
+ uid_str = create_uid_str(uid, NULL);
+ g_string_append_printf(result, "\n" BULLET_STR "%s", uid_str);
+ g_free(uid_str);
+ }
+ }
+
+ /* add the issuer information for CMS only */
+ if (key->protocol == GPGME_PROTOCOL_CMS) {
+ g_string_append_printf(result, "\n%s", _("Issuer"));
+
+ if (key->issuer_name != NULL) {
+ gchar *issuer_readable;
+
+ issuer_readable = libbalsa_cert_subject_readable(key->issuer_name);
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Name:"), issuer_readable);
+ g_free(issuer_readable);
+ }
+ if (key->issuer_serial != NULL) {
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Serial number:"),
key->issuer_serial);
+ }
+ if (key->chain_id != NULL) {
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Chain ID:"),
key->chain_id);
+ }
+ }
+
+ /* subkey information */
+ if (key->subkeys != NULL) {
+ gpgme_subkey_t subkey;
+
+ g_string_append_printf(result, "\n%s", _("Subkey used"));
+ for (subkey = key->subkeys; subkey != NULL; subkey = subkey->next) {
+ if (strcmp(fingerprint, subkey->fpr) == 0) {
+ gchar *details_str;
+ gchar *timebuf;
+
+ details_str = create_status_str(subkey->expired != 0U, subkey->revoked != 0U,
subkey->disabled != 0U,
+ subkey->invalid != 0U);
+ if (strlen(details_str) > 0U) {
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Status:"),
details_str);
+ }
+ g_free(details_str);
+
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Fingerprint:"),
subkey->fpr);
+
+ details_str = create_subkey_type_str(subkey);
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Type:"),
details_str);
+ g_free(details_str);
+
+ details_str = create_purpose_str(subkey->can_sign != 0U, subkey->can_encrypt
!= 0, subkey->can_certify != 0U,
+ subkey->can_authenticate != 0U);
+ if (strlen(details_str) > 0U) {
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s",
_("Capabilities:"), details_str);
+ }
+ g_free(details_str);
+
+ if (subkey->timestamp == -1) {
+ timebuf = g_strdup(_("invalid timestamp"));
+ } else if (subkey->timestamp == 0) {
+ timebuf = g_strdup(_("not available"));
+ } else {
+ timebuf = libbalsa_date_to_utf8(subkey->timestamp, "%x %X");
+ }
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Created:"),
timebuf);
+ g_free(timebuf);
+
+ if (subkey->expires == 0) {
+ timebuf = g_strdup(_("never"));
+ } else {
+ timebuf = libbalsa_date_to_utf8(subkey->expires, "%x %X");
+ }
+ g_string_append_printf(result, "\n" BULLET_STR "%s %s", _("Expires:"),
timebuf);
+ g_free(timebuf);
+ }
+ }
+ }
+
+ return g_string_free(result, FALSE);
+}
+
+
+/* documentation: see header file */
GtkWidget *
libbalsa_key_dialog(GtkWindow *parent,
GtkButtonsType buttons,
@@ -310,6 +452,44 @@ create_status_str(gboolean revoked,
}
+/** \brief Create a UID string
+ *
+ * \param uid UID
+ * \param warn filled with TRUE if the UID is revoked or invalid
+ * \return a newly allocated string containing the UID string
+ *
+ * Create a string containing the passed UID subject. If the UID is revoked or invalid, the status
information is added in '(…)'.
+ *
+ * \todo Do we want to add more details from the gpgme_user_id_t data?
+ */
+static gchar *
+create_uid_str(const gpgme_user_id_t uid, gboolean *warn)
+{
+ gchar *uid_readable;
+ gchar *uid_status;
+ gchar *result;
+ gboolean do_warn;
+
+ uid_readable = libbalsa_cert_subject_readable(uid->uid);
+ uid_status = create_status_str(uid->revoked != 0U, FALSE, FALSE, uid->invalid != 0U);
+ if (uid_status[0] != '\0') {
+ result = g_strdup_printf("%s (%s)", uid_readable, uid_status);
+ g_free(uid_readable);
+ g_free(uid_status);
+ do_warn = TRUE;
+ } else {
+ result = uid_readable;
+ do_warn = FALSE;
+ }
+
+ if (warn != NULL) {
+ *warn = do_warn;
+ }
+
+ return result;
+}
+
+
/** \brief Add a grid row
*
* \param grid target grid
@@ -349,29 +529,21 @@ create_key_grid_row(GtkGrid *grid,
* Create a widget containing the passed UID subject. If the UID is revoked or invalid, a warning icon is
prepended, and the
* status information is added.
*
+ * \sa create_uid_str()
+ *
* \todo We might want to show the TOFU data (requires gpgme >= 1.7.0, and GPGME_KEYLIST_MODE_WITH_TOFU in
key listing options).
* Maybe also add an expander?
*/
static GtkWidget *
create_key_uid_widget(const gpgme_user_id_t uid)
{
- gchar *uid_readable;
- gchar *uid_status;
+ gchar *buf;
+ gboolean warn;
GtkWidget *result;
- uid_readable = libbalsa_cert_subject_readable(uid->uid);
- uid_status = create_status_str(uid->revoked != 0U, FALSE, FALSE, uid->invalid != 0U);
- if (strlen(uid_status) > 0U) {
- gchar *buf;
-
- buf = g_strdup_printf("%s (%s)", uid_readable, uid_status);
- result = create_key_label_with_warn(buf, TRUE);
- g_free(buf);
- } else {
- result = create_key_label_with_warn(uid_readable, FALSE);
- }
- g_free(uid_status);
- g_free(uid_readable);
+ buf = create_uid_str(uid, &warn);
+ result = create_key_label_with_warn(buf, warn);
+ g_free(buf);
return result;
}
@@ -525,7 +697,7 @@ create_purpose_str(gboolean can_sign,
* \return a newly allocated string containing a human-readable description of the subkey type
*
* Create a string containing the length of the subkey in bits, the public key algorithm supported by it and
for ECC algorithms the
- * name of the curve. Note that the latter is available for Gpgme >= 1.5.0 only.
+ * name of the curve.
*/
static gchar *
create_subkey_type_str(gpgme_subkey_t subkey)
@@ -539,11 +711,9 @@ create_subkey_type_str(gpgme_subkey_t subkey)
if (algo != NULL) {
g_string_append_printf(type_str, " %s", algo);
}
-#if GPGME_VERSION_NUMBER >= 0x010500
if (subkey->curve != NULL) {
g_string_append_printf(type_str, _(" curve “%s”"), subkey->curve);
}
-#endif
return g_string_free(type_str, FALSE);
}
diff --git a/libbalsa/libbalsa-gpgme-widgets.h b/libbalsa/libbalsa-gpgme-widgets.h
index 21723be..0cda361 100644
--- a/libbalsa/libbalsa-gpgme-widgets.h
+++ b/libbalsa/libbalsa-gpgme-widgets.h
@@ -2,7 +2,7 @@
/*
* Balsa E-Mail Client
*
- * gpgme -related widgets
+ * gpgme key related widgets and display functions
* Copyright (C) 2017 Albrecht Dreß <albrecht dress arcor de>
*
* This program is free software; you can redistribute it and/or modify
@@ -48,7 +48,7 @@ typedef enum {
/** \brief Create a key widget
*
* \param key GnuPG or S/MIME key
- * \param fingerprint fingerprint of the subkey which shall be displayed, NULL to display all subkeys
+ * \param fingerprint fingerprint of the subkey which shall be displayed, NULL to display all subkeys with
certain capabilities
* \param subkey_capa mask of capabilities for which subkeys shall be included, used only if \em fingerprint
is NULL
* \param expanded whether the expanders shall be initially expanded
* \return a new widget containing details about the key
@@ -64,6 +64,21 @@ GtkWidget *libbalsa_gpgme_key(gpgme_key_t key,
G_GNUC_WARN_UNUSED_RESULT;
+/** \brief Key details as human-readable string
+ *
+ * \param key GnuPG or S/MIME key
+ * \param fingerprint fingerprint of the subkey which shall be printed, <i>must not</i> be NULL
+ * \return a newly allocated string containing the key details
+ *
+ * Create a human-readable multiline string containing the key details, including the details of the subkey
identified by the
+ * passed fingerprint. The string is basically a printable version of libbalsa_gpgme_key() for the same key
and fingerprint, with
+ * the expanders opened.
+ */
+gchar *libbalsa_gpgme_key_to_gchar(gpgme_key_t key,
+ const gchar *fingerprint)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+
/** \brief Create a key message dialogue
*
* \param parent transient parent window, may be NULL
diff --git a/libbalsa/libbalsa-gpgme.c b/libbalsa/libbalsa-gpgme.c
index 4acf9da..a093e69 100644
--- a/libbalsa/libbalsa-gpgme.c
+++ b/libbalsa/libbalsa-gpgme.c
@@ -42,6 +42,12 @@
#include "libbalsa.h"
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
static gboolean gpgme_add_signer(gpgme_ctx_t ctx, const gchar * signer,
GtkWindow * parent, GError ** error);
static gpgme_key_t *gpgme_build_recipients(gpgme_ctx_t ctx,
@@ -107,7 +113,7 @@ libbalsa_gpgme_init(gpgme_passphrase_cb_t get_passphrase,
const gchar *agent_info;
/* initialise the gpgme library */
- g_message("init gpgme version %s", gpgme_check_version(NULL));
+ g_debug("init gpgme version %s", gpgme_check_version(NULL));
#ifdef ENABLE_NLS
gpgme_set_locale(NULL, LC_CTYPE, get_utf8_locale(LC_CTYPE));
@@ -117,7 +123,7 @@ libbalsa_gpgme_init(gpgme_passphrase_cb_t get_passphrase,
/* dump the available engines */
if (gpgme_get_engine_info(&e) == GPG_ERR_NO_ERROR) {
while (e) {
- g_message("protocol %s: engine %s (home %s, version %s)",
+ g_debug("protocol %s: engine %s (home %s, version %s)",
gpgme_get_protocol_name(e->protocol),
e->file_name, e->home_dir, e->version);
e = e->next;
@@ -127,8 +133,8 @@ libbalsa_gpgme_init(gpgme_passphrase_cb_t get_passphrase,
/* check for gpg-agent */
agent_info = g_getenv("GPG_AGENT_INFO");
if (agent_info) {
- g_message("gpg-agent found: %s", agent_info);
- gpgme_passphrase_cb = NULL;
+ g_debug("gpg-agent found: %s", agent_info);
+ gpgme_passphrase_cb = NULL;
} else {
gpgme_passphrase_cb = get_passphrase;
}
@@ -136,19 +142,18 @@ libbalsa_gpgme_init(gpgme_passphrase_cb_t get_passphrase,
/* verify that the engines we need are there */
if (gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP) ==
GPG_ERR_NO_ERROR) {
- g_message("OpenPGP protocol supported");
- has_proto_openpgp = TRUE;
+ g_debug("OpenPGP protocol supported");
+ has_proto_openpgp = TRUE;
} else {
- g_message
- ("OpenPGP protocol not supported, basic crypto will not work!");
- has_proto_openpgp = FALSE;
+ g_warning("OpenPGP protocol not supported, basic crypto will not work!");
+ has_proto_openpgp = FALSE;
}
if (gpgme_engine_check_version(GPGME_PROTOCOL_CMS) == GPG_ERR_NO_ERROR) {
- g_message("CMS (aka S/MIME) protocol supported");
+ g_debug("CMS (aka S/MIME) protocol supported");
has_proto_cms = TRUE;
} else {
- g_message("CMS protocol not supported, S/MIME will not work!");
+ g_warning("CMS protocol not supported, S/MIME will not work!");
has_proto_cms = FALSE;
}
@@ -341,9 +346,8 @@ libbalsa_gpgme_verify(GMimeStream * content, GMimeStream * sig_plain,
if (err != GPG_ERR_NO_ERROR) {
libbalsa_gpgme_set_error(error, err,
_("signature verification failed"));
- result = g_mime_gpgme_sigstat_new();
+ result = g_mime_gpgme_sigstat_new(ctx);
result->status = err;
- result->protocol = gpgme_get_protocol(ctx);
} else
result = g_mime_gpgme_sigstat_new_from_gpgme_ctx(ctx);
diff --git a/libbalsa/rfc3156.c b/libbalsa/rfc3156.c
index 170602c..37c0429 100644
--- a/libbalsa/rfc3156.c
+++ b/libbalsa/rfc3156.c
@@ -45,6 +45,12 @@
#include <glib/gi18n.h>
+#ifdef G_LOG_DOMAIN
+# undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "crypto"
+
+
/* local prototypes */
static gboolean gpg_updates_trustdb(void);
static gboolean have_pub_key_for(gpgme_ctx_t gpgme_ctx,
@@ -646,7 +652,7 @@ libbalsa_gpgme_sig_stat_to_gchar(gpgme_error_t stat)
gchar errbuf[4096]; /* should be large enough... */
gpgme_strerror_r(stat, errbuf, sizeof(errbuf));
- g_message("stat %d: %s %s", stat, gpgme_strsource(stat), errbuf);
+ g_debug("%s: stat %d: %s %s", __func__, stat, gpgme_strsource(stat), errbuf);
return _("An error prevented the signature verification.");
}
}
@@ -697,181 +703,6 @@ libbalsa_gpgme_validity_to_gchar_short(gpgme_validity_t validity)
}
-const gchar *
-libbalsa_gpgme_sig_protocol_name(gpgme_protocol_t protocol)
-{
- switch (protocol) {
- case GPGME_PROTOCOL_OpenPGP:
- return _("PGP signature: ");
- case GPGME_PROTOCOL_CMS:
- return _("S/MIME signature: ");
- default:
- return _("(unknown protocol) ");
- }
-}
-
-static inline void
-append_time_t(GString *str, const gchar *format, time_t when,
- const gchar * date_string)
-{
- if (when != (time_t) 0) {
- gchar *tbuf = libbalsa_date_to_utf8(when, date_string);
- g_string_append_printf(str, format, tbuf);
- g_free(tbuf);
- } else {
- g_string_append_printf(str, format, _("never"));
- }
-}
-
-gchar *
-libbalsa_signature_info_to_gchar_short(GMimeGpgmeSigstat *info,
- const gchar *date_string)
-{
- GString *msg;
- gchar *retval;
-
- g_return_val_if_fail(info != NULL, NULL);
- g_return_val_if_fail(date_string != NULL, NULL);
- msg = g_string_new(libbalsa_gpgme_sig_protocol_name(info->protocol));
- msg = g_string_append(msg, libbalsa_gpgme_sig_stat_to_gchar(info->status));
- g_string_append_printf(msg, _("\nSignature validity: %s"), libbalsa_gpgme_validity_to_gchar(info->
validity));
- append_time_t(msg, _("\nSigned on: %s"), info->sign_time, date_string);
- if (info->fingerprint) {
- g_string_append_printf(msg, _("\nKey fingerprint: %s"), info->fingerprint);
- }
-
- retval = msg->str;
- g_string_free(msg, FALSE);
- return retval;
-}
-
-gchar *
-libbalsa_signature_info_to_gchar(GMimeGpgmeSigstat *info,
- const gchar *date_string)
-{
- GString *msg;
- gchar *retval;
-
- g_return_val_if_fail(info != NULL, NULL);
- g_return_val_if_fail(date_string != NULL, NULL);
- msg = g_string_new(libbalsa_signature_info_to_gchar_short(info, date_string));
-
- /* add key information */
- if (info->key != NULL) {
- gpgme_user_id_t uid;
- gpgme_subkey_t subkey;
-
- if (info->protocol == GPGME_PROTOCOL_OpenPGP) {
- g_string_append_printf(msg, _("\nKey owner trust: %s"),
libbalsa_gpgme_validity_to_gchar_short(info->key->owner_trust));
- }
-
- /* user ID's */
- if ((uid = info->key->uids)) {
- gchar *lead_text;
-
- uid = info->key->uids;
- if (uid->next) {
- msg = g_string_append(msg, _("\nUser IDs:"));
- lead_text = "\n\342\200\242";
- } else {
- msg = g_string_append(msg, _("\nUser ID:"));
- lead_text = "";
- }
-
- /* Note: there is no way to determine which user id has been used
- * to create the signature. A broken client may even use an
- * invalid and/or revoked one. We therefore add all to the
- * result. */
- while (uid) {
- msg = g_string_append(msg, lead_text);
- if (uid->revoked)
- msg = g_string_append(msg, _(" [Revoked]"));
- if (uid->invalid)
- msg = g_string_append(msg, _(" [Invalid]"));
-
- if (uid->uid && *(uid->uid)) {
- gchar *uid_readable =
- libbalsa_cert_subject_readable(uid->uid);
- g_string_append_printf(msg, " %s", uid_readable);
- g_free(uid_readable);
- } else {
- if (uid->name && *(uid->name))
- g_string_append_printf(msg, " %s", uid->name);
- if (uid->email && *(uid->email))
- g_string_append_printf(msg, " <%s>", uid->email);
- if (uid->comment && *(uid->comment))
- g_string_append_printf(msg, " (%s)", uid->comment);
- }
-
- uid = uid->next;
- }
- }
-
- /* subkey */
- if ((subkey = info->key->subkeys)) {
- /* find the one which can sign */
- while (subkey && !subkey->can_sign)
- subkey = subkey->next;
-
- if (subkey) {
- append_time_t(msg, _("\nSubkey created on: %s"),
- subkey->timestamp, date_string);
- append_time_t(msg, _("\nSubkey expires on: %s"),
- subkey->expires, date_string);
- if (subkey->revoked || subkey->expired || subkey->disabled ||
- subkey->invalid) {
- GString * attrs = g_string_new("");
- int count = 0;
-
- if (subkey->revoked) {
- count++;
- attrs = g_string_append(attrs, _(" revoked"));
- }
- if (subkey->expired) {
- if (count++)
- attrs = g_string_append_c(attrs, ',');
- attrs = g_string_append(attrs, _(" expired"));
- }
- if (subkey->disabled) {
- if (count)
- attrs = g_string_append_c(attrs, ',');
- attrs = g_string_append(attrs, _(" disabled"));
- }
- if (subkey->invalid) {
- if (count)
- attrs = g_string_append_c(attrs, ',');
- attrs = g_string_append(attrs, _(" invalid"));
- }
- /* ngettext: string begins with a single space, so no space
- * after the colon is correct punctuation (in English). */
- g_string_append_printf(msg, ngettext("\nSubkey attribute:%s",
- "\nSubkey attributes:%s",
- count),
- attrs->str);
- g_string_free(attrs, TRUE);
- }
- }
- }
-
- if (info->key->issuer_name) {
- gchar *issuer_name =
- libbalsa_cert_subject_readable(info->key->issuer_name);
- g_string_append_printf(msg, _("\nIssuer name: %s"), issuer_name);
- g_free(issuer_name);
- }
- if (info->key->issuer_serial)
- g_string_append_printf(msg, _("\nIssuer serial number: %s"),
- info->key->issuer_serial);
- if (info->key->chain_id)
- g_string_append_printf(msg, _("\nChain ID: %s"), info->key->chain_id);
- }
-
- retval = msg->str;
- g_string_free(msg, FALSE);
- return retval;
-}
-
-
/* ==== local stuff ======================================================== */
diff --git a/libbalsa/rfc3156.h b/libbalsa/rfc3156.h
index dfb641a..6a34d20 100644
--- a/libbalsa/rfc3156.h
+++ b/libbalsa/rfc3156.h
@@ -101,16 +101,9 @@ gpgme_error_t libbalsa_rfc2440_decrypt(GMimePart * part,
GtkWindow * parent);
/* helper functions to convert states to human-readable form */
-const gchar *libbalsa_gpgme_sig_protocol_name(gpgme_protocol_t protocol);
const gchar *libbalsa_gpgme_sig_stat_to_gchar(gpgme_error_t stat);
const gchar *libbalsa_gpgme_validity_to_gchar(gpgme_validity_t validity);
const gchar *libbalsa_gpgme_validity_to_gchar_short(gpgme_validity_t validity);
-gchar *libbalsa_signature_info_to_gchar(GMimeGpgmeSigstat *info,
- const gchar
*date_string)
- G_GNUC_WARN_UNUSED_RESULT;
-gchar *libbalsa_signature_info_to_gchar_short(GMimeGpgmeSigstat *info,
- const gchar
*date_string)
- G_GNUC_WARN_UNUSED_RESULT;
#endif /* HAVE_GPGME */
#endif /* __RFC3156_H__ */
diff --git a/meson.build b/meson.build
index fa90ddf..bee39c9 100644
--- a/meson.build
+++ b/meson.build
@@ -249,9 +249,9 @@ endif
if gpgmecfg != 'false'
gpgmever = run_command(gpgmecfg, '--version').stdout().strip()
- if gpgmever.version_compare('< 1.2.0')
+ if gpgmever.version_compare('< 1.5.0')
gpgmecfg = 'false'
- message('Sorry, you need at least gpgme version 1.2.0')
+ message('Sorry, you need at least gpgme version 1.5.0')
else
if gpgmever.version_compare('< 1.8.0')
gpgme_libs = run_command(gpgmecfg, '--thread=pthread', '--libs')
diff --git a/src/balsa-message.c b/src/balsa-message.c
index af3150f..5508793 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -2743,11 +2743,11 @@ get_crypto_content_icon(LibBalsaMessageBody * body, const gchar * content_type,
g_ascii_strcasecmp(content_type, "application/pkcs7-signature") &&
g_ascii_strcasecmp(content_type, "application/x-pkcs7-signature"))
new_title = g_strconcat(*icon_title, "; ",
- libbalsa_gpgme_sig_protocol_name(body->sig_info->protocol),
+ g_mime_gpgme_sigstat_protocol_name(body->sig_info),
libbalsa_gpgme_sig_stat_to_gchar(body->sig_info->status),
NULL);
else
- new_title = g_strconcat(libbalsa_gpgme_sig_protocol_name(body->sig_info->protocol),
+ new_title = g_strconcat(g_mime_gpgme_sigstat_protocol_name(body->sig_info),
libbalsa_gpgme_sig_stat_to_gchar(body->sig_info->status),
NULL);
@@ -3089,15 +3089,14 @@ libbalsa_msg_part_2440(LibBalsaMessage * message, LibBalsaMessageBody * body,
libbalsa_mailbox_unlock_store(body->message->mailbox);
if (body->sig_info && sig_res == GPG_ERR_NO_ERROR) {
- if (body->sig_info->validity >= GPGME_VALIDITY_MARGINAL &&
- body->sig_info->key->owner_trust >= GPGME_VALIDITY_MARGINAL)
- libbalsa_information(LIBBALSA_INFORMATION_DEBUG,
- _("Detected a good signature"));
- else
+ if ((body->sig_info->summary & GPGME_SIGSUM_VALID) == GPGME_SIGSUM_VALID) {
+ g_debug("%s: detected a good signature", __func__);
+ } else {
libbalsa_information
(LIBBALSA_INFORMATION_MESSAGE,
_("Detected a good signature with insufficient "
"validity/trust"));
+ }
} else if (sig_res != GPG_ERR_NO_ERROR && sig_res != GPG_ERR_CANCELED)
libbalsa_information
(chk_crypto->chk_mode == LB_MAILBOX_CHK_CRYPT_ALWAYS ?
diff --git a/src/balsa-mime-widget-crypto.c b/src/balsa-mime-widget-crypto.c
index 0ce7189..73a15dd 100644
--- a/src/balsa-mime-widget-crypto.c
+++ b/src/balsa-mime-widget-crypto.c
@@ -36,6 +36,7 @@
static void on_gpg_key_button(GtkWidget *button, const gchar *fingerprint);
static void on_key_import_button(GtkButton *button, gpointer user_data);
static gboolean create_import_keys_widget(GtkBox *box, const gchar *key_buf, GError **error);
+static void show_public_key_data(GtkExpander *expander, gpointer user_data);
BalsaMimeWidget *
@@ -97,6 +98,7 @@ balsa_mime_widget_signature_widget(LibBalsaMessageBody * mime_body,
const gchar * content_type)
{
gchar *infostr;
+ GtkWidget *expander;
GtkWidget *vbox, *label;
GtkWidget *signature_widget;
gchar **lines;
@@ -105,8 +107,7 @@ balsa_mime_widget_signature_widget(LibBalsaMessageBody * mime_body,
mime_body->sig_info->status == GPG_ERR_NOT_SIGNED)
return NULL;
- infostr =
- libbalsa_signature_info_to_gchar_short(mime_body->sig_info, balsa_app.date_string);
+ infostr = g_mime_gpgme_sigstat_to_gchar(mime_body->sig_info, FALSE, balsa_app.date_string);
if (infostr == NULL) {
return NULL;
}
@@ -118,13 +119,6 @@ balsa_mime_widget_signature_widget(LibBalsaMessageBody * mime_body,
gtk_label_set_selectable(GTK_LABEL(label), TRUE);
gtk_widget_set_halign(label, GTK_ALIGN_START);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
- if (mime_body->sig_info->key != NULL) {
- GtkWidget *key_widget;
-
- /* show only the subkey which has been used to sign the message */
- key_widget = libbalsa_gpgme_key(mime_body->sig_info->key, mime_body->sig_info->fingerprint, 0U,
FALSE);
- gtk_box_pack_start(GTK_BOX(vbox), key_widget, FALSE, FALSE, 0);
- }
if (mime_body->sig_info->protocol == GPGME_PROTOCOL_OpenPGP) {
GtkWidget *button;
@@ -139,19 +133,22 @@ balsa_mime_widget_signature_widget(LibBalsaMessageBody * mime_body,
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
}
- if (lines[1] != NULL) {
- /* Hack alert: if we omit the box below and use the expander as signature widget
- * directly, setting the container border width of the container = the expander
- * causes its sensitive area to shrink to an almost unusable narrow line above
- * the label... */
- GtkWidget *expander;
-
- signature_widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- expander = gtk_expander_new(lines[0]);
- gtk_container_add(GTK_CONTAINER(signature_widget), expander);
- gtk_container_add(GTK_CONTAINER(expander), vbox);
- } else {
- signature_widget = vbox;
+ /* Hack alert: if we omit the box below and use the expander as signature widget
+ * directly, setting the container border width of the container = the expander
+ * causes its sensitive area to shrink to an almost unusable narrow line above
+ * the label... */
+ signature_widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ expander = gtk_expander_new(lines[0]);
+ gtk_container_add(GTK_CONTAINER(signature_widget), expander);
+ gtk_container_add(GTK_CONTAINER(expander), vbox);
+
+ /* add a callback to load the key when the user wants to show the details
+ * Note: do *not* pass mime_body->sig_info to the callback, as it will be replaced when the user
re-checks the signature or
+ * opens the message again in a separate window */
+ if (((mime_body->sig_info->summary & GPGME_SIGSUM_KEY_MISSING) == 0) &&
+ (mime_body->sig_info->key == NULL)) {
+ g_signal_connect(expander, "activate", (GCallback) show_public_key_data, mime_body);
+ g_object_set_data(G_OBJECT(expander), "vbox", vbox);
}
gtk_container_set_border_width(GTK_CONTAINER(signature_widget), BMW_CONTAINER_BORDER);
@@ -339,4 +336,29 @@ create_import_keys_widget(GtkBox *box, const gchar *key_buf, GError **error)
return success;
}
+static void
+show_public_key_data(GtkExpander *expander,
+ gpointer user_data)
+{
+ LibBalsaMessageBody *body = (LibBalsaMessageBody *) user_data;
+
+ g_message("%s: %p %p %p", __func__, expander, body, body->sig_info);
+ if (body->sig_info != NULL) {
+ if (body->sig_info->key == NULL) {
+ g_mime_gpgme_sigstat_load_key(body->sig_info);
+ }
+
+ if ((g_object_get_data(G_OBJECT(expander), "vbox") != NULL) && (body->sig_info->key != NULL))
{
+ GtkWidget *key_widget;
+ GtkBox *vbox;
+
+ vbox = GTK_BOX(g_object_steal_data(G_OBJECT(expander), "vbox"));
+ key_widget = libbalsa_gpgme_key(body->sig_info->key, body->sig_info->fingerprint, 0U,
FALSE);
+ gtk_box_pack_start(vbox, key_widget, FALSE, FALSE, 0);
+ gtk_box_reorder_child(vbox, key_widget, 1U);
+ gtk_widget_show_all(key_widget);
+ }
+ }
+}
+
#endif /* HAVE_GPGME */
diff --git a/src/balsa-mime-widget-message.c b/src/balsa-mime-widget-message.c
index c0037a4..b2b37f2 100644
--- a/src/balsa-mime-widget-message.c
+++ b/src/balsa-mime-widget-message.c
@@ -850,7 +850,7 @@ add_header_sigstate(GtkGrid * grid, GMimeGpgmeSigstat * siginfo)
GPG_ERR_NO_ERROR ? "<i>%s%s</i>" : "<b><i>%s%s</i></b>";
msg = g_markup_printf_escaped
(format,
- libbalsa_gpgme_sig_protocol_name(siginfo->protocol),
+ g_mime_gpgme_sigstat_protocol_name(siginfo),
libbalsa_gpgme_sig_stat_to_gchar(siginfo->status));
label = gtk_label_new(NULL);
diff --git a/src/balsa-print-object-header.c b/src/balsa-print-object-header.c
index 352a461..cc7e3e4 100644
--- a/src/balsa-print-object-header.c
+++ b/src/balsa-print-object-header.c
@@ -1,7 +1,7 @@
/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
/* Balsa E-Mail Client
* Copyright (C) 1997-2016 Stuart Parmenter and others
- * Written by (C) Albrecht Dre� <albrecht dress arcor de> 2007
+ * Written by (C) Albrecht Dreß <albrecht dress arcor de> 2007
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -232,7 +232,7 @@ balsa_print_object_header_new_real(GList * list,
GMimeGpgmeSigstat *siginfo = sig_body->parts->next->sig_info;
g_string_append_printf(header_buf, "%s%s\n",
- libbalsa_gpgme_sig_protocol_name(siginfo->protocol),
+ g_mime_gpgme_sigstat_protocol_name(siginfo),
libbalsa_gpgme_sig_stat_to_gchar(siginfo->status));
}
}
@@ -387,10 +387,14 @@ balsa_print_object_header_crypto(GList *list, GtkPrintContext * context,
pango_layout_set_font_description(test_layout, header_font);
pango_font_description_free(header_font);
+ /* check if the key needs to be loaded */
+ if (((body->sig_info->summary & GPGME_SIGSUM_KEY_MISSING) == 0) &&
+ (body->sig_info->key == NULL)) {
+ g_mime_gpgme_sigstat_load_key(body->sig_info);
+ }
+
/* create a buffer with the signature info */
- textbuf =
- libbalsa_signature_info_to_gchar(body->sig_info,
- balsa_app.date_string);
+ textbuf = g_mime_gpgme_sigstat_to_gchar(body->sig_info, TRUE, balsa_app.date_string);
if (label) {
gchar *newbuf = g_strconcat(label, "\n", textbuf, NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]