annotate libervia/backend/plugins/plugin_xep_0448.py @ 4351:6a0a081485b8

plugin autocrypt: Autocrypt protocol implementation: Implementation of autocrypt: `autocrypt` header is checked, and if present and no public key is known for the peer, the key is imported. `autocrypt` header is also added to outgoing message (only if an email gateway is detected). For the moment, the JID is use as identifier, but the real email used by gateway should be used in the future. rel 456
author Goffi <goffi@goffi.org>
date Fri, 28 Feb 2025 09:23:35 +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 []