def after_data_prep_send(ack = None): allData = self.data_buffer.read() self._close_data_buffer() msg = P2PMessage.P2PDataMessage(self.version) if self.version == P2P.Version.V1: msg.Header.Flags = P2P.Flags.Data msg.Header.AckSessionId = random.randint(50, sys.maxint) else: msg.Header.TFCombination = P2P.TFCombination.MsnObject | P2P.TFCombination.First msg.Header.PackageNumber = packNum msg.InnerBody = allData if self.version == P2P.Version.V1: log.info("Sending data message for (V1) %r", self) self.SendMessage(msg, success = lambda ack: self.OnTransferFinished()) else: log.info("Sending data message for (V2) %r", self) def after_data_send(ack = None): rak = P2PMessage.P2PMessage(self.version) rak.SetRAK() log.info("Sending RAK message for (V2). rak = %r, app = %r", rak, self) self.SendMessage(rak, success = lambda ack: self.OnTransferFinished()) self.SendMessage(msg, success = after_data_send)
def Start(self): if not super(P2PActivity, self).Start(): return False if not self.sending: return if not self.ActivityData: return self.ActivityData += u'\0' urlLength = len(self.ActivityData.encode('utf-16-le')) prepData = P2PMessage.P2PDataMessage(self.version) if self.version == P2P.Version.V1: header = '\x80\0\0\0' else: header = '\x80\x3f\x14\x05' data = ''+header data += struct.pack('<H', 8) data += struct.pack('<I', urlLength) data += self.ActivityData.encode('utf-16-le') prepData.InnerBody = urlData if self.version == P2P.Version.V2: prepData.Header.TFCombination = P2P.TFCombination.First self.SendMessage(prepData)
def WrapSLPMessage(self, slp): message = P2PMessage.P2PMessage(self.Version) message.InnerMessage = slp if message.Version == P2P.Version.V2: message.Header.TFCombination = P2P.TFCombination.First message.Header.PackageNumber = self.Bridge.IncrementPackageNumber() else: message.Header.Flags = P2P.Flags.MSNSLPInfo return message
def VerifyHandshake(self, data): authVersion = P2P.Version.V1 ret = None version1 = False version2 = False if len(data) == 48: authVersion = P2P.Version.V1 version1 = True elif len(data) == 16: authVersion = P2P.Version.V2 version2 = True else: return None if authVersion != self.Version: return None incomingHandshake = P2PMessage.P2PDCHandshakeMessage(self.Version) incomingHandshake.ParseBytes(data) incomingGuid = incomingHandshake.Guid if version1 and ((incomingHandshake.VHeader.Flags & P2P.Flags.DCHS) != P2P.Flags.DCHS): return None compareGuid = incomingGuid if self.needHash: compareGuid = MSNU.HashNonce(compareGuid) if self.Nonce == compareGuid or not self.StrictNonce: if self.Nonce != compareGuid: log.warning("nonces don't match! continuing anyway.") ret = P2PMessage.P2PDCHandshakeMessage(self.Version) ret.ParseBytes(data) ret.Guid = compareGuid ret.Header.Identifier = 0 return ret return None
def Start(self): if not super(ObjectTransfer, self).Start(): return False # if self.Remote.DirectBridge is None: # log.error("Don't have a direct bridge (MSNObject)") # return False if self.sending: log.info("Starting send for %r", self) self.P2PSession.Bridge.packageNumber += 1 packNum = self.P2PSession.Bridge.packageNumber prepData = P2PMessage.P2PDataMessage(self.version) prepData.WritePreparationBytes() if self.version == P2P.Version.V2: prepData.Header.TFCombination = P2P.TFCombination.First def after_data_prep_send(ack = None): allData = self.data_buffer.read() self._close_data_buffer() msg = P2PMessage.P2PDataMessage(self.version) if self.version == P2P.Version.V1: msg.Header.Flags = P2P.Flags.Data msg.Header.AckSessionId = random.randint(50, sys.maxint) else: msg.Header.TFCombination = P2P.TFCombination.MsnObject | P2P.TFCombination.First msg.Header.PackageNumber = packNum msg.InnerBody = allData if self.version == P2P.Version.V1: log.info("Sending data message for (V1) %r", self) self.SendMessage(msg, success = lambda ack: self.OnTransferFinished()) else: log.info("Sending data message for (V2) %r", self) def after_data_send(ack = None): rak = P2PMessage.P2PMessage(self.version) rak.SetRAK() log.info("Sending RAK message for (V2). rak = %r, app = %r", rak, self) self.SendMessage(rak, success = lambda ack: self.OnTransferFinished()) self.SendMessage(msg, success = after_data_send) log.info("Sending data prep message for %r", self) self.SendMessage(prepData, after_send = after_data_prep_send) else: log.info("Starting receive for %r", self) self.data_buffer = io.BytesIO()
def SendDirectInvite(self): if not common.pref('msn.p2p.allow_direct', type = bool, default = True): return False if self.Remote.DirectBridge is not None and self.Remote.DirectBridge.IsOpen: return False self.ResetDCTimer() connType, netId = self.ConnectionType(self.protocol) remote = self.Remote ver = self.Version message = P2PMessage.P2PMessage(ver) slp = MSNSLP.SLPRequestMessage(self.RemoteContactId, MSNSLP.RequestMethod.INVITE) slp.Source = self.LocalContactId slp.CSeq = 0 slp.CallId = self.Invitation.CallId slp.MaxForwards = 0 slp.ContentType = 'application/x-msnmsgr-transreqbody' slp.BodyValues['Bridges'] = 'TCPv1 SBBridge' slp.BodyValues['Capabilities-Flags'] = '1' slp.BodyValues['NetID'] = str(netId) slp.BodyValues['Conn-Type'] = connType slp.BodyValues['TCP-Conn-Type'] = connType slp.BodyValues['UPnPNat'] = 'false' slp.BodyValues['ICF'] = 'true' if connType == 'Firewall' else 'false' slp.BodyValues['Nat-Trav-Msg-Type'] = 'WLX-Nat-Trav-Msg-Direct-Connect-Req' remote.GenerateNewDCKeys() slp.BodyValues['Hashed-Nonce'] = '{%s}' % str(remote.dcLocalHashedNonce).upper() message.InnerMessage = slp if ver == P2P.Version.V2: message.Header.TFCombination = P2P.TFCombination.First else: message.Header.Flags = P2P.Flags.MSNSLPInfo Bridge = self.protocol.ns.SDGBridge Bridge.StopSending(self) self.ResetDCTimer() log.info("Sending direct invite") Bridge.Send(None, remote, self.RemoteContactEPID, message) return True
def OnMessageReceived(self, data): #_log.info("%r got data: %r", self, data) #_log.info("\tDC state = %r", self.DCState) if self.DCState == DCState.Established: dcMessage = P2PMessage.P2PDCMessage(self.Version) dcMessage.ParseBytes(data) #_log.info("Got P2P message! %r", dcMessage) self.OnP2PMessageReceived(dcMessage) elif self.DCState == DCState.HandshakeReply: match = self.VerifyHandshake(data) if match is None: log.info("Bad handshake. Disconnecting") self.Disconnect() return else: log.info("Got valid handshake. Session Established") self.DCState = DCState.Established elif self.DCState == DCState.Handshake: match = self.VerifyHandshake(data) if match is None: log.info("Handshake didn't verify. Disconnecting...") self.Disconnect() return match.Guid = self.Reply if self.Version == P2P.Version.V1: match.Header.Identifier = self.startupSession.NextLocalIdentifier( 0) log.info( "Sending matching handshake and changing to 'Established'") self.SendSocketData(self.dcSocket, match.GetBytes()) self.DCState = DCState.Established elif self.DCState == DCState.Foo: if len(data) == 4 and data == 'foo\0': log.info("Got FOO. State is now 'Handshake'") self.DCState = DCState.Handshake else: log.info("Got something besides foo. Disconnecting") self.Disconnect() return else: log.info("Don't know what to do with this data: %r", data)
def Decline(self): if self.Status != P2PSessionStatus.WaitingForLocal: return False slpMessage = self._MakeSLPStatusMessage(self.RemoteContactId, 603, 'Decline') msg = P2PMessage.P2PMessage(self.Version) if self.Version == P2P.Version.V1: msg.Header.Flags = P2P.Flags.MSNSLPInfo else: msg.Header.OperationCode = P2P.OperationCode.RAK msg.Header.TFCombination = P2P.TFCombination.First msg.Header.PackageNumber = self.Bridge.IncrementPackageNumber() msg.InnerMessage = slpMessage self.Send(msg, success = lambda ack: self.Close())
def OnConnected(self): if (not self.IsListener) and self.DCState == DCState.Closed: log.info( "Connected! Changing state to Foo, sending Foo, changing state to Handshake, sending handshake, changing state to HandshakeReply" ) self.DCState = DCState.Foo self.SendSocketData(self.dcSocket, '\x04\0\0\0foo\0') self.DCState = DCState.Handshake hm = P2PMessage.P2PDCHandshakeMessage(self.Version) hm.Guid = self.Reply log.info("Sending handshake reply message: %r", hm) if self.Version == P2P.Version.V1: hm.Header.Identifier = self.startupSession.NextLocalIdentifier( 0) self.SendSocketData(self.dcSocket, hm.GetBytes()) self.DCState = DCState.HandshakeReply
def SendBye(self): if self._sent_bye: log.info("Already sent bye message. not re-sending") return self._sent_bye = True log.info("Constructing and queueing BYE message for %r", self) slpMessage = self._MakeSLPRequestMessage(self.RemoteContactId, 'BYE') slpMessage.MaxForwards = 0 slpMessage.CSeq = 0 slpMessage.Branch = self.Invitation.Branch slpMessage.ContentType = 'application/x-msnmsgr-sessionclosebody' msg = P2PMessage.P2PMessage(self.Version) if msg.Version == P2P.Version.V1: msg.Header.Flags = P2P.Flags.MSNSLPInfo else: msg.Header.OperationCode = P2P.OperationCode.RAK msg.Header.TFCombination = P2P.TFCombination.First if self.Bridge is not None: msg.Header.PackageNumber = self.Bridge.IncrementPackageNumber() msg.InnerMessage = slpMessage self.Send(msg, after_send = lambda ack=None: self.OnClosed(self.Local))
def after_data_send(ack = None): rak = P2PMessage.P2PMessage(self.version) rak.SetRAK() log.info("Sending RAK message for (V2). rak = %r, app = %r", rak, self) self.SendMessage(rak, success = lambda ack: self.OnTransferFinished())
def ProcessDCRespInvite(message, ns, session): body = message.BodyValues if body.get('Bridge', None) == 'TCPv1' and body.get('Listening', 'false').lower() == 'true': remote = ns.contact_list.GetContact(message.FromEmailAccount, MSNAB.IMAddressInfoType.WindowsLive) remoteGuid = message.FromEndPoint dcNonceType, remoteNonce = ParseDCNonce(body) hashed = dcNonceType == DCNonceType.Sha1 replyGuid = remote.dcPlainKey if hashed else remoteNonce selectedPoints = SelectIPEndPoints(body, ns) log.info("SelectedPoints = %r", selectedPoints) if selectedPoints is None or len(selectedPoints) == 0: if session is not None: session.DirectNegotiationFailed() return if uuid.UUID(int = 0) in (message.FromEndPoint, message.ToEndPoint): version1 = True ver = P2P.Version.V1 else: version2 = True ver = P2P.Version.V2 remote.DirectBridge = CreateDirectConnection(remote, remoteGuid, ver, selectedPoints, replyGuid, remoteNonce, hashed, ns, session) needConnectingEndpointInfo = body.get('NeedConnectingEndpointInfo', 'false') == 'true' if needConnectingEndpointInfo: ipep = remote.DirectBridge.LocalEndPoint # Host, port if ipep is not None: port = ipep[-1] else: log.info("Not sending my address info to other client") return ips = map(util.ip_from_bytes, util.myips()) # if ns.protocol.ip not in ips: # ips.append(ns.protocol.ip) hkey = 'IPv4InternalAddrsAndPorts'[::-1] hval = ' '.join(('%s:%s' % (ip, port) for ip in ips))[::-1] slp = MSNSLP.SLPRequestMessage(message.Source, MSNSLP.RequestMethod.ACK) slp.Source = message.Target slp.Via = message.Via slp.CSeq = 0 slp.CallId = str(uuid.UUID(int=0)) slp.MaxForards = 9 slp.ContentType = 'application/x-msnmsgr-transdestaddrupdate' slp.BodyValues[hkey] = hval slp.BodyValues['Nat-Trav-Msg-Type'] = "WLX-Nat-Trav-Msg-Updated-Connecting-Port" msg = P2PMessage.P2PMessage(ver) msg.InnerMessage = slp Bridge = ns.SDGBridge Bridge.Send(None, remote, remoteGuid, msg) else: log.info("Sending transrespbody through transreqbody handler...") return ProcessDCReqInvite(message, ns, session)
def ProcessDCReqInvite(message, ns, session): if session is not None and session.Bridge is not None and session.Bridge.BridgeType == 'TCPv1': return if 'TCPv1' not in message.BodyValues.get('Bridges', message.BodyValues.get('Bridge', '')): if session is not None: session.DirectNegotiationFailed() return remoteGuid = message.FromEndPoint remote = ns.contact_list.GetContact(message.FromEmailAccount, MSNAB.IMAddressInfoType.WindowsLive) dcNonceType, remoteNonce = ParseDCNonce(message.BodyValues) if remoteNonce == uuid.UUID(int = 0): remoteNonce = remote.dcPlainKey hashed = dcNonceType == DCNonceType.Sha1 nonceFieldName = 'Hashed-Nonce' if hashed else 'Nonce' myHashedNonce = remote.dcLocalHashedNonce if hashed else remoteNonce myPlainNonce = remote.dcPlainKey if dcNonceType == DCNonceType.Sha1: remote.dcType = dcNonceType remote.dcRemoteHashedNonce = remoteNonce else: remote.dcType = DCNonceType.Plain myPlainNonce = remote.dcPlainKey = remote.dcLocalHashedNonce = remote.dcRemoteHashedNonce = remoteNonce ipAddress = util.ip_from_bytes(util.myip()) port = 0 if (message.FromEndPoint != uuid.UUID(int=0) and message.ToEndPoint != uuid.UUID(int=0)): ver = P2P.Version.V2 else: ver = P2P.Version.V1 try: remote.DirectBridge = ListenForDirectConnection(remote, remoteGuid, ns, ver, session, ipAddress, port, myPlainNonce, remoteNonce, hashed) except Exception as e: import traceback; traceback.print_exc() log.error("Error setting up direct bridge: %r", e) port = 0 else: port = remote.DirectBridge.LocalEndPoint[1] slp = MSNSLP.SLPStatusMessage(message.Source, 200, 'OK') slp.Target = message.Source slp.Source = message.Target slp.Branch = message.Branch slp.CSeq = 1 slp.CallId = message.CallId slp.MaxForwards = 0 slp.ContentType = 'application/x-msnmsgr-transrespbody' slp.BodyValues['Bridge'] = 'TCPv1' log.info("port = %r, ipaddress = %r, protocol.ip == %r, other_listening = %r", port, ipAddress, ns.protocol.ip, message.BodyValues.get("Listening", None)) if port == 0 and message.BodyValues.get("Listening", None) != "false": slp.BodyValues['Listening'] = 'false' slp.BodyValues[nonceFieldName] = '{%s}' % str(uuid.UUID(int = 0)) else: slp.BodyValues['Listening'] = 'true' slp.BodyValues['Capabilities-Flags'] = '1' slp.BodyValues['IPv6-global'] = '' slp.BodyValues['Nat-Trav-Msg-Type'] = 'WLX-Nat-Trav-Msg-Direct-Connect-Resp' slp.BodyValues['UPnPNat'] = 'false' slp.BodyValues['NeedConnectingEndpointInfo'] = 'true' slp.BodyValues['Conn-Type'] = 'Direct-Connect' slp.BodyValues['TCP-Conn-Type'] = 'Direct-Connect' slp.BodyValues[nonceFieldName] = '{%s}' % str(myHashedNonce).upper() slp.BodyValues['IPv4Internal-Addrs'] = ipAddress slp.BodyValues['IPv4Internal-Port'] = str(port) if ipAddress != ns.protocol.ip: slp.BodyValues['IPv4External-Addrs'] = ns.protocol.ip slp.BodyValues['IPv4External-Port'] = str(port) p2pmessage = P2PMessage.P2PMessage(ver) p2pmessage.InnerMessage = slp if ver == P2P.Version.V2: p2pmessage.Header.TFCombination = P2P.TFCombination.First else: p2pmessage.Header.Flags = P2P.Flags.MSNSLPInfo if session is not None: session.ResetDCTimer() session.Bridge.Send(None, session.Remote, session.RemoteContactID, p2pmessage) session.Bridge.StopSending(session) else: ns.SDGBridge.Send(None, remote, remoteGuid, p2pmessage)