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