mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-24 20:08:10 +01:00
crypto: signature verification reports valid User IDs
When i'm trying to understand a message signature, i care that i know who it came from (the "validity" of the identity associated with the key), *not* whether i'm willing to accept the keyholder's other identity assertions (the "trust" associated with the certificate). We've been reporting User ID information based on the "trust" associated with the certificate, because GMime didn't clearly expose the validity of the User IDs. This change relies on fixes made in GMime 3.0.3 and later which include https://github.com/jstedfast/gmime/pull/18.
This commit is contained in:
parent
83f2661363
commit
cb855d8a9d
5 changed files with 46 additions and 20 deletions
3
configure
vendored
3
configure
vendored
|
@ -482,9 +482,10 @@ fi
|
||||||
# we need to have a version >= 2.6.5 to avoid a crypto bug. We need
|
# we need to have a version >= 2.6.5 to avoid a crypto bug. We need
|
||||||
# 2.6.7 for permissive "From " header handling.
|
# 2.6.7 for permissive "From " header handling.
|
||||||
GMIME_MINVER=2.6.7
|
GMIME_MINVER=2.6.7
|
||||||
|
GMIME3_MINVER=3.0.3
|
||||||
|
|
||||||
printf "Checking for GMime development files... "
|
printf "Checking for GMime development files... "
|
||||||
if pkg-config --exists "gmime-3.0"; then
|
if pkg-config --exists "gmime-3.0 > $GMIME3_MINVER"; then
|
||||||
printf "Yes (3.0).\n"
|
printf "Yes (3.0).\n"
|
||||||
have_gmime=1
|
have_gmime=1
|
||||||
gmime_cflags=$(pkg-config --cflags gmime-3.0)
|
gmime_cflags=$(pkg-config --cflags gmime-3.0)
|
||||||
|
|
|
@ -446,15 +446,11 @@ format_part_sigstatus_sprinter (sprinter_t *sp, mime_node_t *node)
|
||||||
sp->map_key (sp, "expires");
|
sp->map_key (sp, "expires");
|
||||||
sp->integer (sp, expires);
|
sp->integer (sp, expires);
|
||||||
}
|
}
|
||||||
/* output user id only if validity is FULL or ULTIMATE. */
|
|
||||||
/* note that gmime is using the term "trust" here, which
|
|
||||||
* is WRONG. It's actually user id "validity". */
|
|
||||||
if (certificate) {
|
if (certificate) {
|
||||||
const char *name = g_mime_certificate_get_uid (certificate);
|
const char *uid = g_mime_certificate_get_valid_userid (certificate);
|
||||||
GMimeCertificateTrust trust = g_mime_certificate_get_trust (certificate);
|
if (uid) {
|
||||||
if (name && (trust == GMIME_CERTIFICATE_TRUST_FULLY || trust == GMIME_CERTIFICATE_TRUST_ULTIMATE)) {
|
|
||||||
sp->map_key (sp, "userid");
|
sp->map_key (sp, "userid");
|
||||||
sp->string (sp, name);
|
sp->string (sp, uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (certificate) {
|
} else if (certificate) {
|
||||||
|
|
|
@ -48,6 +48,12 @@ EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "signature verification (notmuch CLI)"
|
test_begin_subtest "signature verification (notmuch CLI)"
|
||||||
|
if [ "${NOTMUCH_GMIME_MAJOR}" -lt 3 ]; then
|
||||||
|
# gmime 2 can't report User IDs properly for S/MIME
|
||||||
|
USERID=''
|
||||||
|
else
|
||||||
|
USERID='"userid": "CN=Notmuch Test Suite",'
|
||||||
|
fi
|
||||||
output=$(notmuch show --format=json --verify subject:"test signed message 001" \
|
output=$(notmuch show --format=json --verify subject:"test signed message 001" \
|
||||||
| notmuch_json_show_sanitize \
|
| notmuch_json_show_sanitize \
|
||||||
| sed -e 's|"created": [-1234567890]*|"created": 946728000|' \
|
| sed -e 's|"created": [-1234567890]*|"created": 946728000|' \
|
||||||
|
@ -65,7 +71,7 @@ expected='[[[{"id": "XXXXX",
|
||||||
"Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
|
"Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
|
||||||
"body": [{"id": 1,
|
"body": [{"id": 1,
|
||||||
"sigstatus": [{"fingerprint": "'$FINGERPRINT'",
|
"sigstatus": [{"fingerprint": "'$FINGERPRINT'",
|
||||||
"status": "good",
|
"status": "good",'$USERID'
|
||||||
"expires": 424242424,
|
"expires": 424242424,
|
||||||
"created": 946728000}],
|
"created": 946728000}],
|
||||||
"content-type": "multipart/signed",
|
"content-type": "multipart/signed",
|
||||||
|
|
|
@ -33,6 +33,21 @@ g_string_talloc_strdup (void *ctx, char *g_string)
|
||||||
|
|
||||||
#if (GMIME_MAJOR_VERSION < 3)
|
#if (GMIME_MAJOR_VERSION < 3)
|
||||||
|
|
||||||
|
const char *
|
||||||
|
g_mime_certificate_get_valid_userid (GMimeCertificate *cert)
|
||||||
|
{
|
||||||
|
/* output user id only if validity is FULL or ULTIMATE. */
|
||||||
|
/* note that gmime 2.6 is using the term "trust" here, which
|
||||||
|
* is WRONG. It's actually user id "validity". */
|
||||||
|
const char *name = g_mime_certificate_get_name (cert);
|
||||||
|
if (name == NULL)
|
||||||
|
return name;
|
||||||
|
GMimeCertificateTrust trust = g_mime_certificate_get_trust (cert);
|
||||||
|
if (trust == GMIME_CERTIFICATE_TRUST_FULLY || trust == GMIME_CERTIFICATE_TRUST_ULTIMATE)
|
||||||
|
return name;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
g_mime_message_get_address_string (GMimeMessage *message, GMimeRecipientType type)
|
g_mime_message_get_address_string (GMimeMessage *message, GMimeRecipientType type)
|
||||||
{
|
{
|
||||||
|
@ -107,6 +122,19 @@ g_mime_utils_header_decode_date_unix (const char *date) {
|
||||||
|
|
||||||
#else /* GMime >= 3.0 */
|
#else /* GMime >= 3.0 */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
g_mime_certificate_get_valid_userid (GMimeCertificate *cert)
|
||||||
|
{
|
||||||
|
/* output user id only if validity is FULL or ULTIMATE. */
|
||||||
|
const char *uid = g_mime_certificate_get_user_id (cert);
|
||||||
|
if (uid == NULL)
|
||||||
|
return uid;
|
||||||
|
GMimeValidity validity = g_mime_certificate_get_id_validity (cert);
|
||||||
|
if (validity == GMIME_VALIDITY_FULL || validity == GMIME_VALIDITY_ULTIMATE)
|
||||||
|
return uid;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
g_mime_certificate_get_fpr16 (GMimeCertificate *cert) {
|
g_mime_certificate_get_fpr16 (GMimeCertificate *cert) {
|
||||||
const char *fpr = g_mime_certificate_get_fingerprint (cert);
|
const char *fpr = g_mime_certificate_get_fingerprint (cert);
|
||||||
|
|
|
@ -16,12 +16,10 @@ GMimeStream *g_mime_stream_stdout_new(void);
|
||||||
#define g_mime_2_6_unref(obj) g_object_unref (obj)
|
#define g_mime_2_6_unref(obj) g_object_unref (obj)
|
||||||
#define g_mime_3_unused(arg) arg
|
#define g_mime_3_unused(arg) arg
|
||||||
#define g_mime_certificate_get_fpr16(cert) g_mime_certificate_get_key_id (cert)
|
#define g_mime_certificate_get_fpr16(cert) g_mime_certificate_get_key_id (cert)
|
||||||
#define g_mime_certificate_get_uid(cert) g_mime_certificate_get_name (cert);
|
|
||||||
#else /* GMime >= 3.0 */
|
#else /* GMime >= 3.0 */
|
||||||
typedef GMimeAddressType GMimeRecipientType;
|
typedef GMimeAddressType GMimeRecipientType;
|
||||||
|
|
||||||
#define GMIME_ENABLE_RFC_2047_WORKAROUNDS 0xdeadbeef
|
#define GMIME_ENABLE_RFC_2047_WORKAROUNDS 0xdeadbeef
|
||||||
#define g_mime_certificate_get_uid(cert) g_mime_certificate_get_key_id (cert);
|
|
||||||
#define g_mime_content_type_to_string(c) g_mime_content_type_get_mime_type (c)
|
#define g_mime_content_type_to_string(c) g_mime_content_type_get_mime_type (c)
|
||||||
#define g_mime_filter_crlf_new(encode,dots) g_mime_filter_dos2unix_new (FALSE)
|
#define g_mime_filter_crlf_new(encode,dots) g_mime_filter_dos2unix_new (FALSE)
|
||||||
#define g_mime_gpg_context_new(func,path) g_mime_gpg_context_new ()
|
#define g_mime_gpg_context_new(func,path) g_mime_gpg_context_new ()
|
||||||
|
@ -47,15 +45,6 @@ typedef GMimeAddressType GMimeRecipientType;
|
||||||
|
|
||||||
typedef GMimeSignatureStatus GMimeSignatureError;
|
typedef GMimeSignatureStatus GMimeSignatureError;
|
||||||
|
|
||||||
typedef GMimeTrust GMimeCertificateTrust;
|
|
||||||
|
|
||||||
#define GMIME_CERTIFICATE_TRUST_UNKNOWN GMIME_TRUST_UNKNOWN
|
|
||||||
#define GMIME_CERTIFICATE_TRUST_UNDEFINED GMIME_TRUST_UNDEFINED
|
|
||||||
#define GMIME_CERTIFICATE_TRUST_NEVER GMIME_TRUST_NEVER
|
|
||||||
#define GMIME_CERTIFICATE_TRUST_MARGINAL GMIME_TRUST_MARGINAL
|
|
||||||
#define GMIME_CERTIFICATE_TRUST_FULLY GMIME_TRUST_FULL
|
|
||||||
#define GMIME_CERTIFICATE_TRUST_ULTIMATE GMIME_TRUST_ULTIMATE
|
|
||||||
|
|
||||||
#define g_mime_2_6_unref(obj) /*ignore*/
|
#define g_mime_2_6_unref(obj) /*ignore*/
|
||||||
#define g_mime_3_unused(arg) unused(arg)
|
#define g_mime_3_unused(arg) unused(arg)
|
||||||
#endif
|
#endif
|
||||||
|
@ -107,4 +96,10 @@ gboolean g_mime_signature_status_bad (GMimeSignatureStatus status);
|
||||||
gboolean g_mime_signature_status_error (GMimeSignatureError status);
|
gboolean g_mime_signature_status_error (GMimeSignatureError status);
|
||||||
|
|
||||||
gint64 g_mime_utils_header_decode_date_unix (const char *date);
|
gint64 g_mime_utils_header_decode_date_unix (const char *date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return string for valid User ID (or NULL if no valid User ID exists)
|
||||||
|
*/
|
||||||
|
const char * g_mime_certificate_get_valid_userid (GMimeCertificate *cert);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue