diff --git a/websocket-sharp.userprefs b/websocket-sharp.userprefs index 95d21ed1..1810154c 100644 --- a/websocket-sharp.userprefs +++ b/websocket-sharp.userprefs @@ -1,8 +1,8 @@  - + - + diff --git a/websocket-sharp/Ext.cs b/websocket-sharp/Ext.cs index 901ccaeb..c5cb5172 100644 --- a/websocket-sharp/Ext.cs +++ b/websocket-sharp/Ext.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; +using System.Linq; namespace WebSocketSharp { @@ -40,11 +41,91 @@ namespace WebSocketSharp return b == Convert.ToByte(c); } - public static void NotEqualsDo(this string a, string b, Action action) + public static uint GenerateKey(this Random rand, int space) + { + uint max = (uint)(0xffffffff / space); + + int upper16 = (int)((max & 0xffff0000) >> 16); + int lower16 = (int)(max & 0x0000ffff); + + return ((uint)rand.Next(upper16 + 1) << 16) + (uint)rand.Next(lower16 + 1); + } + + public static string GenerateSecKey(this Random rand, out uint key) + { + int space = rand.Next(1, 13); + int ascii = rand.Next(1, 13); + + key = rand.GenerateKey(space); + + long mKey = key * space; + char[] mKeyChars = mKey.ToString().ToCharArray(); + int mKeyCharsLen = mKeyChars.Length; + + int secKeyCharsLen = mKeyCharsLen + space + ascii; + char[] secKeyChars = new char[secKeyCharsLen].InitializeWith(' '); + + secKeyChars[0] = mKeyChars[0]; + secKeyChars[secKeyCharsLen - 1] = mKeyChars[mKeyCharsLen - 1]; + + int i = 0; + for (int j = 1; j < mKeyCharsLen - 1; j++) + { + i = rand.Next(i + 1, secKeyCharsLen - mKeyCharsLen + j + 1); + secKeyChars[i] = mKeyChars[j]; + } + + var convToAscii = secKeyChars + .IndexOf(' ') + .OrderBy( x => Guid.NewGuid() ) + .Where( (x, idx) => idx < ascii ); + + int k; + foreach (int index in convToAscii) + { + k = rand.Next(2) == 0 ? rand.Next(33, 48) : rand.Next(58, 127); + secKeyChars[index] = Convert.ToChar(k); + } + + return new String(secKeyChars); + } + + public static IEnumerable IndexOf(this T[] array, T val) + { + for (int i = 0; i < array.Length; i++) + { + if (array[i].Equals(val)) + { + yield return i; + } + } + } + + public static T[] InitializeWith(this T[] array, T val) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = val; + } + + return array; + } + + public static Byte[] InitializeWithASCII(this Byte[] bytes, Random rand) + { + for (int i = 0; i < bytes.Length; i++) + { + bytes[i] = (byte)rand.Next(32, 127); + } + + return bytes; + } + + public static void NotEqualsDo(this string a, string b, Action action) { if (a != b) { - action(a); + action(a, b); } } } diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index c72a8743..d17b863e 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -33,11 +33,13 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Text; using System.Threading; +using System.Security.Cryptography; namespace WebSocketSharp { @@ -256,17 +258,39 @@ namespace WebSocketSharp host += ":" + port; } - string subprotocol = protocol != String.Empty + string subProtocol = protocol != String.Empty ? String.Format("Sec-WebSocket-Protocol: {0}\r\n", protocol) : protocol; +#if !CHALLENGE + string secKeys = String.Empty; + string key3AsASCII = String.Empty; +#else + Random rand = new Random(); + uint key1, key2; + string secKey1 = rand.GenerateSecKey(out key1); + string secKey2 = rand.GenerateSecKey(out key2); + + byte[] key3 = new byte[8].InitializeWithASCII(rand); + + string secKeys = "Sec-WebSocket-Key1: {0}\r\n" + + "Sec-WebSocket-Key2: {1}\r\n"; + secKeys = String.Format(secKeys, secKey1, secKey2); + + string key3AsASCII = Encoding.ASCII.GetString(key3); + + byte[] expectedRes = createExpectedRes(key1, key2, key3); + byte[] actualRes = new byte[16]; +#endif string request = "GET " + path + " HTTP/1.1\r\n" + "Upgrade: WebSocket\r\n" + "Connection: Upgrade\r\n" + - subprotocol + + subProtocol + "Host: " + host + "\r\n" + "Origin: " + origin + "\r\n" + - "\r\n"; + secKeys + + "\r\n" + + key3AsASCII; #if DEBUG Console.WriteLine("WS: Info @doHandshake: Handshake from client: \n{0}", request); #endif @@ -283,6 +307,10 @@ namespace WebSocketSharp wsStream.ReadByte().EqualsWithSaveTo('\r', rawdata) && wsStream.ReadByte().EqualsWithSaveTo('\n', rawdata)) { +#if CHALLENGE + wsStream.Read(actualRes, 0, actualRes.Length); + rawdata.AddRange(actualRes); +#endif break; } } @@ -297,15 +325,25 @@ namespace WebSocketSharp Console.WriteLine("{0}", s); } #endif - Action action = s => { throw new IOException("Invalid handshake response: " + s); }; + Action action = (a, b) => + { + throw new IOException("Invalid handshake response: " + a); + }; +#if !CHALLENGE response[0].NotEqualsDo("HTTP/1.1 101 Web Socket Protocol Handshake", action); +#else + response[0].NotEqualsDo("HTTP/1.1 101 WebSocket Protocol Handshake", action); +#endif response[1].NotEqualsDo("Upgrade: WebSocket", action); response[2].NotEqualsDo("Connection: Upgrade", action); for (int i = 3; i < response.Length; i++) { +#if !CHALLENGE if (response[i].Contains("WebSocket-Protocol:")) -// if (response[i].Contains("Sec-WebSocket-Protocol:")) +#else + if (response[i].Contains("Sec-WebSocket-Protocol:")) +#endif { int j = response[i].IndexOf(":"); protocol = response[i].Substring(j + 1).Trim(); @@ -315,10 +353,39 @@ namespace WebSocketSharp #if DEBUG Console.WriteLine("WS: Info @doHandshake: Sub protocol: {0}", protocol); #endif +#if CHALLENGE + string expectedResHexStr = BitConverter.ToString(expectedRes); + string actualResHexStr = BitConverter.ToString(actualRes); + actualResHexStr.NotEqualsDo(expectedResHexStr, (a, b) => + { + Console.WriteLine("WS: Error @doHandshake: Invalid challenge response."); + Console.WriteLine("\texpected: {0}", b); + Console.WriteLine("\tactual : {0}", a); + throw new IOException("Invalid challenge response: " + a); + } + ); + #if DEBUG + Console.WriteLine("WS: Info @doHandshake: challenge response: {0}", actualResHexStr); + #endif +#endif ReadyState = WsState.OPEN; } + private byte[] createExpectedRes(uint key1, uint key2, byte[] key3) + { + byte[] key1Bytes = BitConverter.GetBytes(key1); + byte[] key2Bytes = BitConverter.GetBytes(key2); + + Array.Reverse(key1Bytes); + Array.Reverse(key2Bytes); + + byte[] concatKeys = key1Bytes.Concat(key2Bytes).Concat(key3).ToArray(); + + MD5 md5 = MD5.Create(); + return md5.ComputeHash(concatKeys); + } + private void message() { #if DEBUG diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll b/websocket-sharp/bin/Debug/websocket-sharp.dll index 2d822e8d..709ca57d 100755 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll and b/websocket-sharp/bin/Debug/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb index c4d7b185..cc7980ce 100644 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll index 5a8e6cd9..8af4fa1f 100755 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index aa91a37d..5f51c80e 100644 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Release/websocket-sharp.dll b/websocket-sharp/bin/Release/websocket-sharp.dll index 012e365b..022c9957 100755 Binary files a/websocket-sharp/bin/Release/websocket-sharp.dll and b/websocket-sharp/bin/Release/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll index 3844a3cd..fa19e1b4 100755 Binary files a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/websocket-sharp.csproj b/websocket-sharp/websocket-sharp.csproj index 98f67fdc..ab6fb5c3 100644 --- a/websocket-sharp/websocket-sharp.csproj +++ b/websocket-sharp/websocket-sharp.csproj @@ -16,7 +16,7 @@ full false bin\Debug - DEBUG + DEBUG,CHALLENGE prompt 4 false @@ -34,7 +34,7 @@ full false bin\Debug_Ubuntu - DEBUG + DEBUG,CHALLENGE prompt 4 false diff --git a/websocket-sharp/websocket-sharp.pidb b/websocket-sharp/websocket-sharp.pidb index a5553774..af744ce5 100644 Binary files a/websocket-sharp/websocket-sharp.pidb and b/websocket-sharp/websocket-sharp.pidb differ diff --git a/wsclient/bin/Debug/websocket-sharp.dll b/wsclient/bin/Debug/websocket-sharp.dll index 2d822e8d..709ca57d 100755 Binary files a/wsclient/bin/Debug/websocket-sharp.dll and b/wsclient/bin/Debug/websocket-sharp.dll differ diff --git a/wsclient/bin/Debug/websocket-sharp.dll.mdb b/wsclient/bin/Debug/websocket-sharp.dll.mdb index c4d7b185..cc7980ce 100644 Binary files a/wsclient/bin/Debug/websocket-sharp.dll.mdb and b/wsclient/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/wsclient/bin/Debug/wsclient.exe b/wsclient/bin/Debug/wsclient.exe index 01d320cb..e5d37a65 100755 Binary files a/wsclient/bin/Debug/wsclient.exe and b/wsclient/bin/Debug/wsclient.exe differ diff --git a/wsclient/bin/Debug/wsclient.exe.mdb b/wsclient/bin/Debug/wsclient.exe.mdb index a4789812..15ee5a33 100644 Binary files a/wsclient/bin/Debug/wsclient.exe.mdb and b/wsclient/bin/Debug/wsclient.exe.mdb differ diff --git a/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll b/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll index 5a8e6cd9..8af4fa1f 100755 Binary files a/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll and b/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index aa91a37d..5f51c80e 100644 Binary files a/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/wsclient/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/wsclient/bin/Debug_Ubuntu/wsclient.exe b/wsclient/bin/Debug_Ubuntu/wsclient.exe index d7ae3e72..cca0a0cc 100755 Binary files a/wsclient/bin/Debug_Ubuntu/wsclient.exe and b/wsclient/bin/Debug_Ubuntu/wsclient.exe differ diff --git a/wsclient/bin/Debug_Ubuntu/wsclient.exe.mdb b/wsclient/bin/Debug_Ubuntu/wsclient.exe.mdb index 3019a68a..047b062e 100644 Binary files a/wsclient/bin/Debug_Ubuntu/wsclient.exe.mdb and b/wsclient/bin/Debug_Ubuntu/wsclient.exe.mdb differ diff --git a/wsclient/bin/Release/websocket-sharp.dll b/wsclient/bin/Release/websocket-sharp.dll index 012e365b..022c9957 100755 Binary files a/wsclient/bin/Release/websocket-sharp.dll and b/wsclient/bin/Release/websocket-sharp.dll differ diff --git a/wsclient/bin/Release/wsclient.exe b/wsclient/bin/Release/wsclient.exe index cbffe9bc..881580e6 100755 Binary files a/wsclient/bin/Release/wsclient.exe and b/wsclient/bin/Release/wsclient.exe differ diff --git a/wsclient/bin/Release_Ubuntu/websocket-sharp.dll b/wsclient/bin/Release_Ubuntu/websocket-sharp.dll index 3844a3cd..fa19e1b4 100755 Binary files a/wsclient/bin/Release_Ubuntu/websocket-sharp.dll and b/wsclient/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/wsclient/bin/Release_Ubuntu/wsclient.exe b/wsclient/bin/Release_Ubuntu/wsclient.exe index 3e36cff1..57263711 100755 Binary files a/wsclient/bin/Release_Ubuntu/wsclient.exe and b/wsclient/bin/Release_Ubuntu/wsclient.exe differ