def user_got_kicked(irc_msg, server): """A user got kicked from a channel we are in. Remove them from the member list.""" account = accounts.get_my_account() parsed = util.parse_irc_quit_kick_part(irc_msg, server) nick = parsed['from_nick'] channel = parsed['channel'] command = parsed['command'] target = parsed['target'] assert(command.upper() == "KICK") util.debug("%s got kicked from %s by %s." % (target, channel, nick)) try: viola_room = account.get_viola_room(channel, server) except accounts.NoSuchRoom: util.debug("No viola room at %s. Sending plaintext." % channel) return try: viola_room.remove_member_and_rekey(target) except room.NoSuchMember: util.control_msg("A non-existent nick left the room. WTF.") # XXX i think this also catches ourselves
def user_left_channel(irc_msg, server): """A user left a channel we are in. Remove them from the channel if we are captain.""" account = accounts.get_my_account() parsed = util.parse_irc_quit_kick_part(irc_msg, server) nick = parsed['from_nick'] channel = parsed['channel'] command = parsed['command'] assert(command.upper() == "PART") util.debug("Received %s from %s in channel %s." % (command, nick, channel)) try: flute_room = account.get_flute_room(channel, server) except accounts.NoSuchRoom: util.debug("No flute room at %s. Sending plaintext." % channel) return try: flute_room.remove_member_and_rekey(nick) except room.NoSuchMember: util.control_msg("A non-existent nick left the room. WTF.") # XXX i think this also catches ourselves return
def user_got_kicked(irc_msg, server): """A user got kicked from a channel we are in. Remove them from the member list.""" account = accounts.get_my_account() parsed = util.parse_irc_quit_kick_part(irc_msg, server) nick = parsed['from_nick'] channel = parsed['channel'] command = parsed['command'] target = parsed['target'] assert(command.upper() == "KICK") util.debug("%s got kicked from %s by %s." % (target, channel, nick)) try: flute_room = account.get_flute_room(channel, server) except accounts.NoSuchRoom: util.debug("No flute room at %s. Sending plaintext." % channel) return try: flute_room.remove_member_and_rekey(target) except room.NoSuchMember: util.control_msg("A non-existent nick left the room. WTF.") # XXX i think this also catches ourselves
def user_left_channel(irc_msg, server): """A user left a channel we are in. Remove them from the channel if we are captain.""" account = accounts.get_my_account() parsed = util.parse_irc_quit_kick_part(irc_msg, server) nick = parsed['from_nick'] channel = parsed['channel'] command = parsed['command'] assert(command.upper() == "PART") util.debug("Received %s from %s in channel %s." % (command, nick, channel)) try: viola_room = account.get_viola_room(channel, server) except accounts.NoSuchRoom: util.debug("No viola room at %s. Sending plaintext." % channel) return try: viola_room.remove_member_and_rekey(nick) except room.NoSuchMember: util.control_msg("A non-existent nick left the room. WTF.") # XXX i think this also catches ourselves return
def introduction_cmd(parsed_args, buf): account = accounts.get_my_account() # Prepare the metadata server = util.get_local_server(buf) # If a nick is provided, introduce to that nick. Otherwise, check if we are # currently having a private conversation with another nick, and if so # introduce to that nick. if len(parsed_args) >= 2: target_nick = parsed_args[1] else: if otrlib.buffer_is_private(buf): target_nick = util.get_local_channel(buf) else: util.control_msg( "Bad introduction command! Can't introduce yourself to a channel!" ) raise flute.FluteCommandError introduction.send_introduction(account, target_nick, server, buf) util.flute_channel_msg(buf, "[Introduced ourselves to %s.]" % target_nick, color="green")
def print_friend_list(self): if not os.path.exists(self.friends_db_fname): util.control_msg("Friend list file does not exist.") return with open(self.friends_db_fname, 'r+') as friends_file: friends_dict = json.load(friends_file) util.control_msg("Current state of friend list:\n%s" % json.dumps(friends_dict, indent=2))
def trust_key_cmd(parsed_args, buf): nickname = parsed_args[1] hexed_key = parsed_args[2] # Check for illegal nickname chars if not nickname.isalnum(): util.control_msg("Invalid nickname: %s" % nickname) raise flute.FluteCommandError if len(hexed_key) != 64 or not util.is_hex(hexed_key): util.control_msg("Invalid key value: %s" % hexed_key) raise flute.FluteCommandError account = accounts.get_my_account() account.trust_key(nickname, hexed_key)
def trust_key(self, nickname, hexed_key): """Register trusted key 'hexed_key' under 'nickname'.""" util.debug("Trusting key by %s" % nickname) try: crypto.store_friends_pubkey_to_disk(nickname, hexed_key, self.friends_db_fname) except crypto.NickAlreadyRegistered: util.control_msg(otrlib.colorize("Nick %s is already registered." % nickname, "red")) return except crypto.KeyAlreadyRegistered: util.control_msg(otrlib.colorize("Key %s is already registered." % hexed_key, "red")) return # Print current version of the friend list self.print_friend_list()
def trust_key(self, nickname, hexed_key): """Register trusted key 'hexed_key' under 'nickname'.""" util.debug("Trusting key by %s" % nickname) try: crypto.store_friends_pubkey_to_disk(nickname, hexed_key, self.friends_db_fname) except crypto.NickAlreadyRegistered: util.control_msg( otrlib.colorize("Nick %s is already registered." % nickname, "red")) return except crypto.KeyAlreadyRegistered: util.control_msg( otrlib.colorize("Key %s is already registered." % hexed_key, "red")) return # Print current version of the friend list self.print_friend_list()
def print_fingerprint(self): identity_key = self.get_identity_pubkey() hexed_key = crypto.get_hexed_key(identity_key) util.control_msg("Our identity key is:") util.control_msg("\t%s" % otrlib.colorize(hexed_key, "green")) util.control_msg( "A friend can trust it using the '/flute trust-key' command.")
def introduction_cmd(parsed_args, buf): account = accounts.get_my_account() # Prepare the metadata server = util.get_local_server(buf) # If a nick is provided, introduce to that nick. Otherwise, check if we are # currently having a private conversation with another nick, and if so # introduce to that nick. if len(parsed_args) >= 2: target_nick = parsed_args[1] else: if otrlib.buffer_is_private(buf): target_nick = util.get_local_channel(buf) else: util.control_msg("Bad introduction command! Can't introduce yourself to a channel!") raise flute.FluteCommandError introduction.send_introduction(account, target_nick, server, buf) util.flute_channel_msg(buf, "[Introduced ourselves to %s.]" % target_nick, color="green")
def print_fingerprint(self): identity_key = self.get_identity_pubkey() hexed_key = crypto.get_hexed_key(identity_key) util.control_msg("Our identity key is:") util.control_msg("\t%s" % otrlib.colorize(hexed_key, "green")) util.control_msg("A friend can trust it using the '/flute trust-key' command.")
def handle_introduction_packet(packet_payload, parsed): util.debug("Parsing introduction packet") payload = base64.b64decode(packet_payload) if len(payload) < INTRODUCTION_PAYLOAD_LEN: raise IncompletePacket # Get packet fields signature = payload[:64] rcvd_pubkey = crypto.parse_signing_pubkey(payload[64:64+32]) # Verify signature try: rcvd_pubkey.verify(payload) except nacl.exceptions.BadSignatureError: util.control_msg("Could not verify signature of INTRODUCTION packet.") return "" hexed_key = crypto.get_hexed_key(rcvd_pubkey) irc_nick = parsed['from_nick'] util.control_msg("You received an introduction from %s with identity key:" % irc_nick) util.control_msg("\t%s" % otrlib.colorize(hexed_key, "green")) util.control_msg("If you trust that key, please type:") util.control_msg("\t /flute trust-key <name> %s" % hexed_key) util.control_msg("where <name> is the nickname you want to assign to the key.") util.control_msg("Example: /flute trust-key alice %s" % hexed_key) util.control_msg("-" * 100) return ""
def handle_room_message_packet(packet_payload, parsed, server): sender_host = parsed['from'] sender_nick = parsed['from_nick'] channel = parsed['to_channel'] account = accounts.get_my_account() if not channel: # XXX functionify util.debug("Received ROOM_MESSAGE not in channel from %s. Ignoring." % sender_host) return "" # Is this channel a viola room for us? # XXX Code duplication try: viola_room = account.get_viola_room(channel, server) except accounts.NoSuchRoom: util.debug("Received ROOM_MESSAGE in a regular channel (%s). Ignoring." % channel) buf = util.get_current_buffer() # XXX weechat API shouldn't polute viola.py util.viola_channel_msg(buf, "[You hear a viola screeching... Please do '/viola join-room' to join the session.]", "lightcyan") return "" try: room_message_key = viola_room.get_room_message_key() except room.NoMessageKey: util.debug("Received ROOM_MESSAGE in %s but no message key. Ignoring." % channel) # XXX ??? util.viola_channel_msg(viola_room.buf, "[You hear a viola screeching... Please do '/viola join-room' to join the session.]", "grey") return "" # Get room member object based on sender_host nickname: try: room_member = viola_room.get_member(sender_nick) except room.NoSuchMember: util.control_msg("Received ROOM_MESSAGE from %s who is not a room member. Ignoring." % sender_host) return "" payload = base64.b64decode(packet_payload) if len(payload) <= 64: raise IncompletePacket util.debug("Attempting to decrypt ROOM_MESSAGE in %s" % channel) # Get packet fields signature = payload[:SIG_LEN] message_ciphertext = payload[SIG_LEN:] # Verify signature verify_key = room_member.get_identity_pubkey() try: verify_key.verify(payload) # XXX put this in crypto.py except nacl.exceptions.BadSignatureError: util.control_msg("Could not verify signature of ROOM_MESSAGE by %s" % sender_host) return "" # XXX catch decrypt exception try: plaintext = crypto.decrypt_room_message(room_message_key, message_ciphertext) except nacl.exceptions.CryptoError: util.viola_channel_msg(viola_room.buf, "Could not decrypt message sent in room. Maybe old key. Try rejoining the channel.", "red") # XXX this won't work return "" msg = "[ENCRYPTED] %s" % plaintext msg_in = otrlib.build_privmsg_in(sender_host, channel, msg) return msg_in
# Check if nick or key are already registered. if hexed_key in friends_dict: raise KeyAlreadyRegistered() if nickname in friends_dict.values(): raise NickAlreadyRegistered() # Prepare entry for new friend new_friend = {hexed_key : nickname} friends_dict.update(new_friend) # Update database with open(friends_db_fname, 'w') as friends_file: json.dump(friends_dict, friends_file) util.control_msg("Success. %s added to friend list." % nickname) def array_chunk_generator(array, chunk_size): """Yield successive n-sized chunks from l.""" for i in xrange(0, len(array), chunk_size): yield array[i : i+chunk_size] def decrypt_room_message_key(message_key_array, captain_transport_pubkey, my_room_privkey): """ Parse the message key array, do the trial decryption, and try to retrieve the room message key. Return it if found, otherwise raise NoKeyFound. """ # The array length needs to be a multiple of 72 bytes. if len(message_key_array) % 72 != 0: util.debug("Received message key array of length %d" % len(message_key_array)) raise NoKeyFound
def handle_introduction_packet(packet_payload, parsed): util.debug("Parsing introduction packet") payload = base64.b64decode(packet_payload) if len(payload) < INTRODUCTION_PAYLOAD_LEN: raise IncompletePacket # Get packet fields signature = payload[:64] rcvd_pubkey = crypto.parse_signing_pubkey(payload[64:64+32]) # Verify signature try: rcvd_pubkey.verify(payload) except nacl.exceptions.BadSignatureError: util.control_msg("Could not verify signature of INTRODUCTION packet.") return "" hexed_key = crypto.get_hexed_key(rcvd_pubkey) irc_nick = parsed['from_nick'] util.control_msg("You received an introduction from %s with identity key:" % irc_nick) util.control_msg("\t%s" % otrlib.colorize(hexed_key, "green")) util.control_msg("If you trust that key, please type:") util.control_msg("\t /viola trust-key <name> %s" % hexed_key) util.control_msg("where <name> is the nickname you want to assign to the key.") util.control_msg("Example: /viola trust-key alice %s" % hexed_key) util.control_msg("-" * 100) return ""
# Check if nick or key are already registered. if hexed_key in friends_dict: raise KeyAlreadyRegistered() if nickname in friends_dict.values(): raise NickAlreadyRegistered() # Prepare entry for new friend new_friend = {hexed_key: nickname} friends_dict.update(new_friend) # Update database with open(friends_db_fname, 'w') as friends_file: json.dump(friends_dict, friends_file) util.control_msg("Success. %s added to friend list." % nickname) def array_chunk_generator(array, chunk_size): """Yield successive n-sized chunks from l.""" for i in xrange(0, len(array), chunk_size): yield array[i:i + chunk_size] def decrypt_room_message_key(message_key_array, captain_transport_pubkey, my_room_privkey): """ Parse the message key array, do the trial decryption, and try to retrieve the room message key. Return it if found, otherwise raise NoKeyFound. """ # The array length needs to be a multiple of 72 bytes.