annotate libervia/backend/plugins/plugin_sec_aesgcm.py @ 4226:3f7ca590a5da

cli (pubsub): use `PEP` when service is not specified in error message.
author Goffi <goffi@goffi.org>
date Tue, 05 Mar 2024 17:31:56 +0100
parents 4b842c1fb686
children 0d7bb4df2343
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
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4051
diff changeset
31 from libervia.backend.core.i18n import _
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4051
diff changeset
32 from libervia.backend.core.constants import Const as C
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4051
diff changeset
33 from libervia.backend.core import exceptions
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4051
diff changeset
34 from libervia.backend.tools import stream
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4051
diff changeset
35 from libervia.backend.core.log import getLogger
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4051
diff changeset
36 from libervia.backend.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(
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
70 self.can_handle_attachment, 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)
4051
c23cad65ae99 core: renamed `messageReceived` trigger to `message_received`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
73 host.trigger.add("message_received", self._message_received_trigger)
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(
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
126 self.on_data_download,
3186
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
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
135 async def can_handle_attachment(self, client, data):
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3205
diff changeset
136 try:
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
137 await self._http_upload.get_http_upload_entity(client)
3219
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).
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
159 attachments = data["extra"][C.KEY_ATTACHMENTS]
3219
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()
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
168 del data["extra"][C.KEY_ATTACHMENTS]
3219
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'],
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
184 extra={C.KEY_ATTACHMENTS: [attachment]},
3219
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
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
193 def on_data_download(self, data, client, file_obj, decryptor):
3090
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
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
280 def _pop_aesgcm_links(self, match, links):
3174
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
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
286 def _check_aesgcm_attachments(self, client, data):
3174
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(
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
293 partial(self._pop_aesgcm_links, links=links),
3174
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)
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
302 attachments = data['extra'].setdefault(C.KEY_ATTACHMENTS, [])
3174
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:
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
310 attachment[C.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
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
322 def _message_received_trigger(self, client, message_elt, post_treat):
3174
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
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
326 post_treat.addCallback(partial(self._check_aesgcm_attachments, client))
3174
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