public int Send(byte[] buffer) { if (buffer[0] == 'W' && buffer[1] == 'A') { //received hello, must wait for features protocolPhase = 1; } else { MessageParser parser = new MessageParser(); ProtocolNode node = parser.ParseNode(buffer); if (node.tag == "stream:features") { //received features, must wait for auth protocolPhase = 2; } else if (node.tag == "auth") { protocolPhase = 3; receiveBuffer = new List<byte>(); //<stream:stream from="s.whatsapp.net"></stream:stream> Dictionary<string, string> startNodeAttributes = new Dictionary<string, string>(); startNodeAttributes["from"] = "s.whatsapp.net"; ProtocolNode startNode = new ProtocolNode("stream:stream", startNodeAttributes, null, ""); receiveBuffer.AddRange(startNode.ToBytes()); // <stream:features> // <receipt_acks></receipt_acks> //</stream:features> ProtocolNode receiptAcksNode = new ProtocolNode("receipt_acks", null, null, ""); List<ProtocolNode> featuresNodeChildren = new List<ProtocolNode>(); featuresNodeChildren.Add(receiptAcksNode); ProtocolNode featuresNode = new ProtocolNode("stream:features", null, featuresNodeChildren, ""); receiveBuffer.AddRange(featuresNode.ToBytes()); // <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">bm9uY2U9IjE0OTcxOTQ2MzkyMSIscW9wPSJhdXRoIixjaGFyc2V0PXV0Zi04LGFsZ29yaXRobT1tZDUtc2Vzcw==</challenge> Dictionary<string, string> attributes = new Dictionary<string, string>(); attributes["xmlns"] = "urn:ietf:params:xml:ns:xmpp-sasl"; ProtocolNode challenge = new ProtocolNode("challenge", attributes, null, "bm9uY2U9IjE0OTcxOTQ2MzkyMSIscW9wPSJhdXRoIixjaGFyc2V0PXV0Zi04LGFsZ29yaXRobT1tZDUtc2Vzcw=="); receiveBuffer.AddRange(challenge.ToBytes()); } else if (node.tag == "response") { //received //<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dXNlcm5hbWU9IjU1NTE5ODc2NTQzMiIscmVhbG09InMud2hhdHNhcHAubmV0Iixub25jZT0iMTQ5NzE5NDYzOTIxIixjbm9uY2U9IjM2MzgzNTNhMzUzNTM1MzEzOTM4MzczNjM1MzQzMzMyM2EzODMxMzIzODYxMzQzMDM4MzMzNzMxMzE2MTM4NjU2MTYzMzk2MTMzNjM2MzY0MzYzODMwNjM2MzMzNjMzOTMyIixuYz0wMDAwMDAwMSxxb3A9YXV0aCxkaWdlc3QtdXJpPSJ4bXBwL3Mud2hhdHNhcHAubmV0IixyZXNwb25zZT1lM2Q5MjIxOTRlN2M3MTBlYmE3YjEyNjI4Mjc5MTgzMyxjaGFyc2V0PXV0Zi04</response> //must verify and send success MessageFactory factory = new MessageFactory(); Dictionary<string,string> encodedAttributes = factory.ProcessChallenge(node); if (encodedAttributes["username"] == "555198765432" && encodedAttributes["realm"] == "s.whatsapp.net" && encodedAttributes["nonce"] == "149719463921" && encodedAttributes["nc"] == "00000001" && encodedAttributes["qop"] == "auth" && encodedAttributes["digest-uri"] == "xmpp/s.whatsapp.net" && encodedAttributes["charset"] == "utf-8") { //&& encodedAttributes["cnonce"] == "aaaaa" //&& encodedAttributes["response"] == "e3d922194e7c710eba7b126282791833" //TODO: validate cnonce e response //send //<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl" status="active" kind="free" creation="1338065926" expiration="1369601926"></success> ProtocolNode success = new ProtocolNode("success", null, null, ""); receiveBuffer.AddRange(success.ToBytes()); } } } return buffer.Length; }
public void LoginTest() { // send: // - hello // - feature // - auth TcpSocketMock socket = new TcpSocketMock(); MessageFactory messageFactory = new MessageFactory(); socket.Connect("bin-short.whatsapp.net", 5222); List<byte> helloMessage = messageFactory.CreateHelloMessage(); socket.Send(helloMessage.ToArray()); ProtocolNode features = messageFactory.CreateFeaturesNode(); socket.Send(features.ToBytes()); ProtocolNode authNode = messageFactory.CreateAuthNode(); socket.Send(authNode.ToBytes()); // receive // - start (tream) // - features // - challenge byte[] startMessage = new byte[7]; socket.Receive(startMessage, SocketFlags.None); MessageParser parser = new MessageParser(); ProtocolNode startNode = parser.ParseNode(startMessage); Console.WriteLine(startNode.ToString()); byte[] serverFeaturesMessage = new byte[10]; socket.Receive(serverFeaturesMessage, SocketFlags.None); parser = new MessageParser(); ProtocolNode serverFeaturesNode = parser.ParseNode(serverFeaturesMessage); Console.WriteLine(serverFeaturesNode.ToString()); byte[] challengeMessage = new byte[97]; socket.Receive(challengeMessage, SocketFlags.None); //send // - response parser = new MessageParser(); ProtocolNode challengeNode = parser.ParseNode(challengeMessage); Console.WriteLine(challengeNode.ToString()); Dictionary<string, string> challengeParameters = messageFactory.ProcessChallenge(challengeNode); string nonce = challengeParameters["nonce"]; string qop = challengeParameters["qop"]; string charset = challengeParameters["charset"]; string algorithm = challengeParameters["algorithm"]; WhatsAppApi api = new WhatsAppApi(); ProtocolNode authResponseNode = messageFactory.CreateAuthResponseNode("s.whatsapp.net", "555198765432", api.EncryptPassword("175422846762539"), nonce, qop, charset); socket.Send(authResponseNode.ToBytes()); byte[] serverMessage = new byte[1024]; socket.Receive(serverMessage, SocketFlags.None); parser = new MessageParser(); ProtocolNode resultNode = parser.ParseNode(serverMessage); Console.WriteLine(resultNode.ToString()); Assert.AreEqual(resultNode.tag, "success"); }