crypto: actually stash session keys when decrypt=true
[notmuch] / test / T357-index-decryption.sh
1 #!/usr/bin/env bash
2
3 # TODO: test index.decryption=failed
4
5 test_description='indexing decrypted mail'
6 . $(dirname "$0")/test-lib.sh || exit 1
7
8 ##################################################
9
10 add_gnupg_home
11 # get key fingerprint
12 FINGERPRINT=$(gpg --no-tty --list-secret-keys --with-colons --fingerprint | grep '^fpr:' | cut -d: -f10)
13
14 # create a test encrypted message
15 test_begin_subtest 'emacs delivery of encrypted message'
16 test_expect_success \
17 'emacs_fcc_message \
18     "test encrypted message for cleartext index 001" \
19     "This is a test encrypted message with a wumpus.\n" \
20     "(mml-secure-message-encrypt)"'
21
22 test_begin_subtest "search for unindexed cleartext"
23 output=$(notmuch search wumpus)
24 expected=''
25 test_expect_equal \
26     "$output" \
27     "$expected"
28
29 # create a test encrypted message that is indexed in the clear
30 test_begin_subtest 'emacs delivery of encrypted message'
31 test_expect_success \
32 'emacs_fcc_message --decrypt=true \
33     "test encrypted message for cleartext index 002" \
34     "This is a test encrypted message with a wumpus.\n" \
35     "(mml-secure-message-encrypt)"'
36
37 test_begin_subtest "emacs delivery of encrypted message, indexed cleartext"
38 output=$(notmuch search wumpus)
39 expected='thread:0000000000000002   2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (encrypted inbox)'
40 test_expect_equal \
41     "$output" \
42     "$expected"
43
44 # and the same search, but by property ($expected is untouched):
45 test_begin_subtest "emacs search by property for one message"
46 output=$(notmuch search property:index.decryption=success)
47 test_expect_equal \
48     "$output" \
49     "$expected"
50
51 test_begin_subtest "show the message body of the encrypted message"
52 notmuch dump wumpus
53 output=$(notmuch show wumpus | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }')
54 expected='This is a test encrypted message with a wumpus.'
55 if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then
56     test_subtest_known_broken
57 fi
58 test_expect_equal \
59     "$output" \
60     "$expected"
61
62
63 test_begin_subtest "message should go away after deletion"
64 # cache the message in an env var and remove it:
65 fname=$(notmuch search --output=files wumpus)
66 contents="$(notmuch show --format=raw wumpus)"
67 rm -f "$fname"
68 notmuch new
69 output=$(notmuch search wumpus)
70 expected=''
71 test_expect_equal \
72     "$output" \
73     "$expected"
74
75 # try reinserting it without decryption, should stay the same:
76 test_begin_subtest "message cleartext not present after insert"
77 notmuch insert --folder=sent <<<"$contents"
78 output=$(notmuch search wumpus)
79 test_expect_equal \
80     "$output" \
81     "$expected"
82
83 # try reinserting it with decryption, should appear again, but now we
84 # have two copies of the message:
85 test_begin_subtest "message cleartext is present after reinserting with --decrypt=true"
86 notmuch insert --folder=sent --decrypt=true <<<"$contents"
87 output=$(notmuch search wumpus)
88 expected='thread:0000000000000003   2000-01-01 [1/1(2)] Notmuch Test Suite; test encrypted message for cleartext index 002 (encrypted inbox unread)'
89 test_expect_equal \
90     "$output" \
91     "$expected"
92
93 # remove all copies
94 test_begin_subtest "delete all copies of the message"
95 mid="$(notmuch search --output=messages wumpus)"
96 rm -f $(notmuch search --output=files wumpus)
97 notmuch new
98 output=$(notmuch search "id:$mid")
99 expected=''
100 test_expect_equal \
101     "$output" \
102     "$expected"
103
104 # try inserting it with decryption, should appear as a single copy
105 # (note: i think thread id skips 4 because of duplicate message-id
106 # insertion, above)
107 test_begin_subtest "message cleartext is present with insert --decrypt=true"
108 notmuch insert --folder=sent --decrypt=true <<<"$contents"
109 output=$(notmuch search wumpus)
110 expected='thread:0000000000000005   2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (encrypted inbox unread)'
111 test_expect_equal \
112     "$output" \
113     "$expected"
114
115
116 # add a tag to all messages to ensure that it stays after reindexing
117 test_begin_subtest 'tagging all messages'
118 test_expect_success 'notmuch tag +blarney "encrypted message"'
119 test_begin_subtest "verify that tags have not changed"
120 output=$(notmuch search tag:blarney)
121 expected='thread:0000000000000001   2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 001 (blarney encrypted inbox)
122 thread:0000000000000005   2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (blarney encrypted inbox unread)'
123 test_expect_equal \
124     "$output" \
125     "$expected"
126
127 # see if first message shows up after reindexing with --decrypt=true (same $expected, untouched):
128 test_begin_subtest 'reindex old messages'
129 test_expect_success 'notmuch reindex --decrypt=true tag:encrypted and not property:index.decryption=success'
130 test_begin_subtest "reindexed encrypted message, including cleartext"
131 output=$(notmuch search wumpus)
132 test_expect_equal \
133     "$output" \
134     "$expected"
135
136 # and the same search, but by property ($expected is untouched):
137 test_begin_subtest "emacs search by property for both messages"
138 output=$(notmuch search property:index.decryption=success)
139 test_expect_equal \
140     "$output" \
141     "$expected"
142
143 # try a simple reindex
144 test_begin_subtest 'reindex in auto mode'
145 test_expect_success 'notmuch reindex tag:encrypted and property:index.decryption=success'
146 test_begin_subtest "reindexed encrypted messages, should not have changed"
147 output=$(notmuch search wumpus)
148 if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then
149     test_subtest_known_broken
150 fi
151 test_expect_equal \
152     "$output" \
153     "$expected"
154
155 # try to remove cleartext indexing
156 test_begin_subtest 'reindex without cleartext'
157 test_expect_success 'notmuch reindex --decrypt=false tag:encrypted and property:index.decryption=success'
158 test_begin_subtest "reindexed encrypted messages, without cleartext"
159 output=$(notmuch search wumpus)
160 expected=''
161 test_expect_equal \
162     "$output" \
163     "$expected"
164
165 # ensure no session keys are present:
166 test_begin_subtest 'reindex using only session keys'
167 test_expect_success 'notmuch reindex tag:encrypted and property:index.decryption=success'
168 test_begin_subtest "reindexed encrypted messages, decrypting only with session keys"
169 output=$(notmuch search wumpus)
170 expected=''
171 test_expect_equal \
172     "$output" \
173     "$expected"
174
175 # and the same search, but by property ($expected is untouched):
176 test_begin_subtest "emacs search by property with both messages unindexed"
177 output=$(notmuch search property:index.decryption=success)
178 test_expect_equal \
179     "$output" \
180     "$expected"
181
182 # ensure that the tags remain even when we are dropping the cleartext.
183 test_begin_subtest "verify that tags remain without cleartext"
184 output=$(notmuch search tag:blarney)
185 expected='thread:0000000000000001   2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 001 (blarney encrypted inbox)
186 thread:0000000000000005   2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (blarney encrypted inbox unread)'
187 test_expect_equal \
188     "$output" \
189     "$expected"
190
191 add_email_corpus crypto
192
193 test_begin_subtest "indexing message fails when secret key not available"
194 notmuch reindex --decrypt=true id:simple-encrypted@crypto.notmuchmail.org
195 output=$(notmuch dump )
196 expected='#notmuch-dump batch-tag:3 config,properties,tags
197 +encrypted +inbox +unread -- id:simple-encrypted@crypto.notmuchmail.org
198 #= simple-encrypted@crypto.notmuchmail.org index.decryption=failure'
199 test_expect_equal \
200     "$output" \
201     "$expected"
202
203 test_begin_subtest "cannot find cleartext index"
204 output=$(notmuch search sekrit)
205 expected=''
206 test_expect_equal \
207     "$output" \
208     "$expected"
209
210 test_begin_subtest "cleartext index recovery on reindexing with stashed session keys"
211 notmuch restore <<EOF
212 #notmuch-dump batch-tag:3 config,properties,tags
213 #= simple-encrypted@crypto.notmuchmail.org session-key=9%3AFC09987F5F927CC0CC0EE80A96E4C5BBF4A499818FB591207705DFDDD6112CF9
214 EOF
215 notmuch reindex id:simple-encrypted@crypto.notmuchmail.org
216 output=$(notmuch search sekrit)
217 expected='thread:0000000000000001   2016-12-22 [1/1] Daniel Kahn Gillmor; encrypted message (encrypted inbox unread)'
218 if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then
219     test_subtest_known_broken
220 fi
221 test_expect_equal \
222     "$output" \
223     "$expected"
224
225 test_begin_subtest "notmuch reply should show cleartext if session key is present"
226 output=$(notmuch reply id:simple-encrypted@crypto.notmuchmail.org | grep '^>')
227 expected='> This is a top sekrit message.'
228 if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then
229     test_subtest_known_broken
230 fi
231 test_expect_equal \
232     "$output" \
233     "$expected"
234
235 test_begin_subtest "notmuch show should show cleartext if session key is present"
236 output=$(notmuch show id:simple-encrypted@crypto.notmuchmail.org | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }')
237 expected='This is a top sekrit message.'
238 if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then
239     test_subtest_known_broken
240 fi
241 test_expect_equal \
242     "$output" \
243     "$expected"
244
245 test_begin_subtest "notmuch show should show nothing if decryption is explicitly disallowed"
246 output=$(notmuch show --decrypt=false id:simple-encrypted@crypto.notmuchmail.org | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }')
247 expected='Non-text part: application/octet-stream'
248 test_expect_equal \
249     "$output" \
250     "$expected"
251
252 test_begin_subtest "purging stashed session keys should lose access to the cleartext"
253 notmuch reindex --decrypt=false id:simple-encrypted@crypto.notmuchmail.org
254 output=$(notmuch search sekrit)
255 expected=''
256 test_expect_equal \
257     "$output" \
258     "$expected"
259
260 test_begin_subtest "and cleartext should be unrecoverable now that there are no stashed session keys"
261 notmuch dump
262 notmuch reindex --decrypt=true id:simple-encrypted@crypto.notmuchmail.org
263 output=$(notmuch search sekrit)
264 expected=''
265 test_expect_equal \
266     "$output" \
267     "$expected"
268
269
270 # TODO: test removal of a message from the message store between
271 # indexing and reindexing.
272
273 # TODO: insert the same message into the message store twice, index,
274 # remove one of them from the message store, and then reindex.
275 # reindexing should return a failure but the message should still be
276 # present? -- or what should the semantics be if you ask to reindex a
277 # message whose underlying files have been renamed or moved or
278 # removed?
279
280 test_done