summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_ntlm_web_auth.js
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/unit/test_ntlm_web_auth.js')
-rw-r--r--netwerk/test/unit/test_ntlm_web_auth.js249
1 files changed, 249 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_ntlm_web_auth.js b/netwerk/test/unit/test_ntlm_web_auth.js
new file mode 100644
index 0000000000..a4493e2504
--- /dev/null
+++ b/netwerk/test/unit/test_ntlm_web_auth.js
@@ -0,0 +1,249 @@
+// Unit tests for a NTLM authenticated web server.
+//
+// Currently the tests do not determine whether the Authentication dialogs have
+// been displayed.
+//
+
+"use strict";
+
+const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
+
+XPCOMUtils.defineLazyGetter(this, "URL", function () {
+ return "http://localhost:" + httpserver.identity.primaryPort;
+});
+
+function AuthPrompt() {}
+
+AuthPrompt.prototype = {
+ user: "guest",
+ pass: "guest",
+
+ QueryInterface: ChromeUtils.generateQI(["nsIAuthPrompt2"]),
+
+ promptAuth: function ap_promptAuth(channel, level, authInfo) {
+ authInfo.username = this.user;
+ authInfo.password = this.pass;
+
+ return true;
+ },
+
+ asyncPromptAuth: function ap_async(chan, cb, ctx, lvl, info) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
+ },
+};
+
+function Requestor() {}
+
+Requestor.prototype = {
+ QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor"]),
+
+ getInterface: function requestor_gi(iid) {
+ if (iid.equals(Ci.nsIAuthPrompt2)) {
+ // Allow the prompt to store state by caching it here
+ if (!this.prompt) {
+ this.prompt = new AuthPrompt();
+ }
+ return this.prompt;
+ }
+
+ throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
+ },
+
+ prompt: null,
+};
+
+function makeChan(url, loadingUrl) {
+ var principal = Services.scriptSecurityManager.createContentPrincipal(
+ Services.io.newURI(loadingUrl),
+ {}
+ );
+ return NetUtil.newChannel({
+ uri: url,
+ loadingPrincipal: principal,
+ securityFlags: Ci.nsILoadInfo.SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
+ contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
+ });
+}
+
+function TestListener() {}
+TestListener.prototype.onStartRequest = function (request, context) {
+ // Need to do the instanceof to allow request.responseStatus
+ // to be read.
+ if (!(request instanceof Ci.nsIHttpChannel)) {
+ dump("Expecting an HTTP channel");
+ }
+
+ Assert.equal(expectedResponse, request.responseStatus, "HTTP Status code");
+};
+TestListener.prototype.onStopRequest = function (request, context, status) {
+ Assert.equal(expectedRequests, requestsMade, "Number of requests made ");
+
+ if (current_test < tests.length - 1) {
+ current_test++;
+ tests[current_test]();
+ } else {
+ do_test_pending();
+ httpserver.stop(do_test_finished);
+ }
+
+ do_test_finished();
+};
+TestListener.prototype.onDataAvaiable = function (
+ request,
+ context,
+ stream,
+ offset,
+ count
+) {
+ read_stream(stream, count);
+};
+
+// NTLM Messages, for the received type 1 and 3 messages only check that they
+// are of the expected type.
+const NTLM_TYPE1_PREFIX = "NTLM TlRMTVNTUAABAAAA";
+const NTLM_TYPE2_PREFIX = "NTLM TlRMTVNTUAACAAAA";
+const NTLM_TYPE3_PREFIX = "NTLM TlRMTVNTUAADAAAA";
+const NTLM_PREFIX_LEN = 21;
+
+const NTLM_CHALLENGE =
+ NTLM_TYPE2_PREFIX +
+ "DAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAAR" +
+ "ABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUg" +
+ "BWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwB" +
+ "lAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=";
+
+// Web server responses for the happy path scenario.
+// i.e. successful web server auth
+//
+function successfulAuth(metadata, response) {
+ let authorization;
+ let authPrefix;
+ switch (requestsMade) {
+ case 0:
+ // Web Server - Initial request
+ // Will respond with a 401 to start web server auth sequence
+ response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
+ response.setHeader("WWW-Authenticate", "NTLM", false);
+ break;
+ case 1:
+ // Web Server - Expecting a type 1 negotiate message from the client
+ authorization = metadata.getHeader("Authorization");
+ authPrefix = authorization.substring(0, NTLM_PREFIX_LEN);
+ Assert.equal(NTLM_TYPE1_PREFIX, authPrefix, "Expecting a Type 1 message");
+ response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
+ response.setHeader("WWW-Authenticate", NTLM_CHALLENGE, false);
+ break;
+ case 2:
+ // Web Server - Expecting a type 3 Authenticate message from the client
+ authorization = metadata.getHeader("Authorization");
+ authPrefix = authorization.substring(0, NTLM_PREFIX_LEN);
+ Assert.equal(NTLM_TYPE3_PREFIX, authPrefix, "Expecting a Type 3 message");
+ response.setStatusLine(metadata.httpVersion, 200, "Successful");
+ break;
+ default:
+ // We should be authenticated and further requests are permitted
+ authorization = metadata.getHeader("Authorization");
+ Assert.isnull(authorization);
+ response.setStatusLine(metadata.httpVersion, 200, "Successful");
+ }
+ requestsMade++;
+}
+
+// web server responses simulating an unsuccessful web server auth
+function failedAuth(metadata, response) {
+ let authorization;
+ let authPrefix;
+ switch (requestsMade) {
+ case 0:
+ // Web Server - First request return a 401 to start auth sequence
+ response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
+ response.setHeader("WWW-Authenticate", "NTLM", false);
+ break;
+ case 1:
+ // Web Server - Expecting a type 1 negotiate message from the client
+ authorization = metadata.getHeader("Authorization");
+ authPrefix = authorization.substring(0, NTLM_PREFIX_LEN);
+ Assert.equal(NTLM_TYPE1_PREFIX, authPrefix, "Expecting a Type 1 message");
+ response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
+ response.setHeader("WWW-Authenticate", NTLM_CHALLENGE, false);
+ break;
+ case 2:
+ // Web Server - Expecting a type 3 Authenticate message from the client
+ // Respond with a 401 to restart the auth sequence.
+ authorization = metadata.getHeader("Authorization");
+ authPrefix = authorization.substring(0, NTLM_PREFIX_LEN);
+ Assert.equal(NTLM_TYPE3_PREFIX, authPrefix, "Expecting a Type 1 message");
+ response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
+ break;
+ default:
+ // We should not get called past step 2
+ // Strictly speaking the connection should not be used again
+ // commented out for testing
+ // dump( "ERROR: NTLM Auth failed connection should not be reused");
+ //Assert.fail();
+ response.setHeader("WWW-Authenticate", "NTLM", false);
+ }
+ requestsMade++;
+}
+
+var tests = [test_happy_path, test_failed_auth];
+var current_test = 0;
+
+var httpserver = null;
+function run_test() {
+ httpserver = new HttpServer();
+ httpserver.start(-1);
+
+ tests[0]();
+}
+
+var expectedRequests = 0; // Number of HTTP requests that are expected
+var requestsMade = 0; // The number of requests that were made
+var expectedResponse = 0; // The response code
+// Note that any test failures in the HTTP handler
+// will manifest as a 500 response code
+
+// Common test setup
+// Parameters:
+// path - path component of the URL
+// handler - http handler function for the httpserver
+// requests - expected number oh http requests
+// response - expected http response code
+// clearCache - clear the authentication cache before running the test
+function setupTest(path, handler, requests, response, clearCache) {
+ requestsMade = 0;
+ expectedRequests = requests;
+ expectedResponse = response;
+
+ // clear the auth cache if requested
+ if (clearCache) {
+ dump("Clearing auth cache");
+ Cc["@mozilla.org/network/http-auth-manager;1"]
+ .getService(Ci.nsIHttpAuthManager)
+ .clearAll();
+ }
+
+ var chan = makeChan(URL + path, URL);
+ httpserver.registerPathHandler(path, handler);
+ chan.notificationCallbacks = new Requestor();
+ chan.asyncOpen(new TestListener());
+
+ return chan;
+}
+
+// Happy code path
+// Succesful web server auth.
+function test_happy_path() {
+ dump("RUNNING TEST: test_happy_path");
+ setupTest("/auth", successfulAuth, 3, 200, 1);
+
+ do_test_pending();
+}
+
+// Unsuccessful web server sign on
+function test_failed_auth() {
+ dump("RUNNING TEST: test_failed_auth");
+ setupTest("/auth", failedAuth, 3, 401, 1);
+
+ do_test_pending();
+}