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