Commit Graph

96 Commits

Author SHA1 Message Date
link2xt
296ed6d74a api!: remove functions for sending and receiving Autocrypt Setup Message 2026-03-17 20:10:59 +00:00
link2xt
5fb118e5a3 refactor: make signing key non-optional for pk_encrypt 2025-12-01 01:16:01 +00:00
Hocuri
5034449009 feat!: QR codes and symmetric encryption for broadcast channels (#7268)
Follow-up for https://github.com/chatmail/core/pull/7042, part of
https://github.com/chatmail/core/issues/6884.

This will make it possible to create invite-QR codes for broadcast
channels, and make them symmetrically end-to-end encrypted.

- [x] Go through all the changes in #7042, and check which ones I still
need, and revert all other changes
- [x] Use the classical Securejoin protocol, rather than the new 2-step
protocol
- [x] Make the Rust tests pass
- [x] Make the Python tests pass
- [x] Fix TODOs in the code
- [x] Test it, and fix any bugs I find
- [x] I found a bug when exporting all profiles at once fails sometimes,
though this bug is unrelated to channels:
https://github.com/chatmail/core/issues/7281
- [x] Do a self-review (i.e. read all changes, and check if I see some
things that should be changed)
- [x] Have this PR reviewed and merged
- [ ] Open an issue for "TODO: There is a known bug in the securejoin
protocol"
- [ ] Create an issue that outlines how we can improve the Securejoin
protocol in the future (I don't have the time to do this right now, but
want to do it sometime in winter)
- [ ] Write a guide for UIs how to adapt to the changes (see
https://github.com/deltachat/deltachat-android/pull/3886)

## Backwards compatibility

This is not very backwards compatible:
- Trying to join a symmetrically-encrypted broadcast channel with an old
device will fail
- If you joined a symmetrically-encrypted broadcast channel with one
device, and use an old core on the other device, then the other device
will show a mostly empty chat (except for two device messages)
- If you created a broadcast channel in the past, then you will get an
error message when trying to send into the channel:

> The up to now "experimental channels feature" is about to become an officially supported one. By that, privacy will be improved, it will become faster, and less traffic will be consumed.
> 
> As we do not guarantee feature-stability for such experiments, this means, that you will need to create the channel again. 
> 
> Here is what to do:
>  • Create a new channel
>  • Tap on the channel name
>  • Tap on "QR Invite Code"
>  • Have all recipients scan the QR code, or send them the link
> 
> If you have any questions, please send an email to delta@merlinux.eu or ask at https://support.delta.chat/.


## The symmetric encryption

Symmetric encryption uses a shared secret. Currently, we use AES128 for
encryption everywhere in Delta Chat, so, this is what I'm using for
broadcast channels (though it wouldn't be hard to switch to AES256).

The secret shared between all members of a broadcast channel has 258
bits of entropy (see `fn create_broadcast_shared_secret` in the code).

Since the shared secrets have more entropy than the AES session keys,
it's not necessary to have a hard-to-compute string2key algorithm, so,
I'm using the string2key algorithm `salted`. This is fast enough that
Delta Chat can just try out all known shared secrets. [^1] In order to
prevent DOS attacks, Delta Chat will not attempt to decrypt with a
string2key algorithm other than `salted` [^2].

## The "Securejoin" protocol that adds members to the channel after they
scanned a QR code

This PR uses the classical securejoin protocol, the same that is also
used for group and 1:1 invitations.

The messages sent back and forth are called `vg-request`,
`vg-auth-required`, `vg-request-with-auth`, and `vg-member-added`. I
considered using the `vc-` prefix, because from a protocol-POV, the
distinction between `vc-` and `vg-` isn't important (as @link2xt pointed
out in an in-person discussion), but
1. it would be weird if groups used `vg-` while broadcasts and 1:1 chats
used `vc-`,
2. we don't have a `vc-member-added` message yet, so, this would mean
one more different kind of message
3. we anyways want to switch to a new securejoin protocol soon, which
will be a backwards incompatible change with a transition phase. When we
do this change, we can make everything `vc-`.



[^1]: In a symmetrically encrypted message, it's not visible which
secret was used to encrypt without trying out all secrets. If this does
turn out to be too slow in the future, then we can remember which secret
was used more recently, and and try the most recent secret first. If
this is still too slow, then we can assign a short, non-unique (~2
characters) id to every shared secret, and send it in cleartext. The
receiving Delta Chat will then only try out shared secrets with this id.
Of course, this would leak a little bit of metadata in cleartext, so, I
would like to avoid it.
[^2]: A DOS attacker could send a message with a lot of encrypted
session keys, all of which use a very hard-to-compute string2key
algorithm. Delta Chat would then try to decrypt all of the encrypted
session keys with all of the known shared secrets. In order to prevent
this, as I said, Delta Chat will not attempt to decrypt with a
string2key algorithm other than `salted`

BREAKING CHANGE: A new QR type AskJoinBroadcast; cloning a broadcast
channel is no longer possible; manually adding a member to a broadcast
channel is no longer possible (only by having them scan a QR code)
2025-11-03 21:02:13 +01:00
link2xt
5b66535134 feat: verify contacts via Autocrypt-Gossip
This mechanism replaces `Chat-Verified` header.
New parameter `_verified=1` in `Autocrypt-Gossip`
header marks that the sender has the gossiped key
verified.

Using `_verified=1` instead of `_verified`
because it is less likely to cause troubles
with existing Autocrypt header parsers.
This is also how https://www.rfc-editor.org/rfc/rfc2045
defines parameter syntax.
2025-10-19 11:35:09 +00:00
link2xt
a745cf78ee test: test reception of multipart/alternative with text/calendar
In messages with text/plain, text/html and text/calendar parts
within a multipart/alternative, text/calendar part is currently ignored,
text/plain is displayed and HTML is available via HTML API.
2025-10-02 02:20:17 +00:00
iequidoo
7477ebbdd7 fix: Take the last valid Autocrypt header (#7167)
DKIM-Signatures apply to the last headers, so start from the last header and take a valid one,
i.e. skip headers having unknown critical attributes, etc. Though this means that Autocrypt header
must be "oversigned" to guarantee that a not DKIM-signed header isn't taken, still start from the
last header for consistency with processing other headers. This isn't a security issue anyway.
2025-09-22 15:38:32 -03:00
link2xt
a89b6321f1 feat: assign messages to key-contacts based on Issuer Fingerprint 2025-08-16 23:22:35 +00:00
link2xt
f41a3970b2 fix: do not add key-contacts to unencrypted groups
Encrypted message may create unencrypted groups
if the message does not have a Chat-Group-ID.
This can happen if v1 client sends an encrypted
message to opportunistically encrypted ad hoc group.
In this case `from_id` corresponds to the key-contact,
but we should add address-contact of the sender
to the member list.
2025-08-11 10:33:27 +00:00
link2xt
039a8b7c36 fix: lookup self by address if there is no fingerprint or gossip 2025-07-28 19:18:07 +00:00
Hocuri
85414558c5 test: Add regression test for verification-gossiping crash (#7033)
This adds a test for https://github.com/chatmail/core/pull/7032/.

The crash happened if you received a message that has the from contact
also in the "To: " and "Chat-Group-Member-Fpr: " headers. Not sure how
it happened that such a message was created; I managed to create one in
a test, but needed to access some internals of MimeFactory for that.

I then saved the email that is sent by Alice into the test-data
directory, and then made a test that Bob doesn't crash if he receives
this email. And as a sanity-check, also test that Bob marks Fiona as
verified after receiving this email.
2025-07-24 17:24:00 +02:00
ivn
22258f7269 fix!: Use Viewtype::File for messages with invalid images, images of unknown size, images > 50 Mpx (#6825)
BREAKING CHANGE: messages with invalid images, images of unknown size,
huge images, will have Viewtype::File

After changing the logic of Viewtype selection, I had to fix 3 old tests
that used invalid Base64 image data.

Co-authored-by: iequidoo <117991069+iequidoo@users.noreply.github.com>
2025-07-10 18:11:55 -03:00
link2xt
416131b4a2 feat: key-contacts
This change introduces a new type of contacts
identified by their public key fingerprint
rather than an e-mail address.

Encrypted chats now stay encrypted
and unencrypted chats stay unencrypted.
For example, 1:1 chats with key-contacts
are encrypted and 1:1 chats with address-contacts
are unencrypted.
Groups that have a group ID are encrypted
and can only contain key-contacts
while groups that don't have a group ID ("adhoc groups")
are unencrypted and can only contain address-contacts.

JSON-RPC API `reset_contact_encryption` is removed.
Python API `Contact.reset_encryption` is removed.
"Group tracking plugin" in legacy Python API was removed because it
relied on parsing email addresses from system messages with regexps.

Co-authored-by: Hocuri <hocuri@gmx.de>
Co-authored-by: iequidoo <dgreshilov@gmail.com>
Co-authored-by: B. Petersen <r10s@b44t.com>
2025-06-26 14:07:39 +00:00
iequidoo
c12c4f64c4 fix: Ignore hidden headers in IMF section
Hidden headers are nonstandard, so they aren't DKIM-signed by e.g. OpenDKIM if they appear in IMF
section.
2025-03-11 23:39:36 -03:00
link2xt
43a3e40bc7 fix: update mailparse to 0.16.1 to fix panic when parsing a message 2025-02-28 01:12:01 +00:00
Hocuri
0c0afead2c refactor: Move even more tests into their own files (#6521)
As always, I moved the tests from the biggest files. I left out
`mimefactory.rs` because @link2xt has an active PR modifying the tests.
2025-02-06 22:37:25 +01:00
iequidoo
bb3075c6fd test: Record the current wrong behaviour of HTML display of multipart messages (#4462) 2024-12-12 11:30:02 -03:00
link2xt
d036ad5853 fix: do not fail if Autocrypt Setup Message has no encryption preference
According to Autocrypt specification
Autocrypt Setup Message SHOULD
contain Autocrypt-Prefer-Encrypt header,
but K-9 6.802 does not include it.
2024-04-23 22:16:54 +00:00
link2xt
1adea3c678 fix: put overridden sender name into message info 2024-03-25 05:19:04 +00:00
link2xt
863a386d0f test: test that ASM "encrypted" with plaintext algorithm is not accepted 2024-03-04 21:10:04 +00:00
iequidoo
ba35e83db2 feat: Add device message about outgoing undecryptable messages (#5164)
Currently when a user sets up another device by logging in, a new key is created. If a message is
sent from either device outside, it cannot be decrypted by the other device.

The message is replaced with square bracket error like this:
```
<string name="systemmsg_cannot_decrypt">This message cannot be decrypted.\n\n• It might already help to simply reply to this message and ask the sender to send the message again.\n\n• If you just re-installed Delta Chat then it is best if you re-setup Delta Chat now and choose "Add as second device" or import a backup.</string>
```
(taken from Android repo `res/values/strings.xml`)

If the message is outgoing, it does not help to "simply reply to this message". Instead, we should
add a translatable device message of a special type so UI can link to the FAQ entry about second
device. But let's limit such notifications to 1 per day. And as for the undecryptable message
itself, let it go to Trash if it can't be assigned to a chat by its references.
2024-02-11 23:22:52 -03:00
link2xt
73d612a07d feat: do not drop unknown report attachments
In particular TLSRPT reports
contain files that may be interesting for admins.
Currently Delta Chat drops the attachment
so message appears as a text message without actual payload.
2024-01-24 16:13:20 +00:00
link2xt
da11542322 fix: do not remove contents from Schleuder ML messages
Before this fix actual contents of the message
reposted by Schleuder is considered a mailing list footer and removed,
not visible even in the "Show Full Message..." view.

With this change there will be two message bubbles,
one for header and one for the contents,
but it is still better than losing the contents completely.

Attempting to parse header part is out of scope for this change.
2024-01-05 15:42:56 +00:00
iequidoo
44227d7b86 fix: Put Message-ID into hidden headers and take it from there on receiver (#4798)
Put a copy of Message-ID into hidden headers and prefer it over the one in the IMF header section
that servers mess up with.

This also reverts "Set X-Microsoft-Original-Message-ID on outgoing emails for amazonaws (#3077)".
2023-12-21 16:14:52 -03:00
iequidoo
ebfbc11973 feat: Don't affect MimeMessage with "From" and secured headers from encrypted unsigned messages
If a message is encrypted, but unsigned:
- Don't set `MimeMessage::from_is_signed`.
- Remove "secure-join-fingerprint" and "chat-verified" headers from `MimeMessage`.
- Minor: Preserve "Subject" from the unencrypted top level if there's no "Subject" in the encrypted
  part, this message is displayed w/o a padlock anyway.

Apparently it didn't lead to any vulnerabilities because there are checks for
`MimeMessage::signatures.is_empty()` in all necessary places, but still the code looked dangerous,
especially because `from_is_singed` var name didn't correspond to its actual value (it was rather
`from_is_encrypted_maybe_signed`).
2023-12-01 19:06:11 -03:00
iequidoo
9cd3a7550b fix: Switch to EncryptionPreference::Mutual on a receipt of encrypted+signed message (#4707) 2023-11-03 23:32:02 -03:00
iequidoo
47d465e6e4 fix: Save mime headers for messages not signed with a known key (#4557)
If a message is unsigned or signed with an unknown key, `MimeMessage::was_encrypted()` returns
false. So, it mustn't be checked when deciding whether to look into
`MimeMessage::decoded_data`. Looking through git history one can see that it's just a wrong check
left in the code for historical reasons.
2023-08-31 14:07:12 -03:00
iequidoo
45e35b3571 feat: Guess message viewtype from "application/octet-stream" attachment extension (#4378) 2023-08-05 16:34:06 -03:00
link2xt
06ead557dc Do not add an error if the message is encrypted but not signed
Services like Lacre [1] on Disroot and Inbound Encryption on Posteo [2]
offer to encrypt all incoming messages with the provided OpenPGP
public key. Resulting messages are encrypted, but not end-to-end encrypted
and not signed by the sender, therefore should not have a padlock displayed.
However, such encrypted and unsigned message is also not an indication
of an error on ongoing attack, so we shoud not report this as a problem
to the user.

[1] https://lacre.io/
[2] https://posteo.de/en/help/how-do-i-activate-inbound-encryption-with-my-public-pgp-key
2022-12-23 10:49:41 +00:00
iequidoo
a3fe105256 Prefer encryption for the peer if the message is encrypted or signed with the known key (#3844)
Note that if the message is encrypted, we don't check whether it's signed with an attached key
currently, otherwise a massive refactoring of the code is needed because for encrypted messages a
signature is checked and discarded first now.
2022-12-19 19:33:39 +04:00
iequidoo
21f1439ad8 Treat attached PGP keys as peer keys with mutual encryption preference (#3778) 2022-12-13 04:57:45 +04:00
link2xt
b341cfd4d9 mimeparser: assume all Thunderbird users prefer encryption
Co-Authored-By: missytake <missytake@systemli.org>
2022-11-24 19:20:56 +00:00
Hocuri
b1c6c40fa7 Check DKIM Authentication-Results (#3583)
Fix #3507

Note that this is not intended for a release at this point! We first have to test whether it runs stable enough. If we want to make a release while we are not confident enough in authres-checking, then we have to disable it.

BTW, most of the 3000 new lines are in `test_data/messages/dkimchecks...`, not the actual code

da3a4b94 adds the results to the Message info. It currently does this by adding them to `hop_info`. Maybe we should rename `hop_info` to `extra_info` or something; this has the disadvantage that we can't rename the sql column name though.

Follow-ups for this could be:
- In `update_authservid_candidates()`: Implement the rest of the algorithm @hpk42 and me thought about. What's missing is remembering how sure we are that these are the right authserv-ids. Esp., when receiving a message sent from another account at the same domain, we can be quite sure that the authserv-ids in there are the ones of our email server. This will make authres-checking work with buzon.uy, disroot.org, yandex.ru, mailo.com, and riseup.net.
- Think about how we present this to the user - e.g. currently the only change is that we don't accept key changes, which will mean that the small lock on the message is not shown.
- And it will mean that we can fully enable AEAP, after revisiting the security implications of this, and assuming everyone (esp. @link2xt who pointed out the problems in the first place) feels comfortable with it.
2022-10-28 12:15:37 +02:00
link2xt
4b91a88bc9 Do not prepend subject to mailing list chat messages (#3253) 2022-09-05 08:12:33 +00:00
Hocuri
6ec9b0a0b0 Show attached .eml files as such (#3561)
Co-authored-by: bjoern <r10s@b44t.com>
2022-08-27 14:36:45 +00:00
link2xt
294d8862e4 Do not treat non-failed DSNs as NDNs 2022-07-14 20:01:45 +00:00
link2xt
32eb016ee7 mimeparser: do not squash NDN text parts into attachments
Text part usually contains an error message that we want to display in
the UI.
2022-07-10 18:18:45 +00:00
link2xt
715664273b Repair encrypted mails turned into attachments
Google Workspace has an option "Append footer" which appends standard
footer defined by administrator to all outgoing messages. However,
there is no plain text part in encrypted messages sent by Delta Chat,
so Google Workspace turn the message into multipart/mixed MIME, where
the first part is an empty plaintext part with a footer and the second
part is the original encrypted message.

This commit makes Delta Chat attempt to repair such messages,
similarly to how it already repairs "Mixed Up" MIME structure in
`get_mixed_up_mime`.
2022-05-14 15:18:51 +00:00
Hocuri
19a32cdfd3 Let MS Exchange MDNs mark the In-Reply-To message as read (#3075)
Fix https://github.com/deltachat/deltachat-core-rust/issues/2891
2022-02-17 09:56:00 +01:00
B. Petersen
8e8c10c438 rename w30 to webxdc 2022-01-13 11:11:50 +01:00
B. Petersen
b656a60234 check that the w30 app is actually an zip-archive with an index.html 2022-01-13 11:11:50 +01:00
B. Petersen
de20e4c9dd basic w30 sending and receiving 2022-01-13 11:11:50 +01:00
link2xt
630754b52e dc_receive_imf: don't fail on invalid address in the To field
This is an irrecoverable error, dc_receive_imf must not fail on it
as it prevents last seen UID from advancing, so the same message
is prefetched on each iteration of IMAP loop.
2022-01-02 00:20:44 +00:00
Hocuri
d47680733b Fix: Also show the hop_info for encrypted messages (#2923)
Before, the hop_info was shown only for unencrypted messages.

Credits: The bug was noticed by link2xt

Follow-up for #2751
2021-12-28 13:23:41 +01:00
link2xt
dae80cbe35 Recognize MS Exchange read receipts as read receipts
They contain X-MSExch-Correlation-Key header, but no
Original-Message-ID, so they cannot be used to find the original
message, but we want to recognize them as MDN nevertheless to assign
them to the trash chat.
2021-12-11 21:44:54 +00:00
link2xt
572260ec29 Test RFC 1847 encapsulation
https://datatracker.ietf.org/doc/html/rfc3156#section-6.1
2021-12-10 22:56:42 +00:00
link2xt
01db8d0130 test_utils: fix Alice's address in alice_keypair()
The key stored in test-data has @example.org identity.
2021-12-05 09:14:58 +00:00
bjoern
bffb41326c better names for more mailinglist-types (#2685)
* add a test for xing mailinglists

* strip long hash-prefixes from mailinglist name if we got the name from the List-Id as a last resort

* add a test for newsletter@ mailinglists

these mailinglists have the list-name in `From:`
and can be detected by addresses starting with `newsletter@`.

* if not list-name is set, use the `From:` name for addresses starting with `newsletter@`

this is similar to what we do with `notifications@`

* Update src/dc_receive_imf.rs

Co-authored-by: Hocuri <hocuri@gmx.de>

* add an example to the regex

Co-authored-by: Hocuri <hocuri@gmx.de>
2021-09-16 18:43:37 +02:00
Hocuri
46956caf75 Fix: Recognize ndns that put the headers into "message/global-headers" part (Improve ndn detection) (#2598)
I sent a message, and the ndn (Non Delivery Notification) was not parsed correctly, so here comes
the fix and the test.
2021-09-12 21:02:51 +02:00
bjoern
da2f30786b get correct names of .xt.local mailinglists (#2665)
* add a test for .xt.local mailinglists

* get correct names of .xt.local mailinglists

these mailinglist probably come from the xt:Commerce system
and are pretty widely used.

i have not seen an .xt.local mailinglist with name set in List-Id,
however, if that happens, it will still be taken.

only if the name is unset,
we use the name from the From-header.
2021-09-12 15:34:29 +02:00
Hocuri
223aeb7b1a Fix: Make emails forwarded by GMX readable (#2600)
Recognizing these emails as forwarded would probably be too complicated and require too much special-casing, but now the user can access the email text via "Show full message".

fix #2599

Co-authored-by: B. Petersen <r10s@b44t.com>
2021-08-14 18:05:17 +02:00