mirror of
https://git.notmuchmail.org/git/notmuch
synced 2025-01-03 15:21:41 +01:00
lib: index PKCS7 SignedData parts
When we are indexing, we should treat SignedData parts the same way that we treat a multipart object, indexing the wrapped part as a distinct MIME object. Unfortunately, this means doing some sort of cryptographic verification whose results we throw away, because GMime doesn't offer us any way to unwrap without doing signature verification. I've opened https://github.com/jstedfast/gmime/issues/67 to request the capability from GMime but for now, we'll just accept the additional performance hit. As we do this indexing, we also apply the "signed" tag, by analogy with how we handle multipart/signed messages. These days, that kind of change should probably be done with a property instead, but that's a different set of changes. This one is just for consistency. Note that we are currently *only* handling signedData parts, which are basically clearsigned messages. PKCS#7 parts can also be envelopedData and authEnvelopedData (which are effectively encryption layers), and compressedData (which afaict isn't implemented anywhere, i've never encountered it). We're laying the groundwork for indexing these other S/MIME types here, but we're only dealing with signedData for now. Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
This commit is contained in:
parent
7880092964
commit
38bd0df922
2 changed files with 57 additions and 2 deletions
57
lib/index.cc
57
lib/index.cc
|
@ -372,6 +372,12 @@ _index_encrypted_mime_part (notmuch_message_t *message, notmuch_indexopts_t *ind
|
||||||
GMimeMultipartEncrypted *part,
|
GMimeMultipartEncrypted *part,
|
||||||
_notmuch_message_crypto_t *msg_crypto);
|
_notmuch_message_crypto_t *msg_crypto);
|
||||||
|
|
||||||
|
static void
|
||||||
|
_index_pkcs7_part (notmuch_message_t *message,
|
||||||
|
notmuch_indexopts_t *indexopts,
|
||||||
|
GMimeObject *part,
|
||||||
|
_notmuch_message_crypto_t *msg_crypto);
|
||||||
|
|
||||||
/* Callback to generate terms for each mime part of a message. */
|
/* Callback to generate terms for each mime part of a message. */
|
||||||
static void
|
static void
|
||||||
_index_mime_part (notmuch_message_t *message,
|
_index_mime_part (notmuch_message_t *message,
|
||||||
|
@ -466,6 +472,11 @@ _index_mime_part (notmuch_message_t *message,
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GMIME_IS_APPLICATION_PKCS7_MIME (part)) {
|
||||||
|
_index_pkcs7_part (message, indexopts, part, msg_crypto);
|
||||||
|
goto DONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (! (GMIME_IS_PART (part))) {
|
if (! (GMIME_IS_PART (part))) {
|
||||||
_notmuch_database_log (notmuch_message_get_database (message),
|
_notmuch_database_log (notmuch_message_get_database (message),
|
||||||
"Warning: Not indexing unknown mime part: %s.\n",
|
"Warning: Not indexing unknown mime part: %s.\n",
|
||||||
|
@ -608,6 +619,52 @@ _index_encrypted_mime_part (notmuch_message_t *message,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_index_pkcs7_part (notmuch_message_t *message,
|
||||||
|
notmuch_indexopts_t *indexopts,
|
||||||
|
GMimeObject *part,
|
||||||
|
_notmuch_message_crypto_t *msg_crypto)
|
||||||
|
{
|
||||||
|
GMimeApplicationPkcs7Mime *pkcs7;
|
||||||
|
GMimeSecureMimeType p7type;
|
||||||
|
GMimeObject *mimeobj = NULL;
|
||||||
|
GMimeSignatureList *sigs = NULL;
|
||||||
|
GError *err = NULL;
|
||||||
|
notmuch_database_t *notmuch = NULL;
|
||||||
|
|
||||||
|
pkcs7 = GMIME_APPLICATION_PKCS7_MIME (part);
|
||||||
|
p7type = g_mime_application_pkcs7_mime_get_smime_type (pkcs7);
|
||||||
|
notmuch = notmuch_message_get_database (message);
|
||||||
|
_index_content_type (message, part);
|
||||||
|
|
||||||
|
if (p7type == GMIME_SECURE_MIME_TYPE_SIGNED_DATA) {
|
||||||
|
sigs = g_mime_application_pkcs7_mime_verify (pkcs7, GMIME_VERIFY_NONE, &mimeobj, &err);
|
||||||
|
if (sigs == NULL) {
|
||||||
|
_notmuch_database_log (notmuch, "Failed to verify PKCS#7 SignedData during indexing. (%d:%d) [%s]\n",
|
||||||
|
err->domain, err->code, err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
goto DONE;
|
||||||
|
}
|
||||||
|
_notmuch_message_add_term (message, "tag", "signed");
|
||||||
|
GMimeObject *toindex = mimeobj;
|
||||||
|
if (_notmuch_message_crypto_potential_payload (msg_crypto, mimeobj, part, 0) &&
|
||||||
|
msg_crypto->decryption_status == NOTMUCH_MESSAGE_DECRYPTED_FULL) {
|
||||||
|
toindex = _notmuch_repair_crypto_payload_skip_legacy_display (mimeobj);
|
||||||
|
if (toindex != mimeobj)
|
||||||
|
notmuch_message_add_property (message, "index.repaired", "skip-protected-headers-legacy-display");
|
||||||
|
}
|
||||||
|
_index_mime_part (message, indexopts, toindex, msg_crypto);
|
||||||
|
} else {
|
||||||
|
_notmuch_database_log (notmuch, "Cannot currently handle PKCS#7 smime-type '%s'\n",
|
||||||
|
g_mime_object_get_content_type_parameter (part, "smime-type"));
|
||||||
|
}
|
||||||
|
DONE:
|
||||||
|
if (mimeobj)
|
||||||
|
g_object_unref (mimeobj);
|
||||||
|
if (sigs)
|
||||||
|
g_object_unref (sigs);
|
||||||
|
}
|
||||||
|
|
||||||
static notmuch_status_t
|
static notmuch_status_t
|
||||||
_notmuch_message_index_user_headers (notmuch_message_t *message, GMimeMessage *mime_message)
|
_notmuch_message_index_user_headers (notmuch_message_t *message, GMimeMessage *mime_message)
|
||||||
{
|
{
|
||||||
|
|
|
@ -132,13 +132,11 @@ expected=''
|
||||||
test_expect_equal "$expected" "$output"
|
test_expect_equal "$expected" "$output"
|
||||||
|
|
||||||
test_begin_subtest "know the MIME type of the embedded part in PKCS#7 SignedData"
|
test_begin_subtest "know the MIME type of the embedded part in PKCS#7 SignedData"
|
||||||
test_subtest_known_broken
|
|
||||||
output=$(notmuch search --output=messages 'mimetype:text/plain')
|
output=$(notmuch search --output=messages 'mimetype:text/plain')
|
||||||
expected=id:smime-onepart-signed@protected-headers.example
|
expected=id:smime-onepart-signed@protected-headers.example
|
||||||
test_expect_equal "$expected" "$output"
|
test_expect_equal "$expected" "$output"
|
||||||
|
|
||||||
test_begin_subtest "PKCS#7 SignedData message is tagged 'signed'"
|
test_begin_subtest "PKCS#7 SignedData message is tagged 'signed'"
|
||||||
test_subtest_known_broken
|
|
||||||
output=$(notmuch dump id:smime-onepart-signed@protected-headers.example)
|
output=$(notmuch dump id:smime-onepart-signed@protected-headers.example)
|
||||||
expected='#notmuch-dump batch-tag:3 config,properties,tags
|
expected='#notmuch-dump batch-tag:3 config,properties,tags
|
||||||
+inbox +signed +unread -- id:smime-onepart-signed@protected-headers.example'
|
+inbox +signed +unread -- id:smime-onepart-signed@protected-headers.example'
|
||||||
|
|
Loading…
Reference in a new issue