def handleSenderKeyMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity(node) enc_ = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG) senderKeyName = SenderKeyName( encMessageProtocolEntity.sender, AxolotlAddress( Jid.denormalize(encMessageProtocolEntity.participant), 0)) groupCipher = GroupCipher(self.store, senderKeyName) try: plaintext = groupCipher.decrypt(enc_.getData()) paddingByte = plaintext[-1] if type(plaintext[-1]) is int else ord( plaintext[-1]) padding = paddingByte & 0xFF self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext[:-padding]) except NoSessionException: logger.warning( "No session for %s, going to send a retry", Jid.denormalize(encMessageProtocolEntity.getAuthor())) retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode( node, self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode()) except Exception as ex: # (AttributeError, TypeError) logger.error('Exception in handleSenderKeyMessage: %s' % ex) raise
def parseAndHandleMessageProto(self, encMessageProtocolEntity, serializedData): node = encMessageProtocolEntity.toProtocolTreeNode() m = Message() try: if sys.version_info >= (3, 0) and isinstance(serializedData, str): serializedData = serializedData.encode() except AttributeError: logger.warning( "AttributeError: 'bytes' object has no attribute 'encode'. Skipping 'encode()'" ) pass if "YOWSUP_PROTOBUF_DEBUG" in os.environ: from yowsup.common.protobuf_inspect.types import StandardParser parser = StandardParser() parser.types["root"] = {} parser.types["root"]["compact"] = False print( parser.safe_call(parser.match_handler("message"), BytesIO(serializedData), "root")) handled = False try: m.ParseFromString(serializedData) params = protobuf_to_dict(m) except Exception: raise if not m or not serializedData: raise ValueError("Empty message") if m.HasField("sender_key_distribution_message"): handled = True axolotlAddress = AxolotlAddress( Jid.denormalize(encMessageProtocolEntity.participant), 0) self.handleSenderKeyDistributionMessage( params['sender_key_distribution_message'], axolotlAddress) params.pop('sender_key_distribution_message') body_type = m.WhichOneof("body") if len(params) and body_type: messageNode = copy.deepcopy(node) messageNode.addChild( ProtocolTreeNode("body", {"type": body_type}, data=params[body_type])) self.toUpper(messageNode) elif not handled: raise ValueError("Unhandled")
def handlePreKeyWhisperMessage(self, node): pkMessageProtocolEntity = EncryptedMessageProtocolEntity(node) enc_ = pkMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_PKMSG) preKeyWhisperMessage = PreKeyWhisperMessage(serialized=enc_.getData()) sessionCipher = self.getSessionCipher( Jid.denormalize(pkMessageProtocolEntity.getAuthor())) plaintext = sessionCipher.decryptPkmsg(preKeyWhisperMessage) if enc_.getVersion() == 2: paddingByte = plaintext[-1] if type(plaintext[-1]) is int else ord( plaintext[-1]) padding = paddingByte & 0xFF self.parseAndHandleMessageProto(pkMessageProtocolEntity, plaintext[:-padding]) else: logger.error("Ignoring message with old version")
def handleWhisperMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity(node) enc_ = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_MSG) whisperMessage = WhisperMessage(serialized=enc_.getData()) sessionCipher = self.getSessionCipher( Jid.denormalize(encMessageProtocolEntity.getAuthor())) plaintext = sessionCipher.decryptMsg(whisperMessage) if enc_.getVersion() == 2: paddingByte = plaintext[-1] if type(plaintext[-1]) is int else ord( plaintext[-1]) padding = paddingByte & 0xFF self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext[:-padding]) else: raise Exception("Protocol not longer supported")
def handleEncMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity(node) isGroup = node["participant"] is not None senderJid = node["participant"] if isGroup else node["from"] if node.getChild( "enc")["v"] == "2" and node["from"] not in self.v2Jids: self.v2Jids.append(node["from"]) try: if encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_PKMSG): self.handlePreKeyWhisperMessage(node) elif encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_MSG): self.handleWhisperMessage(node) if encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG): self.handleSenderKeyMessage(node) except (InvalidMessageException, InvalidKeyIdException): logger.warning( "InvalidMessage or InvalidKeyIdException for %s, would to send a retry", Jid.denormalize(encMessageProtocolEntity.getAuthor())) if node["count"] is not None: logger.warning("This is the second retry forget it") return from yowsup.layers.axolotl.protocolentities.iq_key_get import GetKeysIqProtocolEntity logger.info("Trying GetKeys for %s, getting keys now", Jid.denormalize(encMessageProtocolEntity.getAuthor())) # entity = GetKeysIqProtocolEntity([Jid.denormalize(encMessageProtocolEntity.getAuthor())]) retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode( node, self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode()) except NoSessionException: logger.warning( "No session for %s, getting their keys now", Jid.denormalize(encMessageProtocolEntity.getAuthor())) conversationIdentifier = (node["from"], node["participant"]) if conversationIdentifier not in self.pendingIncomingMessages: self.pendingIncomingMessages[conversationIdentifier] = [] self.pendingIncomingMessages[conversationIdentifier].append(node) def successFn(successJids, _): return self.processPendingIncomingMessages( *conversationIdentifier) if len(successJids) else None self.getKeysFor([senderJid], successFn) except DuplicateMessageException: logger.warning( "Received a message that we've previously decrypted, goint to send the delivery receipt myself" ) self.toLower( OutgoingReceiptProtocolEntity( node["id"], node["from"], participant=node["participant"]).toProtocolTreeNode()) except UntrustedIdentityException as e: if self.getProp(PROP_IDENTITY_AUTOTRUST, False): logger.warning("Autotrusting identity for %s", e.getName()) self.store.saveIdentity(e.getName(), e.getIdentityKey()) return self.handleEncMessage(node) else: logger.error("Ignoring message with untrusted identity")