Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0420.py @ 3933:cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
GPGME is used as the GPG provider.
rel 374
author | Syndace <me@syndace.dev> |
---|---|
date | Tue, 20 Sep 2022 16:22:18 +0200 |
parents | 626629781a53 |
children |
comparison
equal
deleted
inserted
replaced
3932:7af29260ecb8 | 3933:cecf45416403 |
---|---|
20 from datetime import datetime | 20 from datetime import datetime |
21 import enum | 21 import enum |
22 import secrets | 22 import secrets |
23 import string | 23 import string |
24 from typing import Dict, NamedTuple, Optional, Set, Tuple, cast | 24 from typing import Dict, NamedTuple, Optional, Set, Tuple, cast |
25 from typing_extensions import Final | |
25 | 26 |
26 from lxml import etree | 27 from lxml import etree |
28 from sat.core import exceptions | |
27 | 29 |
28 from sat.core.constants import Const as C | 30 from sat.core.constants import Const as C |
29 from sat.core.i18n import D_ | 31 from sat.core.i18n import D_ |
30 from sat.core.log import Logger, getLogger | 32 from sat.core.log import Logger, getLogger |
31 from sat.core.sat_main import SAT | 33 from sat.core.sat_main import SAT |
66 C.PI_HANDLER: "no", | 68 C.PI_HANDLER: "no", |
67 C.PI_DESCRIPTION: D_("Implementation of Stanza Content Encryption"), | 69 C.PI_DESCRIPTION: D_("Implementation of Stanza Content Encryption"), |
68 } | 70 } |
69 | 71 |
70 | 72 |
71 NS_SCE = "urn:xmpp:sce:1" | 73 NS_SCE: Final = "urn:xmpp:sce:1" |
72 | 74 |
73 | 75 |
74 class ProfileRequirementsNotMet(Exception): | 76 class ProfileRequirementsNotMet(Exception): |
75 """ | 77 """ |
76 Raised by :meth:`XEP_0420.unpack_stanza` in case the requirements formulated by the | 78 Raised by :meth:`XEP_0420.unpack_stanza` in case the requirements formulated by the |
112 :meth:`XEP_0420.pack_stanza`, i.e. all encryptable children have been removed | 114 :meth:`XEP_0420.pack_stanza`, i.e. all encryptable children have been removed |
113 and only the root ``<message/>`` or ``<iq/>`` and unencryptable children | 115 and only the root ``<message/>`` or ``<iq/>`` and unencryptable children |
114 remain. Do not modify. | 116 remain. Do not modify. |
115 @return: An affix element to include in the envelope. The element must have the | 117 @return: An affix element to include in the envelope. The element must have the |
116 name :attr:`element_name` and must validate using :attr:`element_schema`. | 118 name :attr:`element_name` and must validate using :attr:`element_schema`. |
117 @raise ValueError: if the affix couldn't be built. | 119 @raise ValueError: if the affix couldn't be built due to missing information on |
120 the stanza. | |
118 """ | 121 """ |
119 | 122 |
120 @abstractmethod | 123 @abstractmethod |
121 def verify(self, stanza: domish.Element, element: domish.Element) -> None: | 124 def verify(self, stanza: domish.Element, element: domish.Element) -> None: |
122 """ | 125 """ |
382 @param stanza: The stanza to process. Will be modified by the call. | 385 @param stanza: The stanza to process. Will be modified by the call. |
383 @param envelope_serialized: The serialized envelope, i.e. the plaintext produced | 386 @param envelope_serialized: The serialized envelope, i.e. the plaintext produced |
384 by the decryption scheme utilizing SCE. | 387 by the decryption scheme utilizing SCE. |
385 @return: The parsed and processed values of all affixes that were present on the | 388 @return: The parsed and processed values of all affixes that were present on the |
386 envelope, notably including the timestamp. | 389 envelope, notably including the timestamp. |
387 @raise ValueError: if the serialized envelope element is malformed. | 390 @raise exceptions.ParsingError: if the serialized envelope element is malformed. |
388 @raise ProfileRequirementsNotMet: if one or more affixes required by the profile | 391 @raise ProfileRequirementsNotMet: if one or more affixes required by the profile |
389 are missing from the envelope. | 392 are missing from the envelope. |
390 @raise AffixVerificationFailed: if an affix included in the envelope fails to | 393 @raise AffixVerificationFailed: if an affix included in the envelope fails to |
391 validate. It doesn't matter whether the affix is required by the profile or | 394 validate. It doesn't matter whether the affix is required by the profile or |
392 not, all affixes included in the envelope are validated and cause this | 395 not, all affixes included in the envelope are validated and cause this |
397 """ | 400 """ |
398 | 401 |
399 try: | 402 try: |
400 envelope_serialized_string = envelope_serialized.decode("utf-8") | 403 envelope_serialized_string = envelope_serialized.decode("utf-8") |
401 except UnicodeError as e: | 404 except UnicodeError as e: |
402 raise ValueError("Serialized envelope can't bare parsed as utf-8.") from e | 405 raise exceptions.ParsingError( |
406 "Serialized envelope can't bare parsed as utf-8." | |
407 ) from e | |
403 | 408 |
404 custom_affixes = set(profile.custom_policies.keys()) | 409 custom_affixes = set(profile.custom_policies.keys()) |
405 | 410 |
406 # Make sure the envelope adheres to the schema | 411 # Make sure the envelope adheres to the schema |
407 parser = etree.XMLParser(schema=etree.XMLSchema(etree.XML(ENVELOPE_SCHEMA.format( | 412 parser = etree.XMLParser(schema=etree.XMLSchema(etree.XML(ENVELOPE_SCHEMA.format( |
418 ).encode("utf-8")))) | 423 ).encode("utf-8")))) |
419 | 424 |
420 try: | 425 try: |
421 etree.fromstring(envelope_serialized_string, parser) | 426 etree.fromstring(envelope_serialized_string, parser) |
422 except etree.XMLSyntaxError as e: | 427 except etree.XMLSyntaxError as e: |
423 raise ValueError("Serialized envelope doesn't pass schema validation.") from e | 428 raise exceptions.ParsingError( |
429 "Serialized envelope doesn't pass schema validation." | |
430 ) from e | |
424 | 431 |
425 # Prepare the envelope and content elements | 432 # Prepare the envelope and content elements |
426 envelope = cast(domish.Element, ElementParser()(envelope_serialized_string)) | 433 envelope = cast(domish.Element, ElementParser()(envelope_serialized_string)) |
427 content = next(envelope.elements(NS_SCE, "content")) | 434 content = next(envelope.elements(NS_SCE, "content")) |
428 | 435 |
450 # The time affix isn't verified other than that the timestamp is parseable. | 457 # The time affix isn't verified other than that the timestamp is parseable. |
451 try: | 458 try: |
452 timestamp_value = None if time_element is None else \ | 459 timestamp_value = None if time_element is None else \ |
453 XEP_0082.parse_datetime(time_element["stamp"]) | 460 XEP_0082.parse_datetime(time_element["stamp"]) |
454 except ValueError as e: | 461 except ValueError as e: |
455 raise AffixVerificationFailed("Malformed time affix") from e | 462 raise AffixVerificationFailed("Malformed time affix.") from e |
456 | 463 |
457 # The to affix is verified by comparing the to attribute of the stanza with the | 464 # The to affix is verified by comparing the to attribute of the stanza with the |
458 # JID referenced by the affix. Note that only bare JIDs are compared as per the | 465 # JID referenced by the affix. Note that only bare JIDs are compared as per the |
459 # specification. | 466 # specification. |
460 recipient_value: Optional[jid.JID] = None | 467 recipient_value: Optional[jid.JID] = None |