annotate sat/plugins/plugin_sec_aesgcm.py @ 4001:32d714a8ea51

plugin XEP-0045: dot not wait for MAM retrieval to be completed: in `_join_MAM`, `room.fully_joined` is called before retrieving the MAM archive, as the process can be very long, and is not necessary to have the room working (message can be received after being in the room, and added out of order). This avoid blocking the `join` workflow for an extended time. Some renaming and coroutine integrations.
author Goffi <goffi@goffi.org>
date Fri, 10 Mar 2023 17:22:41 +0100
parents 0ff265725489
children 78b5f356900c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
3 # SàT plugin for handling AES-GCM file encryption
3479
be6d91572633 date update
Goffi <goffi@goffi.org>
parents: 3222
diff changeset
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
5
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # (at your option) any later version.
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
18
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
19 import re
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from textwrap import dedent
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from functools import partial
3186
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
22 from urllib import parse
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
23 import mimetypes
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 import secrets
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from cryptography.hazmat.primitives import ciphers
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from cryptography.hazmat.primitives.ciphers import modes
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from cryptography.hazmat import backends
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 from cryptography.exceptions import AlreadyFinalized
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 import treq
3186
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
30 from twisted.internet import defer
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 from sat.core.i18n import _
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 from sat.core.constants import Const as C
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from sat.core import exceptions
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 from sat.tools import stream
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 from sat.core.log import getLogger
3205
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
36 from sat.tools.web import treq_client_no_ssl
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
37
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 log = getLogger(__name__)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
39
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 PLUGIN_INFO = {
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 C.PI_NAME: "AES-GCM",
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 C.PI_IMPORT_NAME: "AES-GCM",
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 C.PI_TYPE: "SEC",
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 C.PI_PROTOCOLS: ["OMEMO Media sharing"],
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
45 C.PI_DEPENDENCIES: ["XEP-0363", "XEP-0384", "DOWNLOAD", "ATTACH"],
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 C.PI_MAIN: "AESGCM",
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 C.PI_HANDLER: "no",
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 C.PI_DESCRIPTION: dedent(_("""\
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 Implementation of AES-GCM scheme, a way to encrypt files (not official XMPP standard).
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 See https://xmpp.org/extensions/inbox/omemo-media-sharing.html for details
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 """)),
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 }
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
54 AESGCM_RE = re.compile(
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
55 r'aesgcm:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9'
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
56 r'()@:%_\+.~#?&\/\/=]*)')
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
57
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
58
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 class AESGCM(object):
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
60
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 def __init__(self, host):
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 self.host = host
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
63 log.info(_("AESGCM plugin initialization"))
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
64 self._http_upload = host.plugins['XEP-0363']
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
65 self._attach = host.plugins["ATTACH"]
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
66 host.plugins["DOWNLOAD"].register_scheme(
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 "aesgcm", self.download
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 )
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
69 self._attach.register(
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
70 self.canHandleAttachment, self.attach, encrypted=True)
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
71 host.trigger.add("XEP-0363_upload_pre_slot", self._upload_pre_slot)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
72 host.trigger.add("XEP-0363_upload", self._upload_trigger)
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
73 host.trigger.add("messageReceived", self._messageReceivedTrigger)
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
74
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 async def download(self, client, uri_parsed, dest_path, options):
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
76 fragment = bytes.fromhex(uri_parsed.fragment)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
77
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 # legacy method use 16 bits IV, but OMEMO media sharing published spec indicates
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 # which is 12 bits IV (AES-GCM spec recommandation), so we have to determine
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 # which size has been used.
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 if len(fragment) == 48:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 iv_size = 16
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 elif len(fragment) == 44:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 iv_size = 12
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 else:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 raise ValueError(
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 f"Invalid URL fragment, can't decrypt file at {uri_parsed.get_url()}")
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
88
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 iv, key = fragment[:iv_size], fragment[iv_size:]
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
90
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 decryptor = ciphers.Cipher(
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 ciphers.algorithms.AES(key),
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 modes.GCM(iv),
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 backend=backends.default_backend(),
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 ).decryptor()
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
96
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 download_url = parse.urlunparse(
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 ('https', uri_parsed.netloc, uri_parsed.path, '', '', ''))
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
99
3205
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
100 if options.get('ignore_tls_errors', False):
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
101 log.warning(
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
102 "TLS certificate check disabled, this is highly insecure"
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
103 )
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
104 treq_client = treq_client_no_ssl
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
105 else:
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
106 treq_client = treq
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
107
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
108 head_data = await treq_client.head(download_url)
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 content_length = int(head_data.headers.getRawHeaders('content-length')[0])
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 # the 128 bits tag is put at the end
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 file_size = content_length - 16
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
112
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 file_obj = stream.SatFile(
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 self.host,
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 client,
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 dest_path,
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 mode="wb",
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 size = file_size,
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 )
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
120
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 progress_id = file_obj.uid
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
122
3205
2c0628f3927e plugin download, aesgcm: disable TLS check if `check_certificate` setting is disabled
Goffi <goffi@goffi.org>
parents: 3196
diff changeset
123 resp = await treq_client.get(download_url, unbuffered=True)
3186
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
124 if resp.code == 200:
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
125 d = treq.collect(resp, partial(
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
126 self.onDataDownload,
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
127 client=client,
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
128 file_obj=file_obj,
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
129 decryptor=decryptor))
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
130 else:
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
131 d = defer.Deferred()
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
132 self.host.plugins["DOWNLOAD"].errback_download(file_obj, d, resp)
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 return progress_id, d
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
134
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
135 async def canHandleAttachment(self, client, data):
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
136 try:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
137 await self._http_upload.getHTTPUploadEntity(client)
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
138 except exceptions.NotFound:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
139 return False
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
140 else:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
141 return True
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
142
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
143 async def _upload_cb(self, client, filepath, filename, extra):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
144 extra['encryption'] = C.ENC_AES_GCM
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
145 return await self._http_upload.file_http_upload(
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
146 client=client,
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
147 filepath=filepath,
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
148 filename=filename,
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
149 extra=extra
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
150 )
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
151
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
152 async def attach(self, client, data):
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
153 # XXX: the attachment removal/resend code below is due to the one file per
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
154 # message limitation of OMEMO media sharing unofficial XEP. We have to remove
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
155 # attachments from original message, and send them one by one.
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
156 # TODO: this is to be removed when a better mechanism is available with OMEMO (now
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
157 # possible with the 0.4 version of OMEMO, it's possible to encrypt other stanza
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
158 # elements than body).
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
159 attachments = data["extra"][C.MESS_KEY_ATTACHMENTS]
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
160 if not data['message'] or data['message'] == {'': ''}:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
161 extra_attachments = attachments[1:]
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
162 del attachments[1:]
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
163 await self._attach.upload_files(client, data, upload_cb=self._upload_cb)
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
164 else:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
165 # we have a message, we must send first attachment separately
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
166 extra_attachments = attachments[:]
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
167 attachments.clear()
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
168 del data["extra"][C.MESS_KEY_ATTACHMENTS]
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
169
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
170 body_elt = data["xml"].body
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
171 if body_elt is None:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
172 body_elt = data["xml"].addElement("body")
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
173
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
174 for attachment in attachments:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
175 body_elt.addContent(attachment["url"])
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
176
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
177 for attachment in extra_attachments:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
178 # we send all remaining attachment in a separate message
3222
653fa213d2f8 plugin aesgcm: wait for each splitted message to be sent before sending next one
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
179 await client.sendMessage(
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
180 to_jid=data['to'],
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
181 message={'': ''},
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
182 subject=data['subject'],
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
183 mess_type=data['type'],
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
184 extra={C.MESS_KEY_ATTACHMENTS: [attachment]},
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
185 )
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
186
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
187 if ((not data['extra']
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
188 and (not data['message'] or data['message'] == {'': ''})
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
189 and not data['subject'])):
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
190 # nothing left to send, we can cancel the message
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
191 raise exceptions.CancelError("Cancelled by AESGCM attachment handling")
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
192
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 def onDataDownload(self, data, client, file_obj, decryptor):
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 if file_obj.tell() + len(data) > file_obj.size:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 # we're reaching end of file with this bunch of data
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 # we may still have a last bunch if the tag is incomplete
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 bytes_left = file_obj.size - file_obj.tell()
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 if bytes_left > 0:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 decrypted = decryptor.update(data[:bytes_left])
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 file_obj.write(decrypted)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 tag = data[bytes_left:]
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 else:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 tag = data
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 if len(tag) < 16:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 # the tag is incomplete, either we'll get the rest in next data bunch
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 # or we have already the other part from last bunch of data
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 try:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 # we store partial tag in decryptor._sat_tag
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 tag = decryptor._sat_tag + tag
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 except AttributeError:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
211 # no other part, we'll get the rest at next bunch
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 decryptor.sat_tag = tag
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 else:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 # we have the complete tag, it must be 128 bits
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 if len(tag) != 16:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 raise ValueError(f"Invalid tag: {tag}")
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 remain = decryptor.finalize_with_tag(tag)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 file_obj.write(remain)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 file_obj.close()
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 else:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 decrypted = decryptor.update(data)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 file_obj.write(decrypted)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
223
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
224 def _upload_pre_slot(self, client, extra, file_metadata):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
225 if extra.get('encryption') != C.ENC_AES_GCM:
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 return True
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 # the tag is appended to the file
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
228 file_metadata["size"] += 16
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 return True
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
230
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 def _encrypt(self, data, encryptor):
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 if data:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 return encryptor.update(data)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 else:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 try:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 # end of file is reached, me must finalize
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 ret = encryptor.finalize()
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 tag = encryptor.tag
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 return ret + tag
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 except AlreadyFinalized:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 # as we have already finalized, we can now send EOF
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 return b''
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
243
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
244 def _upload_trigger(self, client, extra, sat_file, file_producer, slot):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
245 if extra.get('encryption') != C.ENC_AES_GCM:
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 return True
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 log.debug("encrypting file with AES-GCM")
3178
98b321234068 plugin aesgcm: use 12 bytes Initialisation Vector:
Goffi <goffi@goffi.org>
parents: 3174
diff changeset
248 iv = secrets.token_bytes(12)
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 key = secrets.token_bytes(32)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 fragment = f'{iv.hex()}{key.hex()}'
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 ori_url = parse.urlparse(slot.get)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 # we change the get URL with the one with aesgcm scheme and containing the
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 # encoded key + iv
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 slot.get = parse.urlunparse(['aesgcm', *ori_url[1:5], fragment])
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
255
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 # encrypted data size will be bigger than original file size
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 # so we need to check with final data length to avoid a warning on close()
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 sat_file.check_size_with_read = True
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
259
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
260 # file_producer get length directly from file, and this cause trouble as
3090
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 # we have to change the size because of encryption. So we adapt it here,
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
262 # else the producer would stop reading prematurely
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
263 file_producer.length = sat_file.size
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
264
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 encryptor = ciphers.Cipher(
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 ciphers.algorithms.AES(key),
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 modes.GCM(iv),
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 backend=backends.default_backend(),
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 ).encryptor()
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
270
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 if sat_file.data_cb is not None:
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 raise exceptions.InternalError(
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 f"data_cb was expected to be None, it is set to {sat_file.data_cb}")
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
274
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 # with data_cb we encrypt the file on the fly
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
276 sat_file.data_cb = partial(self._encrypt, encryptor=encryptor)
4f8bdf50593f plugin sec aesgcm: new plugin handling `aesgcm:` scheme for e2e encrypted media sharing:
Goffi <goffi@goffi.org>
parents:
diff changeset
277 return True
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
278
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
279
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
280 def _popAESGCMLinks(self, match, links):
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
281 link = match.group()
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
282 if link not in links:
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
283 links.append(link)
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
284 return ""
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
285
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
286 def _checkAESGCMAttachments(self, client, data):
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
287 if not data.get('message'):
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
288 return data
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
289 links = []
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
290
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
291 for lang, message in list(data['message'].items()):
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
292 message = AESGCM_RE.sub(
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
293 partial(self._popAESGCMLinks, links=links),
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
294 message)
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
295 if links:
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
296 message = message.strip()
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
297 if not message:
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
298 del data['message'][lang]
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
299 else:
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
300 data['message'][lang] = message
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
301 mess_encrypted = client.encryption.isEncrypted(data)
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
302 attachments = data['extra'].setdefault(C.MESS_KEY_ATTACHMENTS, [])
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
303 for link in links:
3186
84b0c8b4dee0 plugin download, aesgcm: fixed handling of HTTP errors
Goffi <goffi@goffi.org>
parents: 3178
diff changeset
304 path = parse.urlparse(link).path
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
305 attachment = {
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
306 "url": link,
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
307 }
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
308 media_type = mimetypes.guess_type(path, strict=False)[0]
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
309 if media_type is not None:
3196
adf1aeaa0d37 core (constants): renamed `MESS_KEY_MEDIA_TYPE` to `MESS_KEY_ATTACHMENTS_MEDIA_TYPE`
Goffi <goffi@goffi.org>
parents: 3186
diff changeset
310 attachment[C.MESS_KEY_ATTACHMENTS_MEDIA_TYPE] = media_type
3174
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
311
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
312 if mess_encrypted:
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
313 # we don't add the encrypted flag if the message itself is not
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
314 # encrypted, because the decryption key is part of the link,
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
315 # so sending it over unencrypted channel is like having no
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
316 # encryption at all.
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
317 attachment['encrypted'] = True
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
318 attachments.append(attachment)
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
319
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
320 return data
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
321
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
322 def _messageReceivedTrigger(self, client, message_elt, post_treat):
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
323 # we use a post_treat callback instead of "message_parse" trigger because we need
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
324 # to check if the "encrypted" flag is set to decide if we add the same flag to the
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
325 # attachment
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
326 post_treat.addCallback(partial(self._checkAESGCMAttachments, client))
c90f27ce52b0 plugin aesgcm: look for "aesgcm" links in body to use them as attachments
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
327 return True