]> git.cworth.org Git - notmuch/blob - test/T350-crypto.sh
tests: remove dead code from T055-path-config.sh
[notmuch] / test / T350-crypto.sh
1 #!/usr/bin/env bash
2
3 # TODO:
4 # - decryption/verification with signer key not available
5 # - verification of signatures from expired/revoked keys
6
7 test_description='PGP/MIME signature verification and decryption'
8 . $(dirname "$0")/test-lib.sh || exit 1
9 . $NOTMUCH_SRCDIR/test/test-lib-emacs.sh || exit 1
10
11 ##################################################
12
13 test_require_emacs
14 add_gnupg_home
15
16 test_begin_subtest "emacs delivery of signed message via fcc"
17 test_expect_success \
18 'emacs_fcc_message \
19     "test signed message 001" \
20     "This is a test signed message." \
21     "(mml-secure-message-sign)"'
22
23 test_begin_subtest "emacs delivery of signed message via fcc and smtp"
24 emacs_deliver_message \
25     'signed message sent via SMTP' \
26     'This is a test that messages are sent via SMTP' \
27     "(add-hook 'message-send-mail-hook (lambda () (sleep-for 1)))
28      (mml-secure-message-sign)"
29 msg_file=$(notmuch search --output=files subject:signed-message-sent-via-SMTP)
30 test_expect_equal_message_body sent_message "$msg_file"
31
32 test_begin_subtest "signed part content-type indexing"
33 notmuch search mimetype:multipart/signed and mimetype:application/pgp-signature | notmuch_search_sanitize > OUTPUT
34 cat <<EOF >EXPECTED
35 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; test signed message 001 (inbox signed)
36 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; signed message sent via SMTP (inbox signed)
37 EOF
38 test_expect_equal_file EXPECTED OUTPUT
39
40 test_begin_subtest "signature verification"
41 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
42     | notmuch_json_show_sanitize \
43     | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
44 expected='[[[{"id": "XXXXX",
45  "match": true,
46  "excluded": false,
47  "filename": ["YYYYY"],
48  "timestamp": 946728000,
49  "date_relative": "2000-01-01",
50  "tags": ["inbox","signed"],
51  "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "email": "'"$SELF_EMAIL"'", "fingerprint": "'$FINGERPRINT'", "userid": "'"$SELF_USERID"'"}]}},
52  "headers": {"Subject": "test signed message 001",
53  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
54  "To": "test_suite@notmuchmail.org",
55  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
56  "body": [{"id": 1,
57  "sigstatus": [{"status": "good",
58  "fingerprint": "'$FINGERPRINT'",
59  "created": 946728000,
60  "email": "'"$SELF_EMAIL"'",
61  "userid": "'"$SELF_USERID"'"}],
62  "content-type": "multipart/signed",
63  "content": [{"id": 2,
64  "content-type": "text/plain",
65  "content": "This is a test signed message.\n"},
66  {"id": 3,
67  "content-type": "application/pgp-signature",
68  "content-length": "NONZERO"}]}]},
69  []]]]'
70 test_expect_equal_json \
71     "$output" \
72     "$expected"
73
74 test_begin_subtest "detection of modified signed contents"
75 emacs_fcc_message \
76     "bad signed message 001" \
77     "Incriminating stuff. This is a test signed message." \
78     "(mml-secure-message-sign)"
79
80 file=$(notmuch search --output=files subject:"bad signed message 001")
81
82 sed -i 's/Incriminating stuff. //' ${file}
83
84 output=$(notmuch show --format=json --verify subject:"bad signed message 001" \
85     | notmuch_json_show_sanitize \
86     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
87 expected='[[[{"id": "XXXXX",
88  "match": true,
89  "excluded": false,
90  "filename": ["YYYYY"],
91  "timestamp": 946728000,
92  "date_relative": "2000-01-01",
93  "tags": ["inbox","signed"],
94  "crypto": {"signed": {"status": [{ "status": "bad", "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'"}]}},
95  "headers": {"Subject": "bad signed message 001",
96  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
97  "To": "test_suite@notmuchmail.org",
98  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
99  "body": [{"id": 1,
100  "sigstatus": [{"status": "bad",
101  "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'"}],
102  "content-type": "multipart/signed",
103  "content": [{"id": 2,
104  "content-type": "text/plain",
105  "content": "This is a test signed message.\n"},
106  {"id": 3,
107  "content-type": "application/pgp-signature",
108  "content-length": "NONZERO"}]}]},
109  []]]]'
110 test_expect_equal_json \
111     "$output" \
112     "$expected"
113
114 test_begin_subtest "corrupted pgp/mime signature"
115 emacs_fcc_message \
116     "bad signed message 002" \
117     "Incriminating stuff. This is a test signed message." \
118     "(mml-secure-message-sign)"
119
120 file=$(notmuch search --output=files subject:"bad signed message 002")
121
122 awk '/-----BEGIN PGP SIGNATURE-----/{flag=1;print;next} \
123      /-----END PGP SIGNATURE-----/{flag=0;print;next} \
124      flag{gsub(/[A-Za-z]/,"0");print}!flag{print}' $file > $file.new
125
126 rm $file
127 mv $file.new $file
128
129 output=$(notmuch show --format=json --verify subject:"bad signed message 002" \
130     | notmuch_json_show_sanitize \
131     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
132 expected='[[[{"id": "XXXXX",
133  "crypto": {},
134  "match": true,
135  "excluded": false,
136  "filename": ["YYYYY"],
137  "timestamp": 946728000,
138  "date_relative": "2000-01-01",
139  "tags": ["inbox","signed"],
140  "headers": {"Subject": "bad signed message 002",
141  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
142  "To": "test_suite@notmuchmail.org",
143  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
144  "body": [{"id": 1,
145  "sigstatus": [],
146  "content-type": "multipart/signed",
147  "content": [{"id": 2,
148  "content-type": "text/plain",
149  "content": "Incriminating stuff. This is a test signed message.\n"},
150  {"id": 3,
151  "content-type": "application/pgp-signature",
152  "content-length": "NONZERO"}]}]},
153  []]]]'
154 test_expect_equal_json \
155     "$output" \
156     "$expected"
157
158 test_begin_subtest "signature verification without full user ID validity"
159 # give the key no owner trust, removes validity on all user IDs of the
160 # certificate in the absence of other trusted certifiers:
161 gpg --quiet --batch --no-tty --export-ownertrust > "$GNUPGHOME/ownertrust.bak"
162 echo "${FINGERPRINT}:3:" | gpg --quiet --batch --no-tty --import-ownertrust
163 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
164     | notmuch_json_show_sanitize \
165     | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
166 expected='[[[{"id": "XXXXX",
167  "match": true,
168  "excluded": false,
169  "filename": ["YYYYY"],
170  "timestamp": 946728000,
171  "date_relative": "2000-01-01",
172  "tags": ["inbox","signed"],
173  "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "fingerprint": "'$FINGERPRINT'"}]}},
174  "headers": {"Subject": "test signed message 001",
175  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
176  "To": "test_suite@notmuchmail.org",
177  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
178  "body": [{"id": 1,
179  "sigstatus": [{"status": "good",
180  "fingerprint": "'$FINGERPRINT'",
181  "created": 946728000}],
182  "content-type": "multipart/signed",
183  "content": [{"id": 2,
184  "content-type": "text/plain",
185  "content": "This is a test signed message.\n"},
186  {"id": 3,
187  "content-type": "application/pgp-signature",
188  "content-length": "NONZERO"}]}]},
189  []]]]'
190 test_expect_equal_json \
191     "$output" \
192     "$expected"
193 gpg --quiet --batch --no-tty --import-ownertrust < "$GNUPGHOME/ownertrust.bak"
194
195 test_begin_subtest "signature verification with signer key unavailable"
196 # move the gnupghome temporarily out of the way
197 mv "${GNUPGHOME}"{,.bak}
198 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
199     | notmuch_json_show_sanitize \
200     | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
201 expected='[[[{"id": "XXXXX",
202  "match": true,
203  "excluded": false,
204  "filename": ["YYYYY"],
205  "timestamp": 946728000,
206  "date_relative": "2000-01-01",
207  "tags": ["inbox","signed"],
208  "crypto": {"signed": {"status": [{"errors": {"key-missing": true}, "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", "status": "error"}]}},
209  "headers": {"Subject": "test signed message 001",
210  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
211  "To": "test_suite@notmuchmail.org",
212  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
213  "body": [{"id": 1,
214  "sigstatus": [{"status": "error",
215  "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
216  "errors": {"key-missing": true}}],
217  "content-type": "multipart/signed",
218  "content": [{"id": 2,
219  "content-type": "text/plain",
220  "content": "This is a test signed message.\n"},
221  {"id": 3,
222  "content-type": "application/pgp-signature",
223  "content-length": "NONZERO"}]}]},
224  []]]]'
225 test_expect_equal_json \
226     "$output" \
227     "$expected"
228 mv "${GNUPGHOME}"{.bak,}
229
230 test_begin_subtest "emacs delivery of encrypted message with attachment"
231 # create a test encrypted message with attachment
232 cat <<EOF >TESTATTACHMENT
233 This is a test file.
234 EOF
235 test_expect_success \
236 'emacs_fcc_message \
237     "test encrypted message 001" \
238     "This is a test encrypted message.\n" \
239     "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'
240
241 test_begin_subtest "encrypted part content-type indexing"
242 output=$(notmuch search mimetype:multipart/encrypted and mimetype:application/pgp-encrypted and mimetype:application/octet-stream | notmuch_search_sanitize)
243 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; test encrypted message 001 (encrypted inbox)"
244
245 test_begin_subtest "decryption, --format=text"
246 output=$(notmuch show --format=text --decrypt=true subject:"test encrypted message 001" \
247     | notmuch_show_sanitize_all \
248     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
249 expected='\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
250 \fheader{
251 Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (encrypted inbox)
252 Subject: test encrypted message 001
253 From: Notmuch Test Suite <test_suite@notmuchmail.org>
254 To: test_suite@notmuchmail.org
255 Date: Sat, 01 Jan 2000 12:00:00 +0000
256 \fheader}
257 \fbody{
258 \fpart{ ID: 1, Content-type: multipart/encrypted
259 \fpart{ ID: 2, Content-type: application/pgp-encrypted
260 Non-text part: application/pgp-encrypted
261 \fpart}
262 \fpart{ ID: 3, Content-type: multipart/mixed
263 \fpart{ ID: 4, Content-type: text/plain
264 This is a test encrypted message.
265 \fpart}
266 \fattachment{ ID: 5, Filename: TESTATTACHMENT, Content-type: application/octet-stream
267 Non-text part: application/octet-stream
268 \fattachment}
269 \fpart}
270 \fpart}
271 \fbody}
272 \fmessage}'
273 test_expect_equal \
274     "$output" \
275     "$expected"
276
277 test_begin_subtest "decryption, --format=json"
278 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \
279     | notmuch_json_show_sanitize \
280     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
281 expected='[[[{"id": "XXXXX",
282  "match": true,
283  "excluded": false,
284  "filename": ["YYYYY"],
285  "timestamp": 946728000,
286  "date_relative": "2000-01-01",
287  "tags": ["encrypted","inbox"],
288  "crypto": {"decrypted": {"status": "full"}},
289  "headers": {"Subject": "test encrypted message 001",
290  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
291  "To": "test_suite@notmuchmail.org",
292  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
293  "body": [{"id": 1,
294  "encstatus": [{"status": "good"}],
295  "content-type": "multipart/encrypted",
296  "content": [{"id": 2,
297  "content-type": "application/pgp-encrypted",
298  "content-length": "NONZERO"},
299  {"id": 3,
300  "content-type": "multipart/mixed",
301  "content": [{"id": 4,
302  "content-type": "text/plain",
303  "content": "This is a test encrypted message.\n"},
304  {"id": 5,
305  "content-type": "application/octet-stream",
306  "content-disposition": "attachment",
307  "content-length": "NONZERO",
308  "content-transfer-encoding": "base64",
309  "filename": "TESTATTACHMENT"}]}]}]},
310  []]]]'
311 test_expect_equal_json \
312     "$output" \
313     "$expected"
314
315 test_begin_subtest "decryption, --format=json, --part=4"
316 output=$(notmuch show --format=json --part=4 --decrypt=true subject:"test encrypted message 001" \
317     | notmuch_json_show_sanitize \
318     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
319 expected='{"id": 4,
320  "content-type": "text/plain",
321  "content": "This is a test encrypted message.\n"}'
322 test_expect_equal_json \
323     "$output" \
324     "$expected"
325
326 test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
327 notmuch show \
328     --format=raw \
329     --part=5 \
330     --decrypt=true \
331     subject:"test encrypted message 001" >OUTPUT
332 test_expect_equal_file TESTATTACHMENT OUTPUT
333
334 test_begin_subtest "decryption failure with missing key"
335 mv "${GNUPGHOME}"{,.bak}
336 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \
337     | notmuch_json_show_sanitize \
338     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
339 expected='[[[{"id": "XXXXX",
340  "crypto": {},
341  "match": true,
342  "excluded": false,
343  "filename": ["YYYYY"],
344  "timestamp": 946728000,
345  "date_relative": "2000-01-01",
346  "tags": ["encrypted","inbox"],
347  "headers": {"Subject": "test encrypted message 001",
348  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
349  "To": "test_suite@notmuchmail.org",
350  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
351  "body": [{"id": 1,
352  "encstatus": [{"status": "bad"}],
353  "content-type": "multipart/encrypted",
354  "content": [{"id": 2,
355  "content-type": "application/pgp-encrypted",
356  "content-length": "NONZERO"},
357  {"id": 3,
358  "content-type": "application/octet-stream",
359  "content-length": "NONZERO"}]}]},
360  []]]]'
361 test_expect_equal_json \
362     "$output" \
363     "$expected"
364 mv "${GNUPGHOME}"{.bak,}
365
366 test_begin_subtest "emacs delivery of encrypted + signed message"
367 test_expect_success \
368 'emacs_fcc_message \
369     "test encrypted message 002" \
370     "This is another test encrypted message.\n" \
371     "(mml-secure-message-sign-encrypt)"'
372
373 test_begin_subtest "decryption + signature verification"
374 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 002" \
375     | notmuch_json_show_sanitize \
376     | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
377 expected='[[[{"id": "XXXXX",
378  "match": true,
379  "excluded": false,
380  "filename": ["YYYYY"],
381  "timestamp": 946728000,
382  "date_relative": "2000-01-01",
383  "tags": ["encrypted","inbox"],
384  "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "fingerprint": "'$FINGERPRINT'", "email": "'"$SELF_EMAIL"'", "userid": "'"$SELF_USERID"'"}],
385                        "encrypted": true },
386             "decrypted": {"status": "full"}},
387  "headers": {"Subject": "test encrypted message 002",
388  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
389  "To": "test_suite@notmuchmail.org",
390  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
391  "body": [{"id": 1,
392  "encstatus": [{"status": "good"}],
393  "sigstatus": [{"status": "good",
394  "fingerprint": "'$FINGERPRINT'",
395  "created": 946728000,
396  "email": "'"$SELF_EMAIL"'",
397  "userid": "'"$SELF_USERID"'"}],
398  "content-type": "multipart/encrypted",
399  "content": [{"id": 2,
400  "content-type": "application/pgp-encrypted",
401  "content-length": "NONZERO"},
402  {"id": 3,
403  "content-type": "text/plain",
404  "content": "This is another test encrypted message.\n"}]}]},
405  []]]]'
406 test_expect_equal_json \
407     "$output" \
408     "$expected"
409
410 test_begin_subtest "reply to encrypted message"
411 output=$(notmuch reply --decrypt=true subject:"test encrypted message 002" \
412     | notmuch_drop_mail_headers In-Reply-To References)
413 expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
414 Subject: Re: test encrypted message 002
415 To: test_suite@notmuchmail.org
416
417 On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
418 > This is another test encrypted message.'
419 test_expect_equal \
420     "$output" \
421     "$expected"
422
423 test_begin_subtest "Reply within emacs to an encrypted message"
424 test_emacs "(let ((message-hidden-headers '())
425       (notmuch-crypto-process-mime 't))
426   (notmuch-show \"subject:test.encrypted.message.002\")
427   (notmuch-show-reply)
428   (test-output))"
429 grep -v -e '^In-Reply-To:' -e '^References:' -e '^Fcc:' < OUTPUT > OUTPUT.clean
430 cat <<EOF >EXPECTED
431 From: Notmuch Test Suite <test_suite@notmuchmail.org>
432 To: test_suite@notmuchmail.org
433 Subject: Re: test encrypted message 002
434 --text follows this line--
435 <#secure method=pgpmime mode=signencrypt>
436 Notmuch Test Suite <test_suite@notmuchmail.org> writes:
437
438 > This is another test encrypted message.
439 EOF
440 test_expect_equal_file EXPECTED OUTPUT.clean
441
442 test_begin_subtest "signature verification with revoked key"
443 # generate revocation certificate and load it to revoke key
444 echo "y
445 1
446 Notmuch Test Suite key revocation (automated) $(date '+%F_%T%z')
447
448 y
449
450 " \
451     | gpg --no-tty --quiet --command-fd 0 --armor --gen-revoke "0x${FINGERPRINT}!" 2>/dev/null \
452     | gpg --no-tty --quiet --import
453 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
454     | notmuch_json_show_sanitize \
455     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
456 expected='[[[{"id": "XXXXX",
457  "match": true,
458  "excluded": false,
459  "filename": ["YYYYY"],
460  "timestamp": 946728000,
461  "date_relative": "2000-01-01",
462  "tags": ["inbox","signed"],
463  "crypto": {"signed": {"status": [{"errors": {"key-revoked": true}, "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", "status": "error"}]}},
464  "headers": {"Subject": "test signed message 001",
465  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
466  "To": "test_suite@notmuchmail.org",
467  "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
468  "body": [{"id": 1,
469  "sigstatus": [{"status": "error",
470  "keyid": "6D92612D94E46381",
471  "errors": {"key-revoked": true}}],
472  "content-type": "multipart/signed",
473  "content": [{"id": 2,
474  "content-type": "text/plain",
475  "content": "This is a test signed message.\n"},
476  {"id": 3,
477  "content-type": "application/pgp-signature",
478  "content-length": "NONZERO"}]}]},
479  []]]]'
480 test_expect_equal_json \
481     "$output" \
482     "$expected"
483
484 test_done