Mercurial > libervia-backend
annotate sat/plugins/plugin_xep_0448.py @ 3934:e345d93fb6e5
plugin OXPS: OpenPGP for XMPP Pubsub implementation:
OpenPGP for XMPP Pubsub (https://xmpp.org/extensions/inbox/pubsub-encryption.html,
currently a protoXEP) is implemented and activated when `encrypted` is set to `True` in
pubsub's `extra` data.
On item retrieval, the decryption is transparent if the key is known, except if the
`decrypt` key in `extra` is set to `False` (notably useful when one wants to checks that
data is well encrypted).
Methods and corresponding bridge methods have been implemented to manage shared secrets
(to share, revoke or rotate the secrets).
plugin XEP-0060's `XEP-0060_publish` trigger point as been move before actual publish so
item can be modified (here e2ee) by the triggers. A new `XEP-0060_items` trigger point has
also been added.
`encrypted` flag can be used with plugin XEP-0277's microblog data
rel 380
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 15 Oct 2022 20:36:53 +0200 |
parents | 328869756cf4 |
children | 78b5f356900c |
rev | line source |
---|---|
3927
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
1 #!/usr/bin/env python3 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
2 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
3 # Libervia plugin for handling stateless file sharing encryption |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
4 # Copyright (C) 2009-2022 Jérôme Poisson (goffi@goffi.org) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
5 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
6 # This program is free software: you can redistribute it and/or modify |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
7 # it under the terms of the GNU Affero General Public License as published by |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
8 # the Free Software Foundation, either version 3 of the License, or |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
9 # (at your option) any later version. |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
10 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
11 # This program is distributed in the hope that it will be useful, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
14 # GNU Affero General Public License for more details. |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
15 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
16 # You should have received a copy of the GNU Affero General Public License |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
18 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
19 import base64 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
20 from functools import partial |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
21 from pathlib import Path |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
22 import secrets |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
23 from textwrap import dedent |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
24 from typing import Any, Dict, Optional, Tuple, Union |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
25 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
26 from cryptography.exceptions import AlreadyFinalized |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
27 from cryptography.hazmat import backends |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
28 from cryptography.hazmat.primitives import ciphers |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
29 from cryptography.hazmat.primitives.ciphers import CipherContext, modes |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
30 from cryptography.hazmat.primitives.padding import PKCS7, PaddingContext |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
31 import treq |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
32 from twisted.internet import defer |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
33 from twisted.words.protocols.jabber.xmlstream import XMPPHandler |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
34 from twisted.words.xish import domish |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
35 from wokkel import disco, iwokkel |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
36 from zope.interface import implementer |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
37 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
38 from sat.core import exceptions |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
39 from sat.core.constants import Const as C |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
40 from sat.core.core_types import SatXMPPEntity |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
41 from sat.core.i18n import _ |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
42 from sat.core.log import getLogger |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
43 from sat.tools import stream |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
44 from sat.tools.web import treq_client_no_ssl |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
45 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
46 log = getLogger(__name__) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
47 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
48 IMPORT_NAME = "XEP-0448" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
49 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
50 PLUGIN_INFO = { |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
51 C.PI_NAME: "Encryption for Stateless File Sharing", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
52 C.PI_IMPORT_NAME: IMPORT_NAME, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
53 C.PI_TYPE: C.PLUG_TYPE_EXP, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
54 C.PI_PROTOCOLS: ["XEP-0448"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
55 C.PI_DEPENDENCIES: [ |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
56 "XEP-0103", "XEP-0300", "XEP-0334", "XEP-0363", "XEP-0384", "XEP-0447", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
57 "DOWNLOAD", "ATTACH" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
58 ], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
59 C.PI_MAIN: "XEP_0448", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
60 C.PI_HANDLER: "yes", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
61 C.PI_DESCRIPTION: dedent(_("""\ |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
62 Implementation of e2e encryption for media sharing |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
63 """)), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
64 } |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
65 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
66 NS_ESFS = "urn:xmpp:esfs:0" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
67 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
|
68 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
|
69 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
|
70 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
71 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
72 class XEP_0448: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
73 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
74 def __init__(self, host): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
75 self.host = host |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
76 log.info(_("XEP_0448 plugin initialization")) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
77 host.registerNamespace("esfs", NS_ESFS) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
78 self._u = host.plugins["XEP-0103"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
79 self._h = host.plugins["XEP-0300"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
80 self._hints = host.plugins["XEP-0334"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
81 self._http_upload = host.plugins["XEP-0363"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
82 self._o = host.plugins["XEP-0384"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
83 self._sfs = host.plugins["XEP-0447"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
84 self._sfs.register_source_handler( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
85 NS_ESFS, "encrypted", self.parse_encrypted_elt, encrypted=True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
86 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
87 self._attach = host.plugins["ATTACH"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
88 self._attach.register( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
89 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
|
90 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
91 host.plugins["DOWNLOAD"].register_download_handler(NS_ESFS, self.download) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
92 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
|
93 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
|
94 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
95 def getHandler(self, client): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
96 return XEP0448Handler() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
97 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
98 def parse_encrypted_elt(self, encrypted_elt: domish.Element) -> Dict[str, Any]: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
99 """Parse an <encrypted> element and return corresponding source data |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
100 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
101 @param encrypted_elt: element to parse |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
102 @raise exceptions.DataError: the element is invalid |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
103 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
104 """ |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
105 sources = self._sfs.parse_sources_elt(encrypted_elt) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
106 if not sources: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
107 raise exceptions.NotFound("sources are missing in {encrypted_elt.toXml()}") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
108 if len(sources) > 1: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
109 log.debug( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
110 "more that one sources has been found, this is not expected, only the " |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
111 "first one will be used" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
112 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
113 source = sources[0] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
114 source["type"] = NS_ESFS |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
115 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
116 encrypted_data = source["encrypted_data"] = { |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
117 "cipher": encrypted_elt["cipher"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
118 "key": str(next(encrypted_elt.elements(NS_ESFS, "key"))), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
119 "iv": str(next(encrypted_elt.elements(NS_ESFS, "iv"))), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
120 } |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
121 except (KeyError, StopIteration): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
122 raise exceptions.DataError( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
123 "invalid <encrypted/> element: {encrypted_elt.toXml()}" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
124 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
125 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
126 hash_algo, hash_value = self._h.parseHashElt(encrypted_elt) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
127 except exceptions.NotFound: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
128 pass |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
129 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
130 encrypted_data["hash_algo"] = hash_algo |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
131 encrypted_data["hash"] = base64.b64encode(hash_value.encode()).decode() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
132 return source |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
133 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
134 async def download( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
135 self, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
136 client: SatXMPPEntity, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
137 attachment: Dict[str, Any], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
138 source: Dict[str, Any], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
139 dest_path: Union[Path, str], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
140 extra: Optional[Dict[str, Any]] = None |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
141 ) -> Tuple[str, defer.Deferred]: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
142 # TODO: check hash |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
143 if extra is None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
144 extra = {} |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
145 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
146 encrypted_data = source["encrypted_data"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
147 cipher = encrypted_data["cipher"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
148 iv = base64.b64decode(encrypted_data["iv"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
149 key = base64.b64decode(encrypted_data["key"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
150 except KeyError as e: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
151 raise ValueError(f"{source} has incomplete encryption data: {e}") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
152 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
153 download_url = source["url"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
154 except KeyError: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
155 raise ValueError(f"{source} has missing URL") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
156 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
157 if extra.get('ignore_tls_errors', False): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
158 log.warning( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
159 "TLS certificate check disabled, this is highly insecure" |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
160 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
161 treq_client = treq_client_no_ssl |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
162 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
163 treq_client = treq |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
164 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
165 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
166 file_size = int(attachment["size"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
167 except (KeyError, ValueError): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
168 head_data = await treq_client.head(download_url) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
169 content_length = int(head_data.headers.getRawHeaders('content-length')[0]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
170 # 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
|
171 file_size = content_length - 16 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
172 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
173 file_obj = stream.SatFile( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
174 self.host, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
175 client, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
176 dest_path, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
177 mode="wb", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
178 size = file_size, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
179 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
180 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
181 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
|
182 decryptor = ciphers.Cipher( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
183 ciphers.algorithms.AES(key), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
184 modes.GCM(iv), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
185 backend=backends.default_backend(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
186 ).decryptor() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
187 decrypt_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
188 self.gcm_decrypt, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
189 client=client, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
190 file_obj=file_obj, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
191 decryptor=decryptor, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
192 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
193 finalize_cb = None |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
194 elif cipher == NS_AES_256_CBC: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
195 cipher_algo = ciphers.algorithms.AES(key) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
196 decryptor = ciphers.Cipher( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
197 cipher_algo, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
198 modes.CBC(iv), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
199 backend=backends.default_backend(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
200 ).decryptor() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
201 unpadder = PKCS7(cipher_algo.block_size).unpadder() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
202 decrypt_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
203 self.cbc_decrypt, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
204 client=client, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
205 file_obj=file_obj, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
206 decryptor=decryptor, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
207 unpadder=unpadder |
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 finalize_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
210 self.cbc_decrypt_finalize, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
211 file_obj=file_obj, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
212 decryptor=decryptor, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
213 unpadder=unpadder |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
214 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
215 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
216 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
|
217 file_obj.close(error=msg) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
218 log.warning(msg) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
219 raise exceptions.CancelError(msg) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
220 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
221 progress_id = file_obj.uid |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
222 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
223 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
|
224 if resp.code == 200: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
225 d = treq.collect(resp, partial(decrypt_cb)) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
226 if finalize_cb is not None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
227 d.addCallback(lambda __: finalize_cb()) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
228 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
229 d = defer.Deferred() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
230 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
|
231 return progress_id, d |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
232 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
233 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
|
234 # 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
|
235 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
|
236 # 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
|
237 # 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
|
238 return False |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
239 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
240 await self._http_upload.getHTTPUploadEntity(client) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
241 except exceptions.NotFound: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
242 return False |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
243 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
244 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
245 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
246 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
|
247 attachment = extra["attachment"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
248 extra["encryption"] = IMPORT_NAME |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
249 attachment["encryption_data"] = extra["encryption_data"] = { |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
250 "algorithm": C.ENC_AES_GCM, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
251 "iv": secrets.token_bytes(12), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
252 "key": secrets.token_bytes(32), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
253 } |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
254 attachment["filename"] = filename |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
255 return await self._http_upload.file_http_upload( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
256 client=client, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
257 filepath=filepath, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
258 filename="encrypted", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
259 extra=extra |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
260 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
261 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
262 async def attach(self, client, data): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
263 # 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
|
264 # 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
|
265 # plugin_sec_aesgcm. |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
266 attachments = data["extra"][C.MESS_KEY_ATTACHMENTS] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
267 if not data['message'] or data['message'] == {'': ''}: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
268 extra_attachments = attachments[1:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
269 del attachments[1:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
270 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
271 # 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
|
272 extra_attachments = attachments[:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
273 attachments.clear() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
274 del data["extra"][C.MESS_KEY_ATTACHMENTS] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
275 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
276 if attachments: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
277 if len(attachments) > 1: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
278 raise exceptions.InternalError( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
279 "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
|
280 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
281 await self._attach.upload_files(client, data, upload_cb=self._upload_cb) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
282 self._hints.addHintElements(data["xml"], [self._hints.HINT_STORE]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
283 for attachment in attachments: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
284 encryption_data = attachment.pop("encryption_data") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
285 file_hash = (attachment["hash_algo"], attachment["hash"]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
286 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
|
287 [], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
288 name=attachment["filename"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
289 size=attachment["size"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
290 file_hash=file_hash |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
291 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
292 encrypted_elt = file_sharing_elt.sources.addElement( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
293 (NS_ESFS, "encrypted") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
294 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
295 encrypted_elt["cipher"] = NS_AES_256_GCM |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
296 encrypted_elt.addElement( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
297 "key", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
298 content=base64.b64encode(encryption_data["key"]).decode() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
299 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
300 encrypted_elt.addElement( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
301 "iv", |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
302 content=base64.b64encode(encryption_data["iv"]).decode() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
303 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
304 encrypted_elt.addChild(self._h.buildHashElt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
305 attachment["encrypted_hash"], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
306 attachment["encrypted_hash_algo"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
307 )) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
308 encrypted_elt.addChild( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
309 self._sfs.get_sources_elt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
310 [self._u.get_url_data_elt(attachment["url"])] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
311 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
312 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
313 data["xml"].addChild(file_sharing_elt) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
314 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
315 for attachment in extra_attachments: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
316 # 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
|
317 await client.sendMessage( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
318 to_jid=data['to'], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
319 message={'': ''}, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
320 subject=data['subject'], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
321 mess_type=data['type'], |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
322 extra={C.MESS_KEY_ATTACHMENTS: [attachment]}, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
323 ) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
324 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
325 if ((not data['extra'] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
326 and (not data['message'] or data['message'] == {'': ''}) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
327 and not data['subject'])): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
328 # 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
|
329 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
|
330 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
331 def gcm_decrypt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
332 self, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
333 data: bytes, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
334 client: SatXMPPEntity, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
335 file_obj: stream.SatFile, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
336 decryptor: CipherContext |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
337 ) -> None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
338 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
|
339 # 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
|
340 # 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
|
341 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
|
342 if bytes_left > 0: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
343 decrypted = decryptor.update(data[:bytes_left]) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
344 file_obj.write(decrypted) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
345 tag = data[bytes_left:] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
346 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
347 tag = data |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
348 if len(tag) < 16: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
349 # 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
|
350 # 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
|
351 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
352 # 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
|
353 tag = decryptor._sat_tag + tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
354 except AttributeError: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
355 # 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
|
356 decryptor.sat_tag = tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
357 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
358 # 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
|
359 if len(tag) != 16: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
360 raise ValueError(f"Invalid tag: {tag}") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
361 remain = decryptor.finalize_with_tag(tag) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
362 file_obj.write(remain) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
363 file_obj.close() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
364 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
365 decrypted = decryptor.update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
366 file_obj.write(decrypted) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
367 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
368 def cbc_decrypt( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
369 self, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
370 data: bytes, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
371 client: SatXMPPEntity, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
372 file_obj: stream.SatFile, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
373 decryptor: CipherContext, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
374 unpadder: PaddingContext |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
375 ) -> None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
376 decrypted = decryptor.update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
377 file_obj.write(unpadder.update(decrypted)) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
378 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
379 def cbc_decrypt_finalize( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
380 self, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
381 file_obj: stream.SatFile, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
382 decryptor: CipherContext, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
383 unpadder: PaddingContext |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
384 ) -> None: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
385 decrypted = decryptor.finalize() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
386 file_obj.write(unpadder.update(decrypted)) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
387 file_obj.write(unpadder.finalize()) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
388 file_obj.close() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
389 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
390 def _upload_pre_slot(self, client, extra, file_metadata): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
391 if extra.get('encryption') != IMPORT_NAME: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
392 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
393 # the tag is appended to the file |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
394 file_metadata["size"] += 16 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
395 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
396 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
397 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
|
398 if data: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
399 attachment["hasher"].update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
400 ret = encryptor.update(data) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
401 attachment["encrypted_hasher"].update(ret) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
402 return ret |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
403 else: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
404 try: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
405 # 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
|
406 fin = encryptor.finalize() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
407 tag = encryptor.tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
408 ret = fin + tag |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
409 hasher = attachment.pop("hasher") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
410 attachment["hash"] = hasher.hexdigest() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
411 encrypted_hasher = attachment.pop("encrypted_hasher") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
412 encrypted_hasher.update(ret) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
413 attachment["encrypted_hash"] = encrypted_hasher.hexdigest() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
414 return ret |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
415 except AlreadyFinalized: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
416 # as we have already finalized, we can now send EOF |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
417 return b'' |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
418 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
419 def _upload_trigger(self, client, extra, sat_file, file_producer, slot): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
420 if extra.get('encryption') != IMPORT_NAME: |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
421 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
422 attachment = extra["attachment"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
423 encryption_data = extra["encryption_data"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
424 log.debug("encrypting file with AES-GCM") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
425 iv = encryption_data["iv"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
426 key = encryption_data["key"] |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
427 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
428 # 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
|
429 # 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
|
430 sat_file.check_size_with_read = True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
431 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
432 # 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
|
433 # 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
|
434 # else the producer would stop reading prematurely |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
435 file_producer.length = sat_file.size |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
436 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
437 encryptor = ciphers.Cipher( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
438 ciphers.algorithms.AES(key), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
439 modes.GCM(iv), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
440 backend=backends.default_backend(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
441 ).encryptor() |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
442 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
443 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
|
444 raise exceptions.InternalError( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
445 f"data_cb was expected to be None, it is set to {sat_file.data_cb}") |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
446 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
447 attachment.update({ |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
448 "hash_algo": self._h.ALGO_DEFAULT, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
449 "hasher": self._h.getHasher(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
450 "encrypted_hash_algo": self._h.ALGO_DEFAULT, |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
451 "encrypted_hasher": self._h.getHasher(), |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
452 }) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
453 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
454 # 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
|
455 sat_file.data_cb = partial( |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
456 self._encrypt, encryptor=encryptor, attachment=attachment |
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 return True |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
459 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
460 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
461 @implementer(iwokkel.IDisco) |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
462 class XEP0448Handler(XMPPHandler): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
463 |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
464 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
465 return [disco.DiscoFeature(NS_ESFS)] |
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 def getDiscoItems(self, requestor, target, nodeIdentifier=""): |
328869756cf4
plugin XEP-0448: Encryption for stateless file sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
468 return [] |