Chromium Code Reviews| Index: tests/standalone/io/http_proxy_test.dart |
| diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart |
| index 197b11a3dbd410969e8b8aea1968e39b748f5ef8..e1e66f0a4113c7431b121d7d1297c1810101f9da 100644 |
| --- a/tests/standalone/io/http_proxy_test.dart |
| +++ b/tests/standalone/io/http_proxy_test.dart |
| @@ -80,21 +80,65 @@ class ProxyServer { |
| HttpServer server; |
| HttpClient client; |
| int requestCount = 0; |
| + String authScheme; |
| + String realm = "test"; |
| String username; |
| String password; |
| + var ha1; |
| + String serverAlgorithm = "MD5"; |
| + String serverQop = "auth"; |
| + Set ncs = new Set(); |
| + |
| + var nonce = "12345678"; // No need for random nonce in test. |
| + |
| ProxyServer() : client = new HttpClient(); |
| - authenticationRequired(request) { |
| + void useBasicAuthentication(String username, String password) { |
| + this.username = username; |
| + this.password = password; |
| + authScheme = "Basic"; |
| + } |
| + |
| + void useDigestAuthentication(String username, String password) { |
| + this.username = username; |
| + this.password = password; |
| + authScheme = "Digest"; |
| + |
| + // Calculate ha1. |
| + var hasher = new MD5(); |
| + hasher.add("${username}:${realm}:${password}".codeUnits); |
| + ha1 = CryptoUtils.bytesToHex(hasher.close()); |
| + } |
| + |
| + basicAuthenticationRequired(request) { |
| request.fold(null, (x, y) {}).then((_) { |
| var response = request.response; |
| response.headers.set(HttpHeaders.PROXY_AUTHENTICATE, |
| - "Basic, realm=realm"); |
| + "Basic, realm=$realm"); |
| response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED; |
| response.close(); |
| }); |
| } |
| + digestAuthenticationRequired(request, {stale: false}) { |
| + request.fold(null, (x, y) {}).then((_) { |
| + var response = request.response; |
| + response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED; |
| + StringBuffer authHeader = new StringBuffer(); |
| + authHeader.write('Digest'); |
| + authHeader.write(', realm="$realm"'); |
| + authHeader.write(', nonce="$nonce"'); |
| + if (stale) authHeader.write(', stale="true"'); |
| + if (serverAlgorithm != null) { |
| + authHeader.write(', algorithm=$serverAlgorithm'); |
| + } |
| + if (serverQop != null) authHeader.write(', qop="$serverQop"'); |
| + response.headers.set(HttpHeaders.PROXY_AUTHENTICATE, authHeader); |
| + response.close(); |
| + }); |
| + } |
| + |
| Future<ProxyServer> start() { |
| var x = new Completer(); |
| HttpServer.bind("localhost", 0).then((s) { |
| @@ -104,20 +148,74 @@ class ProxyServer { |
| requestCount++; |
| if (username != null && password != null) { |
| if (request.headers[HttpHeaders.PROXY_AUTHORIZATION] == null) { |
| - authenticationRequired(request); |
| + if (authScheme == "Digest") { |
| + digestAuthenticationRequired(request); |
| + } else { |
| + basicAuthenticationRequired(request); |
| + } |
| return; |
| } else { |
| Expect.equals( |
| 1, request.headers[HttpHeaders.PROXY_AUTHORIZATION].length); |
| String authorization = |
| request.headers[HttpHeaders.PROXY_AUTHORIZATION][0]; |
| - List<String> tokens = authorization.split(" "); |
| - Expect.equals("Basic", tokens[0]); |
| - String auth = |
| - CryptoUtils.bytesToBase64(encodeUtf8("$username:$password")); |
| - if (auth != tokens[1]) { |
| - authenticationRequired(request); |
| - return; |
| + if (authScheme == "Basic") { |
| + List<String> tokens = authorization.split(" "); |
| + Expect.equals("Basic", tokens[0]); |
| + String auth = |
| + CryptoUtils.bytesToBase64(encodeUtf8("$username:$password")); |
| + if (auth != tokens[1]) { |
| + authenticationRequired(request); |
| + return; |
| + } |
| + } else { |
| + HeaderValue header = |
| + HeaderValue.parse( |
| + authorization, parameterSeparator: ","); |
| + Expect.equals("Digest", header.value); |
| + var uri = header.parameters["uri"]; |
| + var qop = header.parameters["qop"]; |
| + var cnonce = header.parameters["cnonce"]; |
| + var nc = header.parameters["nc"]; |
| + Expect.equals(username, header.parameters["username"]); |
| + Expect.equals(realm, header.parameters["realm"]); |
| + Expect.equals("MD5", header.parameters["algorithm"]); |
| + Expect.equals(nonce, header.parameters["nonce"]); |
| + Expect.equals(request.uri.toString(), uri); |
| + if (qop != null) { |
| + // A server qop of auth-int is downgraded to none by the client. |
| + Expect.equals("auth", serverQop); |
| + Expect.equals("auth", header.parameters["qop"]); |
| + Expect.isNotNull(cnonce); |
| + Expect.isNotNull(nc); |
| + Expect.isFalse(ncs.contains(nc)); |
| + ncs.add(nc); |
| + } else { |
| + Expect.isNull(cnonce); |
| + Expect.isNull(nc); |
| + } |
| + Expect.isNotNull(header.parameters["response"]); |
| + |
| + var hasher = new MD5(); |
| + hasher.add("${request.method}:${uri}".codeUnits); |
| + var ha2 = CryptoUtils.bytesToHex(hasher.close()); |
| + |
| + var x; |
| + hasher = new MD5(); |
| + if (qop == null || qop == "" || qop == "none") { |
| + hasher.add("$ha1:${nonce}:$ha2".codeUnits); |
| + } else { |
| + hasher.add("$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits); |
|
Anders Johnsen
2013/05/07 13:23:58
Nit: long line.
|
| + } |
| + Expect.equals(CryptoUtils.bytesToHex(hasher.close()), |
| + header.parameters["response"]); |
| + |
| + // Add a bogus Proxy-Authentication-Info for testing. |
| + var info = 'rspauth="77180d1ab3d6c9de084766977790f482", ' |
| + 'cnonce="8f971178", ' |
| + 'nc=000002c74, ' |
| + 'qop=auth'; |
| + request.response.headers.set("Proxy-Authentication-Info", info); |
| } |
| } |
| } |
| @@ -412,10 +510,11 @@ void testProxyFromEnviroment() { |
| int testProxyAuthenticateCount = 0; |
| -void testProxyAuthenticate() { |
| +Future testProxyAuthenticate(bool useDigestAuthentication) { |
| + testProxyAuthenticateCount = 0; |
| + var completer = new Completer(); |
| + |
| setupProxyServer().then((proxyServer) { |
| - proxyServer.username = "test"; |
| - proxyServer.password = "test"; |
| setupServer(1).then((server) { |
| setupServer(1, secure: true).then((secureServer) { |
| HttpClient client = new HttpClient(); |
| @@ -423,6 +522,12 @@ void testProxyAuthenticate() { |
| Completer step1 = new Completer(); |
| Completer step2 = new Completer(); |
| + if (useDigestAuthentication) { |
| + proxyServer.useDigestAuthentication("test", "test"); |
| + } else { |
| + proxyServer.useBasicAuthentication("test", "test"); |
| + } |
| + |
| // Test with no authentication. |
| client.findProxy = (Uri uri) { |
| return "PROXY localhost:${proxyServer.port}"; |
| @@ -459,15 +564,25 @@ void testProxyAuthenticate() { |
| } |
| step1.future.then((_) { |
| testProxyAuthenticateCount = 0; |
| - client.findProxy = (Uri uri) { |
| - return "PROXY test:test@localhost:${proxyServer.port}"; |
| - }; |
| + if (useDigestAuthentication) { |
| + client.findProxy = (Uri uri) => "PROXY localhost:${proxyServer.port}"; |
| + client.addProxyCredentials( |
| + "localhost", |
| + proxyServer.port, |
| + "test", |
| + new HttpClientDigestCredentials("test", "test")); |
|
Anders Johnsen
2013/05/07 13:23:58
make user and pass not equal (here and other place
|
| + } else { |
| + client.findProxy = (Uri uri) { |
| + return "PROXY test:test@localhost:${proxyServer.port}"; |
| + }; |
| + } |
| for (int i = 0; i < loopCount; i++) { |
| test(bool secure) { |
| + var path = useDigestAuthentication ? "A" : "$i"; |
| String url = secure |
| - ? "https://localhost:${secureServer.port}/$i" |
| - : "http://localhost:${server.port}/$i"; |
| + ? "https://localhost:${secureServer.port}/$path" |
| + : "http://localhost:${server.port}/$path"; |
| client.postUrl(Uri.parse(url)) |
| .then((HttpClientRequest clientRequest) { |
| @@ -531,6 +646,7 @@ void testProxyAuthenticate() { |
| server.shutdown(); |
| secureServer.shutdown(); |
| client.close(); |
| + completer.complete(null); |
| } |
| }); |
| }); |
| @@ -543,6 +659,8 @@ void testProxyAuthenticate() { |
| }); |
| }); |
| }); |
| + |
| + return completer.future; |
| } |
| int testRealProxyDoneCount = 0; |
| @@ -639,7 +757,10 @@ main() { |
| testProxy(); |
| testProxyChain(); |
| testProxyFromEnviroment(); |
| - testProxyAuthenticate(); |
| + // The two invocations of uses the same global variable for state - |
| + // run one after the other. |
| + testProxyAuthenticate(false) |
| + .then((_) => testProxyAuthenticate(true)); |
| // This test is not normally run. It can be used for locally testing |
| // with a real proxy server (e.g. Apache). |
| //testRealProxy(); |