Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0373.py @ 3942:a92eef737703
plugin XEP-0373: download public keys if they are not found in local storage:
public keys were only obtained from PEP notifications, however this wasn't working if the
entity was not in our roster.
Now if no public key is retrieved from local storage, the public key node is requested,
and an error is raised if nothing is found. This allows the use of OX with entities which
are not in roster.
rel 380
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 15 Oct 2022 20:38:33 +0200 |
parents | cecf45416403 |
children | 1ab16449577b |
comparison
equal
deleted
inserted
replaced
3941:036188fff714 | 3942:a92eef737703 |
---|---|
97 NS_OX: Final = "urn:xmpp:openpgp:0" | 97 NS_OX: Final = "urn:xmpp:openpgp:0" |
98 | 98 |
99 | 99 |
100 PARAM_CATEGORY = "Security" | 100 PARAM_CATEGORY = "Security" |
101 PARAM_NAME = "ox_policy" | 101 PARAM_NAME = "ox_policy" |
102 STR_KEY_PUBLIC_KEYS_METADATA = "/public-keys-metadata/{}" | |
102 | 103 |
103 | 104 |
104 class VerificationError(Exception): | 105 class VerificationError(Exception): |
105 """ | 106 """ |
106 Raised by verifying methods of :class:`XEP_0373` on semantical verification errors. | 107 Raised by verifying methods of :class:`XEP_0373` on semantical verification errors. |
1094 new_public_keys_metadata = { PublicKeyMetadata( | 1095 new_public_keys_metadata = { PublicKeyMetadata( |
1095 fingerprint=cast(str, pubkey_metadata_elt["v4-fingerprint"]), | 1096 fingerprint=cast(str, pubkey_metadata_elt["v4-fingerprint"]), |
1096 timestamp=parse_datetime(cast(str, pubkey_metadata_elt["date"])) | 1097 timestamp=parse_datetime(cast(str, pubkey_metadata_elt["date"])) |
1097 ) for pubkey_metadata_elt in pubkey_metadata_elts } | 1098 ) for pubkey_metadata_elt in pubkey_metadata_elts } |
1098 | 1099 |
1099 storage_key = f"/public-keys-metadata/{sender.userhost()}" | 1100 storage_key = STR_KEY_PUBLIC_KEYS_METADATA.format(sender.userhost()) |
1100 | 1101 |
1101 local_public_keys_metadata = cast( | 1102 local_public_keys_metadata = cast( |
1102 Set[PublicKeyMetadata], | 1103 Set[PublicKeyMetadata], |
1103 await self.__storage[profile].get(storage_key, set()) | 1104 await self.__storage[profile].get(storage_key, set()) |
1104 ) | 1105 ) |
1183 | 1184 |
1184 secret_key = gpg_provider.create_key(f"xmpp:{client.jid.userhost()}") | 1185 secret_key = gpg_provider.create_key(f"xmpp:{client.jid.userhost()}") |
1185 | 1186 |
1186 await self.publish_public_key(client, secret_key.public_key) | 1187 await self.publish_public_key(client, secret_key.public_key) |
1187 | 1188 |
1188 storage_key = f"/public-keys-metadata/{client.jid.userhost()}" | 1189 storage_key = STR_KEY_PUBLIC_KEYS_METADATA.format(client.jid.userhost()) |
1189 | 1190 |
1190 public_keys_list = cast( | 1191 public_keys_list = cast( |
1191 Set[PublicKeyMetadata], | 1192 Set[PublicKeyMetadata], |
1192 await self.__storage[client.profile].get(storage_key, set()) | 1193 await self.__storage[client.profile].get(storage_key, set()) |
1193 ) | 1194 ) |
1487 raise XMPPInteractionFailed("Publishing the public key failed.") from e | 1488 raise XMPPInteractionFailed("Publishing the public key failed.") from e |
1488 | 1489 |
1489 async def import_all_public_keys( | 1490 async def import_all_public_keys( |
1490 self, | 1491 self, |
1491 client: SatXMPPClient, | 1492 client: SatXMPPClient, |
1492 jid: jid.JID | 1493 entity_jid: jid.JID |
1493 ) -> Set[GPGPublicKey]: | 1494 ) -> Set[GPGPublicKey]: |
1494 """Import all public keys of a JID that have not been imported before. | 1495 """Import all public keys of a JID that have not been imported before. |
1495 | 1496 |
1496 @param client: The client. | 1497 @param client: The client. |
1497 @param jid: The JID. Can be a bare JID. | 1498 @param jid: The JID. Can be a bare JID. |
1498 @return: The public keys. | 1499 @return: The public keys. |
1499 @note: Failure to import a key simply results in the key not being included in the | 1500 @note: Failure to import a key simply results in the key not being included in the |
1500 result. | 1501 result. |
1501 """ | 1502 """ |
1502 | 1503 |
1503 available_public_keys = self.list_public_keys(client, jid) | 1504 available_public_keys = self.list_public_keys(client, entity_jid) |
1504 | 1505 |
1505 storage_key = f"/public-keys-metadata/{jid.userhost()}" | 1506 storage_key = STR_KEY_PUBLIC_KEYS_METADATA.format(entity_jid.userhost()) |
1506 | 1507 |
1507 public_keys_metadata = cast( | 1508 public_keys_metadata = cast( |
1508 Set[PublicKeyMetadata], | 1509 Set[PublicKeyMetadata], |
1509 await self.__storage[client.profile].get(storage_key, set()) | 1510 await self.__storage[client.profile].get(storage_key, set()) |
1510 ) | 1511 ) |
1512 if not public_keys_metadata: | |
1513 public_keys_metadata = await self.download_public_keys_list( | |
1514 client, entity_jid | |
1515 ) | |
1516 if not public_keys_metadata: | |
1517 raise exceptions.NotFound( | |
1518 f"Can't find public keys for {entity_jid}" | |
1519 ) | |
1520 else: | |
1521 await self.__storage[client.profile].aset( | |
1522 storage_key, public_keys_metadata | |
1523 ) | |
1524 | |
1511 | 1525 |
1512 missing_keys = set(filter(lambda public_key_metadata: all( | 1526 missing_keys = set(filter(lambda public_key_metadata: all( |
1513 public_key_metadata.fingerprint != public_key.fingerprint | 1527 public_key_metadata.fingerprint != public_key.fingerprint |
1514 for public_key | 1528 for public_key |
1515 in available_public_keys | 1529 in available_public_keys |
1516 ), public_keys_metadata)) | 1530 ), public_keys_metadata)) |
1517 | 1531 |
1518 for missing_key in missing_keys: | 1532 for missing_key in missing_keys: |
1519 try: | 1533 try: |
1520 available_public_keys.add( | 1534 available_public_keys.add( |
1521 await self.import_public_key(client, jid, missing_key.fingerprint) | 1535 await self.import_public_key(client, entity_jid, missing_key.fingerprint) |
1522 ) | 1536 ) |
1523 except Exception as e: | 1537 except Exception as e: |
1524 log.warning( | 1538 log.warning( |
1525 f"Import of public key {missing_key.fingerprint} owned by" | 1539 f"Import of public key {missing_key.fingerprint} owned by" |
1526 f" {jid.userhost()} failed, ignoring: {e}" | 1540 f" {entity_jid.userhost()} failed, ignoring: {e}" |
1527 ) | 1541 ) |
1528 | 1542 |
1529 return available_public_keys | 1543 return available_public_keys |
1530 | 1544 |
1531 async def import_public_key( | 1545 async def import_public_key( |