annotate sat/plugins/plugin_xep_0420.py @ 3877:00212260f659

plugin XEP-0420: Implementation of Stanza Content Encryption: Includes implementation of XEP-0082 (XMPP date and time profiles) and tests for both new plugins. Everything is type checked, linted, format checked and unit tested. Adds new dependency xmlschema. fix 377
author Syndace <me@syndace.dev>
date Tue, 23 Aug 2022 12:04:11 +0200
parents
children 8289ac1b34f4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3877
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
1 #!/usr/bin/env python3
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
2
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
3 # Libervia plugin for Stanza Content Encryption
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
4 # Copyright (C) 2022-2022 Tim Henkes (me@syndace.dev)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
5
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
9 # (at your option) any later version.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
10
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
15
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
18
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
19 # Type-check with `mypy --strict --disable-error-code no-untyped-call`
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
20 # Lint with `pylint`
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
21
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
22 from abc import ABC, abstractmethod
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
23 from datetime import datetime
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
24 import enum
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
25 import secrets
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
26 import string
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
27 from typing import Dict, Iterator, List, NamedTuple, Optional, Set, Tuple, Union, cast
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
28
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
29 from lxml import etree
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
30
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
31 from sat.core.constants import Const as C
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
32 from sat.core.i18n import D_
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
33 from sat.core.log import Logger, getLogger
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
34 from sat.core.sat_main import SAT
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
35 from sat.tools.xml_tools import ElementParser
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
36 from sat.plugins.plugin_xep_0033 import NS_ADDRESS
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
37 from sat.plugins.plugin_xep_0082 import XEP_0082
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
38 from sat.plugins.plugin_xep_0334 import NS_HINTS
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
39 from sat.plugins.plugin_xep_0359 import NS_SID
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
40 from sat.plugins.plugin_xep_0380 import NS_EME
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
41 from twisted.words.protocols.jabber import jid
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
42 from twisted.words.xish import domish
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
43
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
44
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
45 __all__ = [ # pylint: disable=unused-variable
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
46 "PLUGIN_INFO",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
47 "NS_SCE",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
48 "XEP_0420",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
49 "ProfileRequirementsNotMet",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
50 "AffixVerificationFailed",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
51 "SCECustomAffix",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
52 "SCEAffixPolicy",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
53 "SCEProfile",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
54 "SCEAffixValues"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
55 ]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
56
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
57
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
58 log = cast(Logger, getLogger(__name__))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
59
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
60
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
61 PLUGIN_INFO = {
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
62 C.PI_NAME: "SCE",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
63 C.PI_IMPORT_NAME: "XEP-0420",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
64 C.PI_TYPE: "SEC",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
65 C.PI_PROTOCOLS: [ "XEP-0420" ],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
66 C.PI_DEPENDENCIES: [ "XEP-0334", "XEP-0082" ],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
67 C.PI_RECOMMENDATIONS: [ "XEP-0045", "XEP-0033", "XEP-0359" ],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
68 C.PI_MAIN: "XEP_0420",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
69 C.PI_HANDLER: "no",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
70 C.PI_DESCRIPTION: D_("Implementation of Stanza Content Encryption"),
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
71 }
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
72
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
73
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
74 NS_SCE = "urn:xmpp:sce:1"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
75
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
76
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
77 class ProfileRequirementsNotMet(Exception):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
78 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
79 Raised by :meth:`XEP_0420.unpack_stanza` in case the requirements formulated by the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
80 profile are not met.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
81 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
82
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
83
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
84 class AffixVerificationFailed(Exception):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
85 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
86 Raised by :meth:`XEP_0420.unpack_stanza` in case of affix verification failure.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
87 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
88
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
89
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
90 class SCECustomAffix(ABC):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
91 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
92 Interface for custom affixes of SCE profiles.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
93 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
94
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
95 @property
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
96 @abstractmethod
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
97 def element_name(self) -> str:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
98 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
99 @return: The name of the affix's XML element.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
100 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
101
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
102 @property
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
103 @abstractmethod
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
104 def element_schema(self) -> str:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
105 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
106 @return: The XML schema definition of the affix element's XML structure, i.e. the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
107 ``<xs:element/>`` schema element. This element will be referenced using
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
108 ``<xs:element ref="{element_name}"/>``.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
109 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
110
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
111 @abstractmethod
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
112 def create(self, stanza: domish.Element) -> domish.Element:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
113 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
114 @param stanza: The stanza element which has been processed by
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
115 :meth:`XEP_0420.pack_stanza`, i.e. all encryptable children have been removed
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
116 and only the root ``<message/>`` or ``<iq/>`` and unencryptable children
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
117 remain. Do not modify.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
118 @return: An affix element to include in the envelope. The element must have the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
119 name :attr:`element_name` and must validate using :attr:`element_schema`.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
120 @raise ValueError: if the affix couldn't be built.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
121 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
122
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
123 @abstractmethod
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
124 def verify(self, stanza: domish.Element, element: domish.Element) -> None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
125 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
126 @param stanza: The stanza element before being processed by
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
127 :meth:`XEP_0420.unpack_stanza`, i.e. all encryptable children have been
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
128 removed and only the root ``<message/>`` or ``<iq/>`` and unencryptable
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
129 children remain. Do not modify.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
130 @param element: The affix element to verify.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
131 @raise AffixVerificationFailed: on verification failure.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
132 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
133
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
134
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
135 @enum.unique
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
136 class SCEAffixPolicy(enum.Enum):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
137 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
138 Policy for the presence of an affix in an SCE envelope.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
139 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
140
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
141 REQUIRED: str = "REQUIRED"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
142 OPTIONAL: str = "OPTIONAL"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
143 NOT_NEEDED: str = "NOT_NEEDED"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
144
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
145
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
146 class SCEProfile(NamedTuple):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
147 # pylint: disable=invalid-name
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
148 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
149 An SCE profile, i.e. the definition which affixes are required, optional or not needed
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
150 at all by an SCE-enabled encryption protocol.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
151 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
152
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
153 rpad_policy: SCEAffixPolicy
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
154 time_policy: SCEAffixPolicy
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
155 to_policy: SCEAffixPolicy
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
156 from_policy: SCEAffixPolicy
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
157 custom_policies: Dict[SCECustomAffix, SCEAffixPolicy]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
158
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
159
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
160 class SCEAffixValues(NamedTuple):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
161 # pylint: disable=invalid-name
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
162 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
163 Structure returned by :meth:`XEP_0420.unpack_stanza` with the parsed/processes values
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
164 of all affixes included in the envelope. For custom affixes, the whole affix element
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
165 is returned.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
166 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
167
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
168 rpad: Optional[str]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
169 timestamp: Optional[datetime]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
170 recipient: Optional[jid.JID]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
171 sender: Optional[jid.JID]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
172 custom: Dict[SCECustomAffix, domish.Element]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
173
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
174
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
175 ENVELOPE_SCHEMA = """<?xml version="1.0" encoding="utf8"?>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
176 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
177 targetNamespace="urn:xmpp:sce:1"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
178 xmlns="urn:xmpp:sce:1">
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
179
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
180 <xs:element name="envelope">
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
181 <xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
182 <xs:all>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
183 <xs:element ref="content"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
184 <xs:element ref="rpad" minOccurs="0"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
185 <xs:element ref="time" minOccurs="0"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
186 <xs:element ref="to" minOccurs="0"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
187 <xs:element ref="from" minOccurs="0"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
188 {custom_affix_references}
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
189 </xs:all>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
190 </xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
191 </xs:element>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
192
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
193 <xs:element name="content">
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
194 <xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
195 <xs:sequence>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
196 <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
197 </xs:sequence>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
198 </xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
199 </xs:element>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
200
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
201 <xs:element name="rpad" type="xs:string"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
202
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
203 <xs:element name="time">
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
204 <xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
205 <xs:attribute name="stamp" type="xs:dateTime"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
206 </xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
207 </xs:element>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
208
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
209 <xs:element name="to">
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
210 <xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
211 <xs:attribute name="jid" type="xs:string"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
212 </xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
213 </xs:element>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
214
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
215 <xs:element name="from">
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
216 <xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
217 <xs:attribute name="jid" type="xs:string"/>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
218 </xs:complexType>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
219 </xs:element>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
220
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
221 {custom_affix_definitions}
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
222 </xs:schema>
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
223 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
224
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
225
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
226 class XEP_0420: # pylint: disable=invalid-name
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
227 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
228 Implementation of XEP-0420: Stanza Content Encryption under namespace
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
229 ``urn:xmpp:sce:1``.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
230
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
231 This is a passive plugin, i.e. it doesn't hook into any triggers to process stanzas
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
232 actively, but offers API for other plugins to use.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
233 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
234
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
235 # Set of namespaces whose elements are never allowed to be transferred in an encrypted
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
236 # envelope.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
237 MUST_BE_PLAINTEXT_NAMESPACES: Set[str] = {
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
238 NS_HINTS,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
239 NS_SID, # TODO: Not sure whether this ban applies to both stanza-id and origin-id
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
240 NS_ADDRESS,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
241 # Not part of the specification (yet), but just doesn't make sense in an encrypted
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
242 # envelope:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
243 NS_EME
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
244 }
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
245
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
246 # Set of (namespace, element name) tuples that define elements which are never allowed
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
247 # to be transferred in an encrypted envelope. If all elements under a certain
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
248 # namespace are forbidden, the namespace can be added to
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
249 # :attr:`MUST_BE_PLAINTEXT_NAMESPACES` instead.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
250 # Note: only full namespaces are forbidden by the spec for now, the following is for
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
251 # potential future use.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
252 MUST_BE_PLAINTEXT_ELEMENTS: Set[Tuple[str, str]] = set()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
253
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
254 def __init__(self, sat: SAT) -> None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
255 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
256 @param sat: The SAT instance.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
257 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
258
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
259 @staticmethod
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
260 def pack_stanza(profile: SCEProfile, stanza: domish.Element) -> bytes:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
261 """Pack a stanza according to Stanza Content Encryption.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
262
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
263 Removes all elements from the stanza except for a few exceptions that explicitly
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
264 need to be transferred in plaintext, e.g. because they contain hints/instructions
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
265 for the server on how to process the stanza. Together with the affix elements as
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
266 requested by the profile, the removed elements are added to an envelope XML
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
267 structure that builds the plaintext to be encrypted by the SCE-enabled encryption
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
268 scheme. Optional affixes are always added to the structure, i.e. they are treated
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
269 by the packing code as if they were required.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
270
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
271 Once built, the envelope structure is serialized to a byte string and returned for
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
272 the encryption scheme to encrypt and add to the stanza.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
273
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
274 @param profile: The SCE profile, i.e. the definition of affixes to include in the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
275 envelope.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
276 @param stanza: The stanza to process. Will be modified by the call.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
277 @return: The serialized envelope structure that builds the plaintext for the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
278 encryption scheme to process.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
279 @raise ValueError: if the <to/> or <from/> affixes are requested but the stanza
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
280 doesn't have the "to"/"from" attribute set to extract the value from. Can also
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
281 be raised by custom affixes.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
282
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
283 @warning: It is up to the calling code to add a <store/> message processing hint
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
284 if applicable.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
285 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
286
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
287 # Prepare the envelope and content elements
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
288 envelope = domish.Element((NS_SCE, "envelope"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
289 content = envelope.addElement((NS_SCE, "content"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
290
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
291 # Note the serialized byte size of the content element before adding any children
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
292 empty_content_byte_size = len(content.toXml().encode("utf-8"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
293
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
294 # Just for type safety
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
295 stanza_children = cast(List[Union[domish.Element, str]], stanza.children)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
296 content_children = cast(List[Union[domish.Element, str]], content.children)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
297
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
298 # Move elements that are not explicitly forbidden from being encrypted from the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
299 # stanza to the content element.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
300 for child in list(cast(Iterator[domish.Element], stanza.elements())):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
301 if (
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
302 child.uri not in XEP_0420.MUST_BE_PLAINTEXT_NAMESPACES
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
303 and (child.uri, child.name) not in XEP_0420.MUST_BE_PLAINTEXT_ELEMENTS
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
304 ):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
305 # Remove the child from the stanza
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
306 stanza_children.remove(child)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
307
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
308 # A namespace of ``None`` can be used on domish elements to inherit the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
309 # namespace from the parent. When moving elements from the stanza root to
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
310 # the content element, however, we don't want elements to inherit the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
311 # namespace of the content element. Thus, check for elements with ``None``
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
312 # for their namespace and set the namespace to jabber:client, which is the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
313 # namespace of the parent element.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
314 if child.uri is None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
315 child.uri = C.NS_CLIENT
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
316 child.defaultUri = C.NS_CLIENT
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
317
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
318 # Add the child with corrected namespaces to the content element
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
319 content_children.append(child)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
320
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
321 # Add the affixes requested by the profile
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
322 if profile.rpad_policy is not SCEAffixPolicy.NOT_NEEDED:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
323 # The specification defines the rpad affix to contain "[...] a randomly
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
324 # generated sequence of random length between 0 and 200 characters." This
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
325 # implementation differs a bit from the specification in that a minimum size
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
326 # other than 0 is chosen depending on the serialized size of the content
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
327 # element. This is to prevent the scenario where the encrypted content is
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
328 # short and the rpad is also randomly chosen to be short, which could allow
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
329 # guessing the content of a short message. To do so, the rpad length is first
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
330 # chosen to pad the content to at least 53 bytes, then afterwards another 0 to
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
331 # 200 bytes are added. Note that single-byte characters are used by this
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
332 # implementation, thus the number of characters equals the number of bytes.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
333 content_byte_size = len(content.toXml().encode("utf-8"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
334 content_byte_size_diff = content_byte_size - empty_content_byte_size
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
335 rpad_length = max(0, 53 - content_byte_size_diff) + secrets.randbelow(201)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
336 rpad_content = "".join(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
337 secrets.choice(string.digits + string.ascii_letters + string.punctuation)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
338 for __
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
339 in range(rpad_length)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
340 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
341 envelope.addElement((NS_SCE, "rpad"), content=rpad_content)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
342
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
343 if profile.time_policy is not SCEAffixPolicy.NOT_NEEDED:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
344 time_element = envelope.addElement((NS_SCE, "time"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
345 time_element["stamp"] = XEP_0082.format_datetime()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
346
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
347 if profile.to_policy is not SCEAffixPolicy.NOT_NEEDED:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
348 recipient = cast(Optional[str], stanza.getAttribute("to", None))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
349 if recipient is None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
350 raise ValueError(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
351 "<to/> affix requested, but stanza doesn't have the 'to' attribute"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
352 " set."
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
353 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
354
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
355 to_element = envelope.addElement((NS_SCE, "to"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
356 to_element["jid"] = jid.JID(recipient).userhost()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
357
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
358 if profile.from_policy is not SCEAffixPolicy.NOT_NEEDED:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
359 sender = cast(Optional[str], stanza.getAttribute("from", None))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
360 if sender is None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
361 raise ValueError(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
362 "<from/> affix requested, but stanza doesn't have the 'from'"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
363 " attribute set."
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
364 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
365
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
366 from_element = envelope.addElement((NS_SCE, "from"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
367 from_element["jid"] = jid.JID(sender).userhost()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
368
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
369 for affix, policy in profile.custom_policies.items():
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
370 if policy is not SCEAffixPolicy.NOT_NEEDED:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
371 envelope.addChild(affix.create(stanza))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
372
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
373 return cast(str, envelope.toXml()).encode("utf-8")
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
374
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
375 @staticmethod
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
376 def unpack_stanza(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
377 profile: SCEProfile,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
378 stanza: domish.Element,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
379 envelope_serialized: bytes
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
380 ) -> SCEAffixValues:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
381 """Unpack a stanza packed according to Stanza Content Encryption.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
382
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
383 Parses the serialized envelope as XML, verifies included affixes and makes sure
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
384 the requirements of the profile are met, and restores the stanza by moving
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
385 decrypted elements from the envelope back to the stanza top level.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
386
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
387 @param profile: The SCE profile, i.e. the definition of affixes that have to/may
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
388 be included in the envelope.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
389 @param stanza: The stanza to process. Will be modified by the call.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
390 @param envelope_serialized: The serialized envelope, i.e. the plaintext produced
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
391 by the decryption scheme utilizing SCE.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
392 @return: The parsed and processed values of all affixes that were present on the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
393 envelope, notably including the timestamp.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
394 @raise ValueError: if the serialized envelope element is malformed.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
395 @raise ProfileRequirementsNotMet: if one or more affixes required by the profile
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
396 are missing from the envelope.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
397 @raise AffixVerificationFailed: if an affix included in the envelope fails to
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
398 validate. It doesn't matter whether the affix is required by the profile or
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
399 not, all affixes included in the envelope are validated and cause this
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
400 exception to be raised on failure.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
401
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
402 @warning: It is up to the calling code to verify the timestamp, if returned, since
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
403 the requirements on the timestamp may vary between SCE-enabled protocols.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
404 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
405
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
406 try:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
407 envelope_serialized_string = envelope_serialized.decode("utf-8")
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
408 except UnicodeError as e:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
409 raise ValueError("Serialized envelope can't bare parsed as utf-8.") from e
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
410
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
411 custom_affixes = set(profile.custom_policies.keys())
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
412
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
413 # Make sure the envelope adheres to the schema
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
414 parser = etree.XMLParser(schema=etree.XMLSchema(etree.XML(ENVELOPE_SCHEMA.format(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
415 custom_affix_references="".join(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
416 f'<xs:element ref="{custom_affix.element_name}" minOccurs="0"/>'
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
417 for custom_affix
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
418 in custom_affixes
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
419 ),
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
420 custom_affix_definitions="".join(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
421 custom_affix.element_schema
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
422 for custom_affix
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
423 in custom_affixes
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
424 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
425 ).encode("utf-8"))))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
426
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
427 try:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
428 etree.fromstring(envelope_serialized_string, parser)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
429 except etree.XMLSyntaxError as e:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
430 raise ValueError("Serialized envelope doesn't pass schema validation.") from e
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
431
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
432 # Prepare the envelope and content elements
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
433 envelope = cast(domish.Element, ElementParser()(envelope_serialized_string))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
434 content = cast(domish.Element, next(envelope.elements(NS_SCE, "content")))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
435
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
436 # Verify the affixes
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
437 rpad_element = cast(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
438 Optional[domish.Element],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
439 next(envelope.elements(NS_SCE, "rpad"), None)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
440 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
441 time_element = cast(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
442 Optional[domish.Element],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
443 next(envelope.elements(NS_SCE, "time"), None)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
444 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
445 to_element = cast(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
446 Optional[domish.Element],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
447 next(envelope.elements(NS_SCE, "to"), None)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
448 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
449 from_element = cast(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
450 Optional[domish.Element],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
451 next(envelope.elements(NS_SCE, "from"), None)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
452 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
453
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
454 # The rpad doesn't need verification.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
455 rpad_value = None if rpad_element is None else str(rpad_element)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
456
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
457 # The time affix isn't verified other than that the timestamp is parseable.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
458 try:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
459 timestamp_value = None if time_element is None else \
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
460 XEP_0082.parse_datetime(time_element["stamp"])
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
461 except ValueError as e:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
462 raise AffixVerificationFailed("Malformed time affix") from e
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
463
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
464 # The to affix is verified by comparing the to attribute of the stanza with the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
465 # JID referenced by the affix. Note that only bare JIDs are compared as per the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
466 # specification.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
467 recipient_value: Optional[jid.JID] = None
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
468 if to_element is not None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
469 recipient_value = jid.JID(to_element["jid"])
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
470
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
471 recipient_actual = cast(Optional[str], stanza.getAttribute("to", None))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
472 if recipient_actual is None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
473 raise AffixVerificationFailed(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
474 "'To' affix is included in the envelope, but the stanza is lacking a"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
475 " 'to' attribute to compare the value to."
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
476 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
477
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
478 recipient_actual_bare_jid = jid.JID(recipient_actual).userhost()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
479 recipient_target_bare_jid = recipient_value.userhost()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
480
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
481 if recipient_actual_bare_jid != recipient_target_bare_jid:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
482 raise AffixVerificationFailed(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
483 f"Mismatch between actual and target recipient bare JIDs:"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
484 f" {recipient_actual_bare_jid} vs {recipient_target_bare_jid}."
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
485 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
486
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
487 # The from affix is verified by comparing the from attribute of the stanza with
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
488 # the JID referenced by the affix. Note that only bare JIDs are compared as per
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
489 # the specification.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
490 sender_value: Optional[jid.JID] = None
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
491 if from_element is not None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
492 sender_value = jid.JID(from_element["jid"])
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
493
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
494 sender_actual = cast(Optional[str], stanza.getAttribute("from", None))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
495 if sender_actual is None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
496 raise AffixVerificationFailed(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
497 "'From' affix is included in the envelope, but the stanza is lacking"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
498 " a 'from' attribute to compare the value to."
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
499 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
500
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
501 sender_actual_bare_jid = jid.JID(sender_actual).userhost()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
502 sender_target_bare_jid = sender_value.userhost()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
503
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
504 if sender_actual_bare_jid != sender_target_bare_jid:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
505 raise AffixVerificationFailed(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
506 f"Mismatch between actual and target sender bare JIDs:"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
507 f" {sender_actual_bare_jid} vs {sender_target_bare_jid}."
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
508 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
509
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
510 # Find and verify custom affixes
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
511 custom_values: Dict[SCECustomAffix, domish.Element] = {}
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
512 for affix in custom_affixes:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
513 element_name = affix.element_name
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
514 element = cast(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
515 Optional[domish.Element],
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
516 next(envelope.elements(NS_SCE, element_name), None)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
517 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
518 if element is not None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
519 affix.verify(stanza, element)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
520 custom_values[affix] = element
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
521
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
522 # Check whether all affixes required by the profile are present
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
523 rpad_missing = \
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
524 profile.rpad_policy is SCEAffixPolicy.REQUIRED and rpad_element is None
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
525 time_missing = \
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
526 profile.time_policy is SCEAffixPolicy.REQUIRED and time_element is None
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
527 to_missing = \
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
528 profile.to_policy is SCEAffixPolicy.REQUIRED and to_element is None
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
529 from_missing = \
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
530 profile.from_policy is SCEAffixPolicy.REQUIRED and from_element is None
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
531 custom_missing = any(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
532 affix not in custom_values
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
533 for affix, policy
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
534 in profile.custom_policies.items()
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
535 if policy is SCEAffixPolicy.REQUIRED
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
536 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
537
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
538 if rpad_missing or time_missing or to_missing or from_missing or custom_missing:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
539 custom_missing_string = ""
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
540 for custom_affix in custom_affixes:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
541 value = "present" if custom_affix in custom_values else "missing"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
542 custom_missing_string += f", [custom]{custom_affix.element_name}={value}"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
543
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
544 raise ProfileRequirementsNotMet(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
545 f"SCE envelope is missing affixes required by the profile {profile}."
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
546 f" Affix presence:"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
547 f" rpad={'missing' if rpad_missing else 'present'}"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
548 f", time={'missing' if time_missing else 'present'}"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
549 f", to={'missing' if to_missing else 'present'}"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
550 f", from={'missing' if from_missing else 'present'}"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
551 + custom_missing_string
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
552 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
553
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
554 # Just for type safety
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
555 content_children = cast(List[Union[domish.Element, str]], content.children)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
556 stanza_children = cast(List[Union[domish.Element, str]], stanza.children)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
557
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
558 # Move elements that are not explicitly forbidden from being encrypted from the
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
559 # content element to the stanza.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
560 for child in list(cast(Iterator[domish.Element], content.elements())):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
561 if (
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
562 child.uri in XEP_0420.MUST_BE_PLAINTEXT_NAMESPACES
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
563 or (child.uri, child.name) in XEP_0420.MUST_BE_PLAINTEXT_ELEMENTS
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
564 ):
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
565 log.warning(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
566 f"An element that MUST be transferred in plaintext was found in an"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
567 f" SCE envelope: {child.toXml()}"
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
568 )
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
569 else:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
570 # Remove the child from the content element
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
571 content_children.remove(child)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
572
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
573 # Add the child to the stanza
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
574 stanza_children.append(child)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
575
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
576 return SCEAffixValues(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
577 rpad_value,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
578 timestamp_value,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
579 recipient_value,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
580 sender_value,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
581 custom_values
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
582 )