22
22
import java .net .Socket ;
23
23
import java .net .URI ;
24
24
import java .security .KeyManagementException ;
25
+ import java .security .MessageDigest ;
25
26
import java .security .NoSuchAlgorithmException ;
26
27
import java .util .List ;
27
28
@@ -69,6 +70,8 @@ public void connect() {
69
70
@ Override
70
71
public void run () {
71
72
try {
73
+ String secret = createSecret ();
74
+
72
75
int port = (mURI .getPort () != -1 ) ? mURI .getPort () : (mURI .getScheme ().equals ("wss" ) ? 443 : 80 );
73
76
74
77
String path = TextUtils .isEmpty (mURI .getPath ()) ? "/" : mURI .getPath ();
@@ -88,7 +91,7 @@ public void run() {
88
91
out .print ("Connection: Upgrade\r \n " );
89
92
out .print ("Host: " + mURI .getHost () + "\r \n " );
90
93
out .print ("Origin: " + origin .toString () + "\r \n " );
91
- out .print ("Sec-WebSocket-Key: " + createSecret () + "\r \n " );
94
+ out .print ("Sec-WebSocket-Key: " + secret + "\r \n " );
92
95
out .print ("Sec-WebSocket-Version: 13\r \n " );
93
96
if (mExtraHeaders != null ) {
94
97
for (NameValuePair pair : mExtraHeaders ) {
@@ -110,13 +113,26 @@ public void run() {
110
113
111
114
// Read HTTP response headers.
112
115
String line ;
116
+ boolean validated = false ;
117
+
113
118
while (!TextUtils .isEmpty (line = readLine (stream ))) {
114
119
Header header = parseHeader (line );
115
120
if (header .getName ().equals ("Sec-WebSocket-Accept" )) {
116
- // FIXME: Verify the response...
121
+ String expected = createSecretValidation (secret );
122
+ String actual = header .getValue ().trim ();
123
+
124
+ if (!expected .equals (actual )) {
125
+ throw new HttpException ("Bad Sec-WebSocket-Accept header value." );
126
+ }
127
+
128
+ validated = true ;
117
129
}
118
130
}
119
131
132
+ if (!validated ) {
133
+ throw new HttpException ("No Sec-WebSocket-Accept header." );
134
+ }
135
+
120
136
mListener .onConnect ();
121
137
122
138
// Now decode websocket frames.
@@ -203,6 +219,16 @@ private String createSecret() {
203
219
return Base64 .encodeToString (nonce , Base64 .DEFAULT ).trim ();
204
220
}
205
221
222
+ private String createSecretValidation (String secret ) {
223
+ try {
224
+ MessageDigest md = MessageDigest .getInstance ("SHA-1" );
225
+ md .update ((secret + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ).getBytes ());
226
+ return Base64 .encodeToString (md .digest (), Base64 .DEFAULT ).trim ();
227
+ } catch (NoSuchAlgorithmException e ) {
228
+ throw new RuntimeException (e );
229
+ }
230
+ }
231
+
206
232
void sendFrame (final byte [] frame ) {
207
233
mHandler .post (new Runnable () {
208
234
@ Override
0 commit comments