Mercurial > libervia-backend
annotate libervia/backend/plugins/plugin_xep_0448.py @ 4306:94e0968987cd
plugin XEP-0033: code modernisation, improve delivery, data validation:
- Code has been rewritten using Pydantic models and `async` coroutines for data validation
and cleaner element parsing/generation.
- Delivery has been completely rewritten. It now works even if server doesn't support
multicast, and send to local multicast service first. Delivering to local multicast
service first is due to bad support of XEP-0033 in server (notably Prosody which has an
incomplete implementation), and the current impossibility to detect if a sub-domain
service handles fully multicast or only for local domains. This is a workaround to have
a good balance between backward compatilibity and use of bandwith, and to make it work
with the incoming email gateway implementation (the gateway will only deliver to
entities of its own domain).
- disco feature checking now uses `async` corountines. `host` implementation still use
Deferred return values for compatibility with legacy code.
rel 450
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 26 Sep 2024 16:12:01 +0200 |
parents | 0d7bb4df2343 |
children |
rev | line source |
---|---|
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
1 #!/usr/bin/env python3 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
2 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
3 # Libervia plugin for handling stateless file sharing encryption |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
4 # Copyright (C) 2009-2022 Jérôme Poisson (goffi@goffi.org) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
5 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
6 # This program is free software: you can redistribute it and/or modify |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
7 # it under the terms of the GNU Affero General Public License as published by |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
8 # the Free Software Foundation, either version 3 of the License, or |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
9 # (at your option) any later version. |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
10 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
11 # This program is distributed in the hope that it will be useful, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
14 # GNU Affero General Public License for more details. |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
15 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
16 # You should have received a copy of the GNU Affero General Public License |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
18 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
19 import base64 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
20 from functools import partial |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
21 from pathlib import Path |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
22 import secrets |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
23 from textwrap import dedent |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
24 from typing import Any, Dict, Optional, Tuple, Union |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
25 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
26 from cryptography.exceptions import AlreadyFinalized |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
27 from cryptography.hazmat import backends |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
28 from cryptography.hazmat.primitives import ciphers |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
29 from cryptography.hazmat.primitives.ciphers import CipherContext, modes |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
30 from cryptography.hazmat.primitives.padding import PKCS7, PaddingContext |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
31 import treq |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
32 from twisted.internet import defer |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
33 from twisted.words.protocols.jabber.xmlstream import XMPPHandler |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
34 from twisted.words.xish import domish |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
35 from wokkel import disco, iwokkel |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
36 from zope.interface import implementer |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
37 |
4071
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
38 from libervia.backend.core import exceptions |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
39 from libervia.backend.core.constants import Const as C |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
40 from libervia.backend.core.core_types import SatXMPPEntity |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
41 from libervia.backend.core.i18n import _ |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
42 from libervia.backend.core.log import getLogger |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
43 from libervia.backend.tools import stream |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
44 from libervia.backend.tools.web import treq_client_no_ssl |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
45 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
46 log = getLogger(__name__) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
47 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
48 IMPORT_NAME = "XEP-0448" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
49 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
50 PLUGIN_INFO = { |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
51 C.PI_NAME: "Encryption for Stateless File Sharing", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
52 C.PI_IMPORT_NAME: IMPORT_NAME, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
53 C.PI_TYPE: C.PLUG_TYPE_EXP, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
54 C.PI_PROTOCOLS: ["XEP-0448"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
55 C.PI_DEPENDENCIES: [ |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
56 "XEP-0103", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
57 "XEP-0300", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
58 "XEP-0334", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
59 "XEP-0363", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
60 "XEP-0384", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
61 "XEP-0447", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
62 "DOWNLOAD", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
63 "ATTACH", |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
64 ], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
65 C.PI_MAIN: "XEP_0448", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
66 C.PI_HANDLER: "yes", |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
67 C.PI_DESCRIPTION: dedent( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
68 _( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
69 """\ |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
70 Implementation of e2e encryption for media sharing |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
71 """ |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
72 ) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
73 ), |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
74 } |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
75 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
76 NS_ESFS = "urn:xmpp:esfs:0" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
77 NS_AES_128_GCM = "urn:xmpp:ciphers:aes-128-gcm-nopadding:0" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
78 NS_AES_256_GCM = "urn:xmpp:ciphers:aes-256-gcm-nopadding:0" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
79 NS_AES_256_CBC = "urn:xmpp:ciphers:aes-256-cbc-pkcs7:0" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
80 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
81 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
82 class XEP_0448: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
83 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
84 def __init__(self, host): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
85 self.host = host |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
86 log.info(_("XEP_0448 plugin initialization")) |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4023
diff
changeset
|
87 host.register_namespace("esfs", NS_ESFS) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
88 self._u = host.plugins["XEP-0103"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
89 self._h = host.plugins["XEP-0300"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
90 self._hints = host.plugins["XEP-0334"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
91 self._http_upload = host.plugins["XEP-0363"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
92 self._o = host.plugins["XEP-0384"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
93 self._sfs = host.plugins["XEP-0447"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
94 self._sfs.register_source_handler( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
95 NS_ESFS, "encrypted", self.parse_encrypted_elt, encrypted=True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
96 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
97 self._attach = host.plugins["ATTACH"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
98 self._attach.register( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
99 self.can_handle_attachment, self.attach, encrypted=True, priority=1000 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
100 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
101 host.plugins["DOWNLOAD"].register_download_handler(NS_ESFS, self.download) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
102 host.trigger.add("XEP-0363_upload_pre_slot", self._upload_pre_slot) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
103 host.trigger.add("XEP-0363_upload", self._upload_trigger) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
104 |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4023
diff
changeset
|
105 def get_handler(self, client): |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
106 return XEP0448Handler() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
107 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
108 def parse_encrypted_elt(self, encrypted_elt: domish.Element) -> Dict[str, Any]: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
109 """Parse an <encrypted> element and return corresponding source data |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
110 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
111 @param encrypted_elt: element to parse |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
112 @raise exceptions.DataError: the element is invalid |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
113 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
114 """ |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
115 sources = self._sfs.parse_sources_elt(encrypted_elt) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
116 if not sources: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
117 raise exceptions.NotFound("sources are missing in {encrypted_elt.toXml()}") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
118 if len(sources) > 1: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
119 log.debug( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
120 "more that one sources has been found, this is not expected, only the " |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
121 "first one will be used" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
122 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
123 source = sources[0] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
124 source["type"] = NS_ESFS |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
125 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
126 encrypted_data = source["encrypted_data"] = { |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
127 "cipher": encrypted_elt["cipher"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
128 "key": str(next(encrypted_elt.elements(NS_ESFS, "key"))), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
129 "iv": str(next(encrypted_elt.elements(NS_ESFS, "iv"))), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
130 } |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
131 except (KeyError, StopIteration): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
132 raise exceptions.DataError( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
133 "invalid <encrypted/> element: {encrypted_elt.toXml()}" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
134 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
135 try: |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4023
diff
changeset
|
136 hash_algo, hash_value = self._h.parse_hash_elt(encrypted_elt) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
137 except exceptions.NotFound: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
138 pass |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
139 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
140 encrypted_data["hash_algo"] = hash_algo |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
141 encrypted_data["hash"] = base64.b64encode(hash_value.encode()).decode() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
142 return source |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
143 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
144 async def download( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
145 self, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
146 client: SatXMPPEntity, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
147 attachment: Dict[str, Any], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
148 source: Dict[str, Any], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
149 dest_path: Union[Path, str], |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
150 extra: Optional[Dict[str, Any]] = None, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
151 ) -> Tuple[str, defer.Deferred]: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
152 # TODO: check hash |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
153 if extra is None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
154 extra = {} |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
155 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
156 encrypted_data = source["encrypted_data"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
157 cipher = encrypted_data["cipher"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
158 iv = base64.b64decode(encrypted_data["iv"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
159 key = base64.b64decode(encrypted_data["key"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
160 except KeyError as e: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
161 raise ValueError(f"{source} has incomplete encryption data: {e}") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
162 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
163 download_url = source["url"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
164 except KeyError: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
165 raise ValueError(f"{source} has missing URL") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
166 |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
167 if extra.get("ignore_tls_errors", False): |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
168 log.warning("TLS certificate check disabled, this is highly insecure") |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
169 treq_client = treq_client_no_ssl |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
170 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
171 treq_client = treq |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
172 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
173 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
174 file_size = int(attachment["size"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
175 except (KeyError, ValueError): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
176 head_data = await treq_client.head(download_url) |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
177 content_length = int(head_data.headers.getRawHeaders("content-length")[0]) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
178 # the 128 bits tag is put at the end |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
179 file_size = content_length - 16 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
180 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
181 file_obj = stream.SatFile( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
182 self.host, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
183 client, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
184 dest_path, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
185 mode="wb", |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
186 size=file_size, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
187 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
188 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
189 if cipher in (NS_AES_128_GCM, NS_AES_256_GCM): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
190 decryptor = ciphers.Cipher( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
191 ciphers.algorithms.AES(key), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
192 modes.GCM(iv), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
193 backend=backends.default_backend(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
194 ).decryptor() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
195 decrypt_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
196 self.gcm_decrypt, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
197 client=client, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
198 file_obj=file_obj, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
199 decryptor=decryptor, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
200 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
201 finalize_cb = None |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
202 elif cipher == NS_AES_256_CBC: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
203 cipher_algo = ciphers.algorithms.AES(key) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
204 decryptor = ciphers.Cipher( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
205 cipher_algo, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
206 modes.CBC(iv), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
207 backend=backends.default_backend(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
208 ).decryptor() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
209 unpadder = PKCS7(cipher_algo.block_size).unpadder() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
210 decrypt_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
211 self.cbc_decrypt, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
212 client=client, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
213 file_obj=file_obj, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
214 decryptor=decryptor, |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
215 unpadder=unpadder, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
216 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
217 finalize_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
218 self.cbc_decrypt_finalize, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
219 file_obj=file_obj, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
220 decryptor=decryptor, |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
221 unpadder=unpadder, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
222 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
223 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
224 msg = f"cipher {cipher!r} is not supported" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
225 file_obj.close(error=msg) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
226 log.warning(msg) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
227 raise exceptions.CancelError(msg) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
228 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
229 progress_id = file_obj.uid |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
230 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
231 resp = await treq_client.get(download_url, unbuffered=True) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
232 if resp.code == 200: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
233 d = treq.collect(resp, partial(decrypt_cb)) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
234 if finalize_cb is not None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
235 d.addCallback(lambda __: finalize_cb()) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
236 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
237 d = defer.Deferred() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
238 self.host.plugins["DOWNLOAD"].errback_download(file_obj, d, resp) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
239 return progress_id, d |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
240 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
241 async def can_handle_attachment(self, client, data): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
242 # FIXME: check if SCE is supported without checking which e2ee algo is used |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
243 if client.encryption.get_namespace(data["to"]) != self._o.NS_TWOMEMO: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
244 # we need SCE, and it is currently supported only by TWOMEMO, thus we can't |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
245 # handle the attachment if it's not activated |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
246 return False |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
247 try: |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4023
diff
changeset
|
248 await self._http_upload.get_http_upload_entity(client) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
249 except exceptions.NotFound: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
250 return False |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
251 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
252 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
253 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
254 async def _upload_cb(self, client, filepath, filename, extra): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
255 attachment = extra["attachment"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
256 extra["encryption"] = IMPORT_NAME |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
257 attachment["encryption_data"] = extra["encryption_data"] = { |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
258 "algorithm": C.ENC_AES_GCM, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
259 "iv": secrets.token_bytes(12), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
260 "key": secrets.token_bytes(32), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
261 } |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
262 attachment["filename"] = filename |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
263 return await self._http_upload.file_http_upload( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
264 client=client, filepath=filepath, filename="encrypted", extra=extra |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
265 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
266 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
267 async def attach(self, client, data): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
268 # XXX: for now, XEP-0447/XEP-0448 only allow to send one file per <message/>, thus |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
269 # we need to send each file in a separate message, in the same way as for |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
270 # plugin_sec_aesgcm. |
4023
78b5f356900c
component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents:
3934
diff
changeset
|
271 attachments = data["extra"][C.KEY_ATTACHMENTS] |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
272 if not data["message"] or data["message"] == {"": ""}: |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
273 extra_attachments = attachments[1:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
274 del attachments[1:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
275 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
276 # we have a message, we must send first attachment separately |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
277 extra_attachments = attachments[:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
278 attachments.clear() |
4023
78b5f356900c
component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents:
3934
diff
changeset
|
279 del data["extra"][C.KEY_ATTACHMENTS] |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
280 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
281 if attachments: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
282 if len(attachments) > 1: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
283 raise exceptions.InternalError( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
284 "There should not be more that one attachment at this point" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
285 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
286 await self._attach.upload_files(client, data, upload_cb=self._upload_cb) |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4023
diff
changeset
|
287 self._hints.add_hint_elements(data["xml"], [self._hints.HINT_STORE]) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
288 for attachment in attachments: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
289 encryption_data = attachment.pop("encryption_data") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
290 file_hash = (attachment["hash_algo"], attachment["hash"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
291 file_sharing_elt = self._sfs.get_file_sharing_elt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
292 [], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
293 name=attachment["filename"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
294 size=attachment["size"], |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
295 file_hash=file_hash, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
296 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
297 encrypted_elt = file_sharing_elt.sources.addElement( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
298 (NS_ESFS, "encrypted") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
299 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
300 encrypted_elt["cipher"] = NS_AES_256_GCM |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
301 encrypted_elt.addElement( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
302 "key", content=base64.b64encode(encryption_data["key"]).decode() |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
303 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
304 encrypted_elt.addElement( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
305 "iv", content=base64.b64encode(encryption_data["iv"]).decode() |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
306 ) |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
307 encrypted_elt.addChild( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
308 self._h.build_hash_elt( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
309 attachment["encrypted_hash"], attachment["encrypted_hash_algo"] |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
310 ) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
311 ) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
312 encrypted_elt.addChild( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
313 self._sfs.get_sources_elt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
314 [self._u.get_url_data_elt(attachment["url"])] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
315 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
316 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
317 data["xml"].addChild(file_sharing_elt) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
318 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
319 for attachment in extra_attachments: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
320 # we send all remaining attachment in a separate message |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
321 await client.sendMessage( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
322 to_jid=data["to"], |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
323 message={"": ""}, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
324 subject=data["subject"], |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
325 mess_type=data["type"], |
4023
78b5f356900c
component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents:
3934
diff
changeset
|
326 extra={C.KEY_ATTACHMENTS: [attachment]}, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
327 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
328 |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
329 if ( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
330 not data["extra"] |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
331 and (not data["message"] or data["message"] == {"": ""}) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
332 and not data["subject"] |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
333 ): |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
334 # nothing left to send, we can cancel the message |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
335 raise exceptions.CancelError("Cancelled by XEP_0448 attachment handling") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
336 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
337 def gcm_decrypt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
338 self, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
339 data: bytes, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
340 client: SatXMPPEntity, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
341 file_obj: stream.SatFile, |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
342 decryptor: CipherContext, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
343 ) -> None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
344 if file_obj.tell() + len(data) > file_obj.size: # type: ignore |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
345 # we're reaching end of file with this bunch of data |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
346 # we may still have a last bunch if the tag is incomplete |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
347 bytes_left = file_obj.size - file_obj.tell() # type: ignore |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
348 if bytes_left > 0: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
349 decrypted = decryptor.update(data[:bytes_left]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
350 file_obj.write(decrypted) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
351 tag = data[bytes_left:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
352 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
353 tag = data |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
354 if len(tag) < 16: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
355 # the tag is incomplete, either we'll get the rest in next data bunch |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
356 # or we have already the other part from last bunch of data |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
357 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
358 # we store partial tag in decryptor._sat_tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
359 tag = decryptor._sat_tag + tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
360 except AttributeError: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
361 # no other part, we'll get the rest at next bunch |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
362 decryptor.sat_tag = tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
363 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
364 # we have the complete tag, it must be 128 bits |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
365 if len(tag) != 16: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
366 raise ValueError(f"Invalid tag: {tag}") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
367 remain = decryptor.finalize_with_tag(tag) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
368 file_obj.write(remain) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
369 file_obj.close() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
370 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
371 decrypted = decryptor.update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
372 file_obj.write(decrypted) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
373 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
374 def cbc_decrypt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
375 self, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
376 data: bytes, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
377 client: SatXMPPEntity, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
378 file_obj: stream.SatFile, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
379 decryptor: CipherContext, |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
380 unpadder: PaddingContext, |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
381 ) -> None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
382 decrypted = decryptor.update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
383 file_obj.write(unpadder.update(decrypted)) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
384 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
385 def cbc_decrypt_finalize( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
386 self, file_obj: stream.SatFile, decryptor: CipherContext, unpadder: PaddingContext |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
387 ) -> None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
388 decrypted = decryptor.finalize() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
389 file_obj.write(unpadder.update(decrypted)) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
390 file_obj.write(unpadder.finalize()) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
391 file_obj.close() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
392 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
393 def _upload_pre_slot(self, client, extra, file_metadata): |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
394 if extra.get("encryption") != IMPORT_NAME: |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
395 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
396 # the tag is appended to the file |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
397 file_metadata["size"] += 16 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
398 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
399 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
400 def _encrypt(self, data: bytes, encryptor: CipherContext, attachment: dict) -> bytes: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
401 if data: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
402 attachment["hasher"].update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
403 ret = encryptor.update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
404 attachment["encrypted_hasher"].update(ret) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
405 return ret |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
406 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
407 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
408 # end of file is reached, me must finalize |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
409 fin = encryptor.finalize() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
410 tag = encryptor.tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
411 ret = fin + tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
412 hasher = attachment.pop("hasher") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
413 attachment["hash"] = hasher.hexdigest() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
414 encrypted_hasher = attachment.pop("encrypted_hasher") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
415 encrypted_hasher.update(ret) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
416 attachment["encrypted_hash"] = encrypted_hasher.hexdigest() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
417 return ret |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
418 except AlreadyFinalized: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
419 # as we have already finalized, we can now send EOF |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
420 return b"" |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
421 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
422 def _upload_trigger(self, client, extra, sat_file, file_producer, slot): |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
423 if extra.get("encryption") != IMPORT_NAME: |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
424 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
425 attachment = extra["attachment"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
426 encryption_data = extra["encryption_data"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
427 log.debug("encrypting file with AES-GCM") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
428 iv = encryption_data["iv"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
429 key = encryption_data["key"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
430 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
431 # encrypted data size will be bigger than original file size |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
432 # so we need to check with final data length to avoid a warning on close() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
433 sat_file.check_size_with_read = True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
434 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
435 # file_producer get length directly from file, and this cause trouble as |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
436 # we have to change the size because of encryption. So we adapt it here, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
437 # else the producer would stop reading prematurely |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
438 file_producer.length = sat_file.size |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
439 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
440 encryptor = ciphers.Cipher( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
441 ciphers.algorithms.AES(key), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
442 modes.GCM(iv), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
443 backend=backends.default_backend(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
444 ).encryptor() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
445 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
446 if sat_file.data_cb is not None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
447 raise exceptions.InternalError( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
448 f"data_cb was expected to be None, it is set to {sat_file.data_cb}" |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
449 ) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
450 |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
451 attachment.update( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
452 { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
453 "hash_algo": self._h.ALGO_DEFAULT, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
454 "hasher": self._h.get_hasher(), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
455 "encrypted_hash_algo": self._h.ALGO_DEFAULT, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
456 "encrypted_hasher": self._h.get_hasher(), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
457 } |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
458 ) |
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
459 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
460 # with data_cb we encrypt the file on the fly |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
461 sat_file.data_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
462 self._encrypt, encryptor=encryptor, attachment=attachment |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
463 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
464 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
465 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
466 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
467 @implementer(iwokkel.IDisco) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
468 class XEP0448Handler(XMPPHandler): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
469 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
470 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
471 return [disco.DiscoFeature(NS_ESFS)] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
472 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
473 def getDiscoItems(self, requestor, target, nodeIdentifier=""): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
474 return [] |