From ed1b16a4e26108a6a6b67252a605a190c21e65e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 2 Apr 2019 15:10:58 +0200 Subject: [PATCH 01/14] [WIP]: SAS support. --- matrix/server.py | 85 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 15 deletions(-) diff --git a/matrix/server.py b/matrix/server.py index 7d22b8c..6b61ac8 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -66,7 +66,11 @@ from nio import ( LoginError, JoinedMembersResponse, JoinedMembersError, - RoomKeyEvent + RoomKeyEvent, + KeyVerificationStart, + KeyVerificationCancel, + KeyVerificationKey, + KeyVerificationMac ) from . import globals as G @@ -1206,6 +1210,28 @@ class MatrixServer(object): room_buffer.undecrypted_events.remove(undecrypted_event) room_buffer.replace_undecrypted_line(event) + def accept_key_verification(self, event): + _, request = self.client.accept_key_verification(event) + self.send_or_queue(request) + + def send_key_verification_key(self, sas): + _, request = self.client.to_device( + "m.key.verification.key", + sas.share_key(), + sas.other_user, + sas.other_device, + ) + self.send_or_queue(request) + + def send_key_verification_mac(self, sas): + _, request = self.client.to_device( + "m.key.verification.mac", + sas.get_mac(), + sas.other_user, + sas.other_device, + ) + self.send_or_queue(request) + def _handle_sync(self, response): # we got the same batch again, nothing to do if self.next_batch == response.next_batch: @@ -1215,22 +1241,51 @@ class MatrixServer(object): self._handle_room_info(response) for event in response.to_device_events: - if not isinstance(event, RoomKeyEvent): - continue + if isinstance(event, RoomKeyEvent): + message = { + "sender": event.sender, + "sender_key": event.sender_key, + "room_id": event.room_id, + "session_id": event.session_id, + "algorithm": event.algorithm, + "server": self.name, + } + W.hook_hsignal_send("matrix_room_key_received", message) - message = { - "sender": event.sender, - "sender_key": event.sender_key, - "room_id": event.room_id, - "session_id": event.session_id, - "algorithm": event.algorithm, - "server": self.name, - } - W.hook_hsignal_send("matrix_room_key_received", message) + # TODO try to decrypt some cached undecrypted messages with the + # new key + # self.decrypt_printed_messages(event) + elif isinstance(event, KeyVerificationStart): + self.accept_key_verification(event) + # print(event) + + elif isinstance(event, KeyVerificationCancel): + print(event) + + elif isinstance(event, KeyVerificationMac): + sas = self.client.active_key_verifications.get( + event.transaction_id, None + ) + + if sas: + self.send_key_verification_mac(sas) + else: + print("NO SAS??") + print(event) + + elif isinstance(event, KeyVerificationKey): + sas = self.client.active_key_verifications.get( + event.transaction_id, None + ) + + if sas: + emoji = sas.get_emoji() + self.info(" ".join(emoji)) + self.send_key_verification_key(sas) + else: + print("NO SAS??") + print(event) - # TODO try to decrypt some cached undecrypted messages with the - # new key - # self.decrypt_printed_messages(event) # Full sync response handle everything. if isinstance(response, SyncResponse): From c32a9e34e61f5c689913ae0b8446d91d012ded3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Sat, 27 Apr 2019 23:15:06 +0200 Subject: [PATCH 02/14] server: More SAS work. --- matrix/server.py | 128 +++++++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 50 deletions(-) diff --git a/matrix/server.py b/matrix/server.py index 6b61ac8..bd41d3e 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -70,7 +70,8 @@ from nio import ( KeyVerificationStart, KeyVerificationCancel, KeyVerificationKey, - KeyVerificationMac + KeyVerificationMac, + KeyVerificationEvent ) from . import globals as G @@ -368,6 +369,55 @@ class MatrixServer(object): self.get_session_path(), extra_path=extra_path ) + self.client.add_to_device_callback( + self.key_verification_cb, + KeyVerificationEvent + ) + + def key_verification_cb(self, event): + # TODO don't accept the verification automatically. + if isinstance(event, KeyVerificationStart): + self.info_highlight("{} via {} has started a key verification " + "process.".format( + event.sender, + event.from_device + )) + try: + self.accept_key_verification(event) + except LocalProtocolError as e: + self.info(e) + + elif isinstance(event, KeyVerificationKey): + sas = self.client.key_verifications.get(event.transaction_id, None) + if not sas: + return + + emoji = sas.get_emoji() + + emojies = [x[0] for x in emoji] + descriptions = [x[1] for x in emoji] + device = sas.other_olm_device + + emoji_str = u"{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}".format( + *emojies + ) + desc = u"{:^11}{:^11}{:^11}{:^11}{:^11}{:^11}{:^11}".format( + *descriptions + ) + short_string = u"\n".join([emoji_str, desc]) + + self.info_highlight(u"Short authentication string for {} via {}:\n" + u"{}".format( + device.user_id, + device.id, + short_string + )) + + elif isinstance(event, KeyVerificationMac): + try: + self.accept_short_auth_string(event.transaction_id) + except LocalProtocolError as e: + self.info(e) def update_option(self, option, option_name): if option_name == "address": @@ -472,6 +522,14 @@ class MatrixServer(object): # type: (MatrixServer) -> None self.send_buffer = b"" + def info_highlight(self, message): + buf = "" + if self.server_buffer: + buf = self.server_buffer + + msg = "{}{}: {}".format(W.prefix("network"), SCRIPT_NAME, message) + W.prnt_date_tags(buf, 0, "notify_highlight", msg) + def info(self, message): buf = "" if self.server_buffer: @@ -1211,26 +1269,16 @@ class MatrixServer(object): room_buffer.replace_undecrypted_line(event) def accept_key_verification(self, event): - _, request = self.client.accept_key_verification(event) - self.send_or_queue(request) + _, request = self.client.accept_key_verification(event.transaction_id) + self.send(request) - def send_key_verification_key(self, sas): - _, request = self.client.to_device( - "m.key.verification.key", - sas.share_key(), - sas.other_user, - sas.other_device, - ) - self.send_or_queue(request) + def to_device(self, message): + _, request = self.client.to_device(message) + self.send(request) - def send_key_verification_mac(self, sas): - _, request = self.client.to_device( - "m.key.verification.mac", - sas.get_mac(), - sas.other_user, - sas.other_device, - ) - self.send_or_queue(request) + def accept_short_auth_string(self, transaction_id): + _, request = self.client.accept_short_auth_string(transaction_id) + self.send(request) def _handle_sync(self, response): # we got the same batch again, nothing to do @@ -1255,37 +1303,6 @@ class MatrixServer(object): # TODO try to decrypt some cached undecrypted messages with the # new key # self.decrypt_printed_messages(event) - elif isinstance(event, KeyVerificationStart): - self.accept_key_verification(event) - # print(event) - - elif isinstance(event, KeyVerificationCancel): - print(event) - - elif isinstance(event, KeyVerificationMac): - sas = self.client.active_key_verifications.get( - event.transaction_id, None - ) - - if sas: - self.send_key_verification_mac(sas) - else: - print("NO SAS??") - print(event) - - elif isinstance(event, KeyVerificationKey): - sas = self.client.active_key_verifications.get( - event.transaction_id, None - ) - - if sas: - emoji = sas.get_emoji() - self.info(" ".join(emoji)) - self.send_key_verification_key(sas) - else: - print("NO SAS??") - print(event) - # Full sync response handle everything. if isinstance(response, SyncResponse): @@ -1701,6 +1718,17 @@ def matrix_timer_cb(server_name, remaining_calls): server.disconnect() return W.WEECHAT_RC_OK + sent_to_device = [] + + for i, message in enumerate(server.client.outgoing_to_device_messages): + if i >= 5: + break + server.to_device(message) + sent_to_device.append(message) + + for message in sent_to_device: + server.client.mark_to_device_message_as_sent(message) + if server.sync_time and current_time > server.sync_time: timeout = 0 if server.transport_type == TransportType.HTTP else 30000 sync_filter = { From 31c38bc01dfbe6c9d80a9b9585dd5c9176f9c973 Mon Sep 17 00:00:00 2001 From: Denis Kasak Date: Mon, 29 Apr 2019 12:47:28 +0200 Subject: [PATCH 03/14] sas: Center emojis above their description properly. --- matrix/server.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/matrix/server.py b/matrix/server.py index bd41d3e..7f4c676 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -394,14 +394,24 @@ class MatrixServer(object): emoji = sas.get_emoji() - emojies = [x[0] for x in emoji] + emojis = [x[0] for x in emoji] descriptions = [x[1] for x in emoji] device = sas.other_olm_device - emoji_str = u"{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}".format( - *emojies - ) - desc = u"{:^11}{:^11}{:^11}{:^11}{:^11}{:^11}{:^11}".format( + emoji_centered_width = 10 + + def center_emoji(emoji, width): + # Assume each emoji has width 2 + emoji_width = 2 + + # This is a trick to account for the fact that emojis are wider + # than other monospace characters. + placeholder = '.' * emoji_width + return placeholder.center(width).replace(placeholder, emoji) + + emoji_str = u"".join(center_emoji(e, emoji_centered_width) + for e in emojis) + desc = u"{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}".format( *descriptions ) short_string = u"\n".join([emoji_str, desc]) From 31d9052b88500b1e20920a55e59fe61518e4d3ba Mon Sep 17 00:00:00 2001 From: Denis Kasak Date: Mon, 29 Apr 2019 14:04:26 +0200 Subject: [PATCH 04/14] Fixup. --- matrix/server.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/matrix/server.py b/matrix/server.py index 7f4c676..9a63050 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -392,28 +392,46 @@ class MatrixServer(object): if not sas: return + device = sas.other_olm_device emoji = sas.get_emoji() emojis = [x[0] for x in emoji] descriptions = [x[1] for x in emoji] - device = sas.other_olm_device - emoji_centered_width = 10 + centered_width = 12 def center_emoji(emoji, width): # Assume each emoji has width 2 emoji_width = 2 + # These are emojis that need VARIATION-SELECTOR-16 (U+FE0F) so + # that they are rendered with coloured glyphs. For these, we + # need to add an extra space after them so that they are + # rendered properly in weechat. + variation_selector_emojis = [ + '☁️', + '❤️', + '☂️', + '✏️', + '✂️', + '☎️', + '✈️' + ] + + # Hack to make weechat behave properly when one of the above is + # printed. + if emoji in variation_selector_emojis: + emoji += " " + # This is a trick to account for the fact that emojis are wider # than other monospace characters. placeholder = '.' * emoji_width + return placeholder.center(width).replace(placeholder, emoji) - emoji_str = u"".join(center_emoji(e, emoji_centered_width) + emoji_str = u"".join(center_emoji(e, centered_width) for e in emojis) - desc = u"{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}{:^10}".format( - *descriptions - ) + desc = u"".join(d.center(centered_width) for d in descriptions) short_string = u"\n".join([emoji_str, desc]) self.info_highlight(u"Short authentication string for {} via {}:\n" From 38fa6d406393d9d154f1df0f8be7897ad15b5c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 30 Apr 2019 18:15:07 +0200 Subject: [PATCH 05/14] server: Change the way to-device messages are sent. --- matrix/server.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/matrix/server.py b/matrix/server.py index 9a63050..7d23bd5 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -71,7 +71,9 @@ from nio import ( KeyVerificationCancel, KeyVerificationKey, KeyVerificationMac, - KeyVerificationEvent + KeyVerificationEvent, + ToDeviceResponse, + ToDeviceError ) from . import globals as G @@ -298,6 +300,7 @@ class MatrixServer(object): self.keys_queried = False # type: bool self.keys_claimed = defaultdict(bool) # type: Dict[str, bool] self.group_session_shared = defaultdict(bool) # type: Dict[str, bool] + self.to_device_sent = [] self.config = ServerConfig(self.name, config_ptr) self._create_session_dir() @@ -651,6 +654,7 @@ class MatrixServer(object): self.keys_queried = False self.keys_claimed = defaultdict(bool) self.group_session_shared = defaultdict(bool) + self.to_device_sent = [] if self.server_buffer: message = ("{prefix}matrix: disconnected from server").format( @@ -1402,6 +1406,12 @@ class MatrixServer(object): self.group_session_shared[response.room_id] = False self.share_group_session(response.room_id) + elif isinstance(response, ToDeviceError): + try: + self.to_device_sent.remove(response.to_device_message) + except ValueError: + pass + def handle_response(self, response): # type: (Response) -> None response_lag = response.elapsed @@ -1419,6 +1429,12 @@ class MatrixServer(object): if isinstance(response, ErrorResponse): self.handle_error_response(response) + elif isinstance(response, ToDeviceResponse): + try: + self.to_device_sent.remove(response.to_device_message) + except ValueError: + pass + elif isinstance(response, LoginResponse): self._handle_login(response) @@ -1746,16 +1762,15 @@ def matrix_timer_cb(server_name, remaining_calls): server.disconnect() return W.WEECHAT_RC_OK - sent_to_device = [] - for i, message in enumerate(server.client.outgoing_to_device_messages): if i >= 5: break - server.to_device(message) - sent_to_device.append(message) - for message in sent_to_device: - server.client.mark_to_device_message_as_sent(message) + if message in server.to_device_sent: + continue + + server.to_device(message) + server.to_device_sent.append(message) if server.sync_time and current_time > server.sync_time: timeout = 0 if server.transport_type == TransportType.HTTP else 30000 From 9f01a0561722df6c56245fa481583b7597700b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Sun, 5 May 2019 23:23:14 +0200 Subject: [PATCH 06/14] commands: Add a command for interactive key verification. --- matrix/commands.py | 81 +++++++++++++++++++++++++++++++++++++++----- matrix/completion.py | 2 +- matrix/server.py | 71 ++++++++++++++++++++++++++------------ 3 files changed, 123 insertions(+), 31 deletions(-) diff --git a/matrix/commands.py b/matrix/commands.py index bc20198..b9ca16e 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -23,14 +23,14 @@ from builtins import str from future.moves.itertools import zip_longest from collections import defaultdict from functools import partial -from nio import EncryptionError +from nio import EncryptionError, LocalProtocolError from . import globals as G from .colors import Formatted from .globals import SERVERS, W, UPLOADS, SCRIPT_NAME from .server import MatrixServer from .utf import utf8_decode -from .utils import key_from_value, tags_from_line_data +from .utils import key_from_value from .uploads import UploadsBuffer, Upload @@ -152,6 +152,18 @@ class WeechatCommandParser(object): import_parser.add_argument("file") import_parser.add_argument("passphrase") + sas_parser = subparsers.add_parser("verification") + sas_parser.add_argument( + "action", + choices=[ + "start", + "accept", + "confirm", + "cancel", + ]) + sas_parser.add_argument("user_id") + sas_parser.add_argument("device_id") + return WeechatCommandParser._run_parser(parser, args) @staticmethod @@ -385,17 +397,19 @@ def hook_commands(): "blacklist ||" "unverify ||" "verify ||" + "verification start|accept|cancel|confirm ||" "export ||" "import " ), # Description - (" info: show info about known devices and their keys\n" - " blacklist: blacklist a device\n" - "unblacklist: unblacklist a device\n" - " unverify: unverify a device\n" - " verify: verify a device\n" - " export: export encryption keys\n" - " import: import encryption keys\n\n" + (" info: show info about known devices and their keys\n" + " blacklist: blacklist a device\n" + " unblacklist: unblacklist a device\n" + " unverify: unverify a device\n" + " verify: verify a device\n" + "verification: manage interactive device verification\n" + " export: export encryption keys\n" + " import: import encryption keys\n\n" "Examples:" "\n /olm verify @example:example.com *" "\n /olm info all example*" @@ -406,6 +420,7 @@ def hook_commands(): 'unblacklist %(olm_user_ids) %(olm_devices) ||' 'unverify %(olm_user_ids) %(olm_devices) ||' 'verify %(olm_user_ids) %(olm_devices) ||' + 'verification start|accept|cancel|confirm %(olm_user_ids) %(olm_devices) ||' 'export %(filename) ||' 'import %(filename)' ), @@ -710,6 +725,52 @@ def olm_import_command(server, args): server.info("Succesfully imported keys") +def olm_sas_command(server, args): + try: + device_store = server.client.device_store + except LocalProtocolError: + server.error("The device store is not loaded") + return W.WEECHAT_RC_OK + + try: + device = device_store[args.user_id][args.device_id] + except KeyError: + server.error("Device {} of user {} not found".format( + args.user_id, + args.device_id + )) + return W.WEECHAT_RC_OK + + if device.deleted: + server.error("Device {} of user {} is deleted.".format( + args.user_id, + args.device_id + )) + return W.WEECHAT_RC_OK + + if args.action == "start": + server.start_verification(device) + elif args.action in ["accept", "confirm", "cancel"]: + sas = server.client.get_active_sas(args.user_id, args.device_id) + + if not sas: + server.error("No active key verification found for " + "device {} of user {}.".format( + args.user_id, + args.device_id + )) + return W.WEECHAT_RC_OK + + try: + if args.action == "accept": + server.accept_sas(sas) + elif args.action == "confirm": + server.confirm_sas(sas) + + except LocalProtocolError as e: + server.error(str(e)) + + @utf8_decode def matrix_olm_command_cb(data, buffer, args): def command(server, data, buffer, args): @@ -736,6 +797,8 @@ def matrix_olm_command_cb(data, buffer, args): olm_blacklist_command(server, parsed_args) elif parsed_args.subcommand == "unblacklist": olm_unblacklist_command(server, parsed_args) + elif parsed_args.subcommand == "verification": + olm_sas_command(server, parsed_args) else: message = ("{prefix}matrix: Command not implemented.".format( prefix=W.prefix("error"))) diff --git a/matrix/completion.py b/matrix/completion.py index 1a08b05..578309e 100644 --- a/matrix/completion.py +++ b/matrix/completion.py @@ -207,7 +207,7 @@ def matrix_olm_device_completion_cb(data, completion_item, buffer, completion): if len(fields) < 2: return W.WEECHAT_RC_OK - user = fields[1] + user = fields[-1] if user not in device_store.users: return W.WEECHAT_RC_OK diff --git a/matrix/server.py b/matrix/server.py index 7d23bd5..a4e5145 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -378,17 +378,14 @@ class MatrixServer(object): ) def key_verification_cb(self, event): - # TODO don't accept the verification automatically. if isinstance(event, KeyVerificationStart): - self.info_highlight("{} via {} has started a key verification " - "process.".format( - event.sender, - event.from_device + self.info_highlight("{user} via {device} has started a key " + "verification process.\n" + "To accept use /olm verification " + "accept {user} {device}".format( + user=event.sender, + device=event.from_device )) - try: - self.accept_key_verification(event) - except LocalProtocolError as e: - self.info(e) elif isinstance(event, KeyVerificationKey): sas = self.client.key_verifications.get(event.transaction_id, None) @@ -437,18 +434,30 @@ class MatrixServer(object): desc = u"".join(d.center(centered_width) for d in descriptions) short_string = u"\n".join([emoji_str, desc]) - self.info_highlight(u"Short authentication string for {} via {}:\n" - u"{}".format( - device.user_id, - device.id, - short_string + self.info_highlight(u"Short authentication string for " + u"{user} via {device}:\n{string}\n" + u"Confirm that the strings match with " + u"/olm verification confirm {user} " + u"{device}".format( + user=device.user_id, + device=device.id, + string=short_string )) elif isinstance(event, KeyVerificationMac): try: - self.accept_short_auth_string(event.transaction_id) - except LocalProtocolError as e: - self.info(e) + sas = self.client.key_verifications[event.transaction_id] + except KeyError: + return + + device = sas.other_olm_device + + if sas.verified: + self.info_highlight("Device {} of user {} succesfully " + "verified".format( + device.id, + device.user_id + )) def update_option(self, option, option_name): if option_name == "address": @@ -1300,18 +1309,38 @@ class MatrixServer(object): room_buffer.undecrypted_events.remove(undecrypted_event) room_buffer.replace_undecrypted_line(event) - def accept_key_verification(self, event): - _, request = self.client.accept_key_verification(event.transaction_id) + def start_verification(self, device): + _, request = self.client.start_key_verification(device) + self.send(request) + self.info("Starting an interactive device verification with " + "{} {}".format(device.user_id, device.id)) + + def accept_sas(self, sas): + _, request = self.client.accept_key_verification(sas.transaction_id) + self.send(request) + + def cancel_sas(self, sas): + _, request = self.client.cancel_key_verification(sas.transaction_id) self.send(request) def to_device(self, message): _, request = self.client.to_device(message) self.send(request) - def accept_short_auth_string(self, transaction_id): - _, request = self.client.accept_short_auth_string(transaction_id) + def confirm_sas(self, sas): + _, request = self.client.accept_short_auth_string(sas.transaction_id) self.send(request) + device = sas.other_olm_device + + if sas.verified: + self.info("Device {} of user {} succesfully verified".format( + device.id, + device.user_id + )) + else: + self.info("Waiting for {} to confirm...".format(device.user_id)) + def _handle_sync(self, response): # we got the same batch again, nothing to do if self.next_batch == response.next_batch: From 88a2de637dd0e24336f4463e008fcd34c03ef43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 7 May 2019 22:18:21 +0200 Subject: [PATCH 07/14] commands: Fix an error message. --- matrix/commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix/commands.py b/matrix/commands.py index b9ca16e..0b6317b 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -756,8 +756,8 @@ def olm_sas_command(server, args): if not sas: server.error("No active key verification found for " "device {} of user {}.".format( - args.user_id, - args.device_id + args.device_id, + args.user_id )) return W.WEECHAT_RC_OK From 810a95edf07d68b97d356e8bc083b0af2840a0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 7 May 2019 22:22:45 +0200 Subject: [PATCH 08/14] server: Change the Sas confirmation function. --- matrix/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix/server.py b/matrix/server.py index a4e5145..e29feca 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -1328,7 +1328,7 @@ class MatrixServer(object): self.send(request) def confirm_sas(self, sas): - _, request = self.client.accept_short_auth_string(sas.transaction_id) + _, request = self.client.confirm_short_auth_string(sas.transaction_id) self.send(request) device = sas.other_olm_device From f294ae5e688ad2bb91950c50f3087378343d0b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 7 May 2019 22:23:16 +0200 Subject: [PATCH 09/14] commands: Allow key verifications to be cancelled. --- matrix/commands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/matrix/commands.py b/matrix/commands.py index 0b6317b..463b079 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -766,6 +766,8 @@ def olm_sas_command(server, args): server.accept_sas(sas) elif args.action == "confirm": server.confirm_sas(sas) + elif args.action == "cancel": + server.cancel_sas(sas) except LocalProtocolError as e: server.error(str(e)) From 9d6fbe14cd3df015c316ea9d6b74eadb631974b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 7 May 2019 22:31:56 +0200 Subject: [PATCH 10/14] server: Don't try to show a short auth string if the SAS object is canceled. --- matrix/server.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/matrix/server.py b/matrix/server.py index e29feca..1cbfb55 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -392,6 +392,9 @@ class MatrixServer(object): if not sas: return + if sas.canceled: + return + device = sas.other_olm_device emoji = sas.get_emoji() From c3b3567e6143322aabc894508bb44035e9511391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 7 May 2019 22:32:22 +0200 Subject: [PATCH 11/14] server: Show KeyVerificationCancel events. --- matrix/server.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/matrix/server.py b/matrix/server.py index 1cbfb55..9d766ae 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -462,6 +462,13 @@ class MatrixServer(object): device.user_id )) + elif isinstance(event, KeyVerificationCancel): + self.info_highlight("The interactive device verification with " + "user {} got canceled: {}.".format( + event.sender, + event.reason + )) + def update_option(self, option, option_name): if option_name == "address": self._change_client() From 53f1edf63ae9f966530fe9049884a10f6599cd94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 7 May 2019 22:32:45 +0200 Subject: [PATCH 12/14] server: Highlight room invitation messages. --- matrix/server.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/matrix/server.py b/matrix/server.py index 9d766ae..4ad8e5d 100644 --- a/matrix/server.py +++ b/matrix/server.py @@ -1234,7 +1234,7 @@ class MatrixServer(object): else: inviter_msg = "" - self.info( + self.info_highlight( "You have been invited to {} {}({}{}{}){}" "{}".format( room.display_name, @@ -1247,7 +1247,9 @@ class MatrixServer(object): ) ) else: - self.info("You have been invited to {}.".format(room_id)) + self.info_highlight("You have been invited to {}.".format( + room_id + )) for room_id, info in response.rooms.leave.items(): if room_id not in self.buffers: From fa5dca12de2e451c99d1689c8ff1cf260871f240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 15 May 2019 21:50:48 +0200 Subject: [PATCH 13/14] commands: Print out device display names. --- matrix/commands.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/matrix/commands.py b/matrix/commands.py index 463b079..bcdc204 100644 --- a/matrix/commands.py +++ b/matrix/commands.py @@ -486,13 +486,15 @@ def hook_commands(): hook_page_up() -def format_device(device_id, fp_key): +def format_device(device_id, fp_key, display_name): fp_key = partition_key(fp_key) - message = (" - Device ID: {device_color}{device_id}{ncolor}\n" - " - Device key: {key_color}{fp_key}{ncolor}").format( + message = (" - Device ID: {device_color}{device_id}{ncolor}\n" + " - Display name: {device_color}{display_name}{ncolor}\n" + " - Device key: {key_color}{fp_key}{ncolor}").format( device_color=W.color("chat_channel"), device_id=device_id, ncolor=W.color("reset"), + display_name=display_name, key_color=W.color("chat_server"), fp_key=fp_key) return message @@ -526,7 +528,8 @@ def olm_info_command(server, args): device_strings.append(format_device( device.id, - device.ed25519 + device.ed25519, + device.display_name )) if not device_strings: @@ -647,7 +650,8 @@ def olm_action_command(server, args, category, error_category, prefix, action): for device in device_list: device_strings.append(format_device( device.id, - device.ed25519 + device.ed25519, + device.display_name )) if not device_strings: continue From f9ebd61f93befda8230d10d64ef0b619a10ff29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Sat, 25 May 2019 11:39:03 +0200 Subject: [PATCH 14/14] requirements: Depend on the released nio version. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index abd1d7a..561ebde 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,4 @@ atomicwrites attrs logbook pygments -matrix-nio @ git+https://github.com/poljar/matrix-nio.git@master#egg=matrix-nio-0 +matrix-nio>=0.3