annotate libervia/backend/plugins/plugin_xep_0448.py @ 4340:ea72364131d5 default tip @

doc (components): Update Email Gateway documentation: A section has been added to explain how attachments are handled. fix 453
author Goffi <goffi@goffi.org>
date Tue, 03 Dec 2024 00:53:18 +0100
parents 111dce64dcb5
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
24 from typing import Any, Dict, Optional, Self, Tuple, Union, cast
3927
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
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
31 from pydantic import BaseModel, ValidationError
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 import treq
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from twisted.internet import defer
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 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
35 from twisted.words.xish import domish
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 from wokkel import disco, iwokkel
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 from zope.interface import implementer
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
38
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
39 from libervia.backend.core import exceptions
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
40 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
41 from libervia.backend.core.core_types import SatXMPPEntity
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
42 from libervia.backend.core.i18n import _
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
43 from libervia.backend.core.log import getLogger
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
44 from libervia.backend.plugins.plugin_misc_download import DownloadPlugin
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
45 from libervia.backend.plugins.plugin_xep_0103 import XEP_0103
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
46 from libervia.backend.plugins.plugin_xep_0300 import NS_HASHES, XEP_0300, Hash
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
47 from libervia.backend.plugins.plugin_xep_0447 import XEP_0447, Source
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
48 from libervia.backend.tools import stream
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
49 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
50
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 log = getLogger(__name__)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
52
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
53 IMPORT_NAME = "XEP-0448"
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
54
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 PLUGIN_INFO = {
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 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
57 C.PI_IMPORT_NAME: IMPORT_NAME,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 C.PI_TYPE: C.PLUG_TYPE_EXP,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 C.PI_PROTOCOLS: ["XEP-0448"],
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 C.PI_DEPENDENCIES: [
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
61 "XEP-0103",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
62 "XEP-0300",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
63 "XEP-0334",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
64 "XEP-0363",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
65 "XEP-0384",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
66 "XEP-0447",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
67 "DOWNLOAD",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
68 "ATTACH",
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 ],
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 C.PI_MAIN: "XEP_0448",
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
71 C.PI_HANDLER: "yes",
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
72 C.PI_DESCRIPTION: dedent(
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
73 _(
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
74 """\
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 Implementation of e2e encryption for media sharing
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
76 """
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
77 )
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
78 ),
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 }
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 NS_ESFS = "urn:xmpp:esfs:0"
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 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
83 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
84 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
85
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
86
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
87 class EncryptedSource(Source):
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
88 type = "encrypted"
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
89 encrypted = True
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
90 cipher: str
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
91 key: str
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
92 iv: str
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
93 hashes: list[Hash]
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
94 sources: list[Source]
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
95 _hash: XEP_0300 | None = None
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
96 _sfs: XEP_0447 | None = None
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
97
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
98 @classmethod
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
99 def from_element(cls, element: domish.Element) -> Self:
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
100 """Parse an <encrypted> element and return corresponding EncryptedData model
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
101
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
102 @param encrypted_elt: element to parse
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
103 @raise exceptions.DataError: the element is invalid
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
104
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
105 """
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
106 assert cls._hash is not None, "_hash attribute is not set"
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
107 assert cls._sfs is not None, "_sfs attribute is not set"
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
108 try:
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
109 cipher = element["cipher"]
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
110 key = str(next(element.elements(NS_ESFS, "key")))
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
111 iv = str(next(element.elements(NS_ESFS, "iv")))
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
112 except (KeyError, StopIteration):
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
113 raise exceptions.DataError(
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
114 "invalid <encrypted/> element: {encrypted_elt.toXml()}"
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
115 )
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
116 sources = cls._sfs.parse_sources_elt(element)
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
117 if not sources:
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
118 raise exceptions.DataError(f"Sources are missing in {element.toXml()}")
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
119
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
120 if any(isinstance(source, cls) for source in sources):
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
121 raise exceptions.DataError(
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
122 f"EncryptedData is used as a source of another EncryptedData"
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
123 )
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
124
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
125 encrypted_data = {
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
126 "cipher": cipher,
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
127 "key": key,
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
128 "iv": iv,
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
129 "hashes": Hash.from_parent(element),
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
130 "sources": sources,
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
131 }
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
132
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
133 return cls(**encrypted_data)
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
134
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
135 def to_element(self) -> domish.Element:
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
136 """Convert EncryptedData model to an <encrypted> element
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
137
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
138 @return: domish.Element representing the encrypted data
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
139
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
140 """
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
141 assert self._hash is not None, "_hash attribute is not set"
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
142 encrypted_elt = domish.Element((NS_ESFS, "encrypted"))
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
143 encrypted_elt["cipher"] = self.cipher
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
144 encrypted_elt.addElement("key").addContent(self.key)
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
145 encrypted_elt.addElement("iv").addContent(self.iv)
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
146 for hash_ in self.hashes:
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
147 encrypted_elt.addChild(hash_.to_element())
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
148
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
149 return encrypted_elt
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
150
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
151
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 class XEP_0448:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
153
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 def __init__(self, host):
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 self.host = host
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 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
157 host.register_namespace("esfs", NS_ESFS)
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
158 self._u = cast(XEP_0103, host.plugins["XEP-0103"])
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
159 self._h = cast(XEP_0300, host.plugins["XEP-0300"])
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 self._hints = host.plugins["XEP-0334"]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 self._http_upload = host.plugins["XEP-0363"]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 self._o = host.plugins["XEP-0384"]
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
163 self._sfs = cast(XEP_0447, host.plugins["XEP-0447"])
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
164 self._sfs.register_source(NS_ESFS, "encrypted", EncryptedSource)
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 self._attach = host.plugins["ATTACH"]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 self._attach.register(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 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
168 )
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
169 EncryptedSource._hash = self._h
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
170 EncryptedSource._sfs = self._sfs
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
171 download = cast(DownloadPlugin, host.plugins["DOWNLOAD"])
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
172 download.register_download_handler(NS_ESFS, self.download)
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 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
174 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
175
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
176 def get_handler(self, client):
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 return XEP0448Handler()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
178
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 async def download(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 self,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 client: SatXMPPEntity,
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
182 attachment: dict[str, Any],
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
183 source: dict[str, Any],
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 dest_path: Union[Path, str],
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
185 extra: dict[str, Any] | None = None,
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
186 ) -> tuple[str, defer.Deferred]:
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 # TODO: check hash
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 if extra is None:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 extra = {}
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
190 assert source["type"] == "encrypted"
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 try:
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
192 cipher = source["cipher"]
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
193 iv = base64.b64decode(source["iv"])
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
194 key = base64.b64decode(source["key"])
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 except KeyError as e:
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
196 raise ValueError(f"{source} has incomplete encryption data: {e}") from e
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
197
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 try:
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
199 download_url = source["sources"][0]["url"]
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
200 except (IndexError, KeyError) as e:
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
201 raise ValueError(f"{source} has missing URL") from e
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
202
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
203 if extra.get("ignore_tls_errors", False):
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
204 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
205 treq_client = treq_client_no_ssl
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 treq_client = treq
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
208
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 try:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 file_size = int(attachment["size"])
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
211 except (KeyError, ValueError):
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 head_data = await treq_client.head(download_url)
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
213 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
214 # 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
215 file_size = content_length - 16
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 file_obj = stream.SatFile(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 self.host,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 client,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 dest_path,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 mode="wb",
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
222 size=file_size,
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
224
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 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
226 decryptor = ciphers.Cipher(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 ciphers.algorithms.AES(key),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
228 modes.GCM(iv),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 backend=backends.default_backend(),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 ).decryptor()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 decrypt_cb = partial(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 self.gcm_decrypt,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 client=client,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 file_obj=file_obj,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 decryptor=decryptor,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 finalize_cb = None
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 elif cipher == NS_AES_256_CBC:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 cipher_algo = ciphers.algorithms.AES(key)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 decryptor = ciphers.Cipher(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 cipher_algo,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 modes.CBC(iv),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 backend=backends.default_backend(),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 ).decryptor()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 unpadder = PKCS7(cipher_algo.block_size).unpadder()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 decrypt_cb = partial(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 self.cbc_decrypt,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 client=client,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 file_obj=file_obj,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 decryptor=decryptor,
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
251 unpadder=unpadder,
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 finalize_cb = partial(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 self.cbc_decrypt_finalize,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
255 file_obj=file_obj,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 decryptor=decryptor,
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
257 unpadder=unpadder,
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
259 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 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
261 file_obj.close(error=msg)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
262 log.warning(msg)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
263 raise exceptions.CancelError(msg)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
264
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 progress_id = file_obj.uid
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 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
268 if resp.code == 200:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 d = treq.collect(resp, partial(decrypt_cb))
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 if finalize_cb is not None:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 d.addCallback(lambda __: finalize_cb())
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 d = defer.Deferred()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 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
275 return progress_id, d
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
276
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
277 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
278 # 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
279 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
280 # 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
281 # 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
282 return False
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
283 try:
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
284 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
285 except exceptions.NotFound:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 return False
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
288 return True
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
289
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
290 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
291 attachment = extra["attachment"]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
292 extra["encryption"] = IMPORT_NAME
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 attachment["encryption_data"] = extra["encryption_data"] = {
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 "algorithm": C.ENC_AES_GCM,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
295 "iv": secrets.token_bytes(12),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
296 "key": secrets.token_bytes(32),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
297 }
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
298 attachment["filename"] = filename
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
299 return await self._http_upload.file_http_upload(
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
300 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
301 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
302
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
303 async def attach(self, client, data):
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
304 # 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
305 # 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
306 # plugin_sec_aesgcm.
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3934
diff changeset
307 attachments = data["extra"][C.KEY_ATTACHMENTS]
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
308 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
309 extra_attachments = attachments[1:]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
310 del attachments[1:]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
311 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
312 # 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
313 extra_attachments = attachments[:]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
314 attachments.clear()
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3934
diff changeset
315 del data["extra"][C.KEY_ATTACHMENTS]
3927
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 if attachments:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
318 if len(attachments) > 1:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
319 raise exceptions.InternalError(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
320 "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
321 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
322 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
323 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
324 for attachment in attachments:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
325 encryption_data = attachment.pop("encryption_data")
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
326 file_hash = (attachment["hash_algo"], attachment["hash"])
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
327 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
328 [],
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
329 name=attachment["filename"],
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
330 size=attachment["size"],
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
331 file_hash=file_hash,
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
332 )
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
333 sources_elt = file_sharing_elt.sources
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
334 assert sources_elt is not None
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
335 encrypted_elt = sources_elt.addElement((NS_ESFS, "encrypted"))
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
336 encrypted_elt["cipher"] = NS_AES_256_GCM
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
337 encrypted_elt.addElement(
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
338 "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
339 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 encrypted_elt.addElement(
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
341 "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
342 )
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
343 encrypted_elt.addChild(
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
344 self._h.build_hash_elt(
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
345 attachment["encrypted_hash"], attachment["encrypted_hash_algo"]
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
346 )
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
347 )
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
348 encrypted_elt.addChild(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
349 self._sfs.get_sources_elt(
4334
111dce64dcb5 plugins XEP-0300, XEP-0446, XEP-0447, XEP0448 and others: Refactoring to use Pydantic:
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
350 [self._u.generate_url_data(attachment["url"]).to_element()]
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
351 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
352 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
353 data["xml"].addChild(file_sharing_elt)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
354
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
355 for attachment in extra_attachments:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 # 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
357 await client.sendMessage(
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
358 to_jid=data["to"],
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
359 message={"": ""},
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
360 subject=data["subject"],
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
361 mess_type=data["type"],
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3934
diff changeset
362 extra={C.KEY_ATTACHMENTS: [attachment]},
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
363 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
364
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
365 if (
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
366 not data["extra"]
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
367 and (not data["message"] or data["message"] == {"": ""})
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
368 and not data["subject"]
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
369 ):
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
370 # 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
371 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
372
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
373 def gcm_decrypt(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
374 self,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
375 data: bytes,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
376 client: SatXMPPEntity,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 file_obj: stream.SatFile,
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
378 decryptor: CipherContext,
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
379 ) -> None:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
380 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
381 # 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
382 # 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
383 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
384 if bytes_left > 0:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
385 decrypted = decryptor.update(data[:bytes_left])
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
386 file_obj.write(decrypted)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
387 tag = data[bytes_left:]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
388 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
389 tag = data
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 if len(tag) < 16:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
391 # 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
392 # 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
393 try:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
394 # 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
395 tag = decryptor._sat_tag + tag
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
396 except AttributeError:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
397 # 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
398 decryptor.sat_tag = tag
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
399 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
400 # 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
401 if len(tag) != 16:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
402 raise ValueError(f"Invalid tag: {tag}")
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
403 remain = decryptor.finalize_with_tag(tag)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
404 file_obj.write(remain)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
405 file_obj.close()
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 decrypted = decryptor.update(data)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
408 file_obj.write(decrypted)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
409
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
410 def cbc_decrypt(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
411 self,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
412 data: bytes,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
413 client: SatXMPPEntity,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
414 file_obj: stream.SatFile,
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
415 decryptor: CipherContext,
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
416 unpadder: PaddingContext,
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
417 ) -> None:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
418 decrypted = decryptor.update(data)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
419 file_obj.write(unpadder.update(decrypted))
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
420
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
421 def cbc_decrypt_finalize(
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
422 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
423 ) -> None:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
424 decrypted = decryptor.finalize()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
425 file_obj.write(unpadder.update(decrypted))
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
426 file_obj.write(unpadder.finalize())
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
427 file_obj.close()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
428
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
429 def _upload_pre_slot(self, client, extra, file_metadata):
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
430 if extra.get("encryption") != IMPORT_NAME:
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
431 return True
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
432 # the tag is appended to the file
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
433 file_metadata["size"] += 16
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
434 return True
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
435
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
436 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
437 if data:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
438 attachment["hasher"].update(data)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
439 ret = encryptor.update(data)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
440 attachment["encrypted_hasher"].update(ret)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
441 return ret
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
442 else:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
443 try:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
444 # 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
445 fin = encryptor.finalize()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
446 tag = encryptor.tag
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
447 ret = fin + tag
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
448 hasher = attachment.pop("hasher")
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
449 attachment["hash"] = hasher.hexdigest()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
450 encrypted_hasher = attachment.pop("encrypted_hasher")
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
451 encrypted_hasher.update(ret)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
452 attachment["encrypted_hash"] = encrypted_hasher.hexdigest()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
453 return ret
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
454 except AlreadyFinalized:
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
455 # 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
456 return b""
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
457
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
458 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
459 if extra.get("encryption") != IMPORT_NAME:
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
460 return True
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
461 attachment = extra["attachment"]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
462 encryption_data = extra["encryption_data"]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
463 log.debug("encrypting file with AES-GCM")
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
464 iv = encryption_data["iv"]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
465 key = encryption_data["key"]
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 # 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
468 # 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
469 sat_file.check_size_with_read = True
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
470
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
471 # 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
472 # 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
473 # else the producer would stop reading prematurely
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
474 file_producer.length = sat_file.size
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
475
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
476 encryptor = ciphers.Cipher(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
477 ciphers.algorithms.AES(key),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
478 modes.GCM(iv),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
479 backend=backends.default_backend(),
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
480 ).encryptor()
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
481
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
482 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
483 raise exceptions.InternalError(
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
484 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
485 )
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
486
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
487 attachment.update(
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
488 {
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
489 "hash_algo": self._h.ALGO_DEFAULT,
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
490 "hasher": self._h.get_hasher(),
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
491 "encrypted_hash_algo": self._h.ALGO_DEFAULT,
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
492 "encrypted_hasher": self._h.get_hasher(),
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
493 }
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
494 )
3927
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
495
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
496 # 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
497 sat_file.data_cb = partial(
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
498 self._encrypt, encryptor=encryptor, attachment=attachment
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
499 )
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
500 return True
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
501
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
502
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
503 @implementer(iwokkel.IDisco)
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
504 class XEP0448Handler(XMPPHandler):
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
505
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
506 def getDiscoInfo(self, requestor, target, nodeIdentifier=""):
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
507 return [disco.DiscoFeature(NS_ESFS)]
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
508
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
509 def getDiscoItems(self, requestor, target, nodeIdentifier=""):
328869756cf4 plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
510 return []