2006-07-27 03:10:48 +04:00
|
|
|
// This file tests authentication prompt callbacks
|
2010-02-12 19:55:11 +03:00
|
|
|
// TODO NIT use do_check_eq(expected, actual) consistently, not sometimes eq(actual, expected)
|
2006-07-27 03:10:48 +04:00
|
|
|
|
2018-01-30 02:20:18 +03:00
|
|
|
ChromeUtils.import("resource://testing-common/httpd.js");
|
|
|
|
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
2006-12-15 05:13:54 +03:00
|
|
|
|
2018-08-07 06:00:00 +03:00
|
|
|
Cu.importGlobalProperties(["XMLHttpRequest"]);
|
|
|
|
|
2015-04-01 13:56:00 +03:00
|
|
|
// Turn off the authentication dialog blocking for this test.
|
|
|
|
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
|
|
|
getService(Ci.nsIPrefBranch);
|
2015-09-08 18:21:19 +03:00
|
|
|
prefs.setIntPref("network.auth.subresource-http-auth-allow", 2);
|
2015-04-01 13:56:00 +03:00
|
|
|
|
2013-07-19 21:19:28 +04:00
|
|
|
XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
|
|
|
return "http://localhost:" + httpserv.identity.primaryPort;
|
|
|
|
});
|
|
|
|
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "PORT", function() {
|
|
|
|
return httpserv.identity.primaryPort;
|
|
|
|
});
|
|
|
|
|
2006-08-02 01:47:04 +04:00
|
|
|
const FLAG_RETURN_FALSE = 1 << 0;
|
|
|
|
const FLAG_WRONG_PASSWORD = 1 << 1;
|
2010-02-12 19:55:11 +03:00
|
|
|
const FLAG_BOGUS_USER = 1 << 2;
|
|
|
|
const FLAG_PREVIOUS_FAILED = 1 << 3;
|
2016-06-06 02:06:00 +03:00
|
|
|
const CROSS_ORIGIN = 1 << 4;
|
2017-02-17 18:44:36 +03:00
|
|
|
const FLAG_NO_REALM = 1 << 5;
|
2017-12-07 02:31:00 +03:00
|
|
|
const FLAG_NON_ASCII_USER_PASSWORD = 1 << 6;
|
2006-07-27 03:10:48 +04:00
|
|
|
|
2018-02-28 20:51:33 +03:00
|
|
|
const nsIAuthPrompt2 = Ci.nsIAuthPrompt2;
|
|
|
|
const nsIAuthInformation = Ci.nsIAuthInformation;
|
2006-08-27 01:42:54 +04:00
|
|
|
|
2006-12-15 05:13:54 +03:00
|
|
|
|
2006-08-02 01:47:04 +04:00
|
|
|
function AuthPrompt1(flags) {
|
|
|
|
this.flags = flags;
|
|
|
|
}
|
2006-07-27 03:10:48 +04:00
|
|
|
|
|
|
|
AuthPrompt1.prototype = {
|
|
|
|
user: "guest",
|
|
|
|
pass: "guest",
|
|
|
|
|
|
|
|
expectedRealm: "secret",
|
|
|
|
|
|
|
|
QueryInterface: function authprompt_qi(iid) {
|
2018-02-28 20:51:33 +03:00
|
|
|
if (iid.equals(Ci.nsISupports) ||
|
|
|
|
iid.equals(Ci.nsIAuthPrompt))
|
2006-07-27 03:10:48 +04:00
|
|
|
return this;
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
2006-07-27 03:10:48 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
prompt: function ap1_prompt(title, text, realm, save, defaultText, result) {
|
|
|
|
do_throw("unexpected prompt call");
|
|
|
|
},
|
|
|
|
|
|
|
|
promptUsernameAndPassword:
|
|
|
|
function ap1_promptUP(title, text, realm, savePW, user, pw)
|
|
|
|
{
|
2017-02-17 18:44:36 +03:00
|
|
|
if (this.flags & FLAG_NO_REALM) {
|
|
|
|
// Note that the realm here isn't actually the realm. it's a pw mgr key.
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(URL + " (" + this.expectedRealm + ")", realm);
|
2017-02-17 18:44:36 +03:00
|
|
|
}
|
2016-06-06 02:06:00 +03:00
|
|
|
if (!(this.flags & CROSS_ORIGIN)) {
|
2018-02-01 22:45:22 +03:00
|
|
|
if (!text.includes(this.expectedRealm)) {
|
2016-06-06 02:06:00 +03:00
|
|
|
do_throw("Text must indicate the realm");
|
|
|
|
}
|
|
|
|
} else {
|
2018-02-01 22:45:22 +03:00
|
|
|
if (text.includes(this.expectedRealm)) {
|
2016-06-06 02:06:00 +03:00
|
|
|
do_throw("There should not be realm for cross origin");
|
|
|
|
}
|
|
|
|
}
|
2018-02-01 22:45:22 +03:00
|
|
|
if (!text.includes("localhost"))
|
2006-07-27 03:10:48 +04:00
|
|
|
do_throw("Text must indicate the hostname");
|
2018-02-01 22:45:22 +03:00
|
|
|
if (!text.includes(String(PORT)))
|
2006-07-27 03:10:48 +04:00
|
|
|
do_throw("Text must indicate the port");
|
2018-02-01 22:45:22 +03:00
|
|
|
if (text.includes("-1"))
|
2006-07-27 03:10:48 +04:00
|
|
|
do_throw("Text must contain negative numbers");
|
|
|
|
|
2006-08-02 01:47:04 +04:00
|
|
|
if (this.flags & FLAG_RETURN_FALSE)
|
|
|
|
return false;
|
|
|
|
|
2017-12-07 02:31:00 +03:00
|
|
|
if (this.flags & FLAG_BOGUS_USER) {
|
2010-02-12 19:55:11 +03:00
|
|
|
this.user = "foo\nbar";
|
2017-12-07 02:31:00 +03:00
|
|
|
} else if (this.flags & FLAG_NON_ASCII_USER_PASSWORD) {
|
|
|
|
this.user = "é";
|
|
|
|
}
|
2010-02-12 19:55:11 +03:00
|
|
|
|
2006-07-27 03:10:48 +04:00
|
|
|
user.value = this.user;
|
2006-08-02 01:47:04 +04:00
|
|
|
if (this.flags & FLAG_WRONG_PASSWORD) {
|
|
|
|
pw.value = this.pass + ".wrong";
|
|
|
|
// Now clear the flag to avoid an infinite loop
|
|
|
|
this.flags &= ~FLAG_WRONG_PASSWORD;
|
2017-12-07 02:31:00 +03:00
|
|
|
} else if (this.flags & FLAG_NON_ASCII_USER_PASSWORD) {
|
|
|
|
pw.value = "é";
|
2006-08-02 01:47:04 +04:00
|
|
|
} else {
|
|
|
|
pw.value = this.pass;
|
|
|
|
}
|
2006-07-27 03:10:48 +04:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
promptPassword: function ap1_promptPW(title, text, realm, save, pwd) {
|
|
|
|
do_throw("unexpected promptPassword call");
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
function AuthPrompt2(flags) {
|
2006-08-02 01:47:04 +04:00
|
|
|
this.flags = flags;
|
2006-07-27 03:10:48 +04:00
|
|
|
}
|
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
AuthPrompt2.prototype = {
|
|
|
|
user: "guest",
|
|
|
|
pass: "guest",
|
|
|
|
|
|
|
|
expectedRealm: "secret",
|
|
|
|
|
|
|
|
QueryInterface: function authprompt2_qi(iid) {
|
2018-02-28 20:51:33 +03:00
|
|
|
if (iid.equals(Ci.nsISupports) ||
|
|
|
|
iid.equals(Ci.nsIAuthPrompt2))
|
2006-08-27 01:42:54 +04:00
|
|
|
return this;
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
2006-08-27 01:42:54 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
promptAuth:
|
|
|
|
function ap2_promptAuth(channel, level, authInfo)
|
|
|
|
{
|
2018-02-01 22:45:22 +03:00
|
|
|
var isNTLM = channel.URI.pathQueryRef.includes("ntlm");
|
|
|
|
var isDigest = channel.URI.pathQueryRef.includes("digest");
|
2006-08-27 01:42:54 +04:00
|
|
|
|
2017-02-17 18:44:36 +03:00
|
|
|
if (isNTLM || (this.flags & FLAG_NO_REALM)) {
|
2006-08-27 01:42:54 +04:00
|
|
|
this.expectedRealm = ""; // NTLM knows no realms
|
2017-02-17 18:44:36 +03:00
|
|
|
}
|
2006-08-27 01:42:54 +04:00
|
|
|
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(this.expectedRealm, authInfo.realm);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
2007-05-04 07:31:30 +04:00
|
|
|
var expectedLevel = (isNTLM || isDigest) ?
|
2006-09-06 03:47:30 +04:00
|
|
|
nsIAuthPrompt2.LEVEL_PW_ENCRYPTED :
|
|
|
|
nsIAuthPrompt2.LEVEL_NONE;
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(expectedLevel, level);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
var expectedFlags = nsIAuthInformation.AUTH_HOST;
|
|
|
|
|
2010-02-12 19:55:11 +03:00
|
|
|
if (this.flags & FLAG_PREVIOUS_FAILED)
|
|
|
|
expectedFlags |= nsIAuthInformation.PREVIOUS_FAILED;
|
|
|
|
|
2016-06-06 02:06:00 +03:00
|
|
|
if (this.flags & CROSS_ORIGIN)
|
|
|
|
expectedFlags |= nsIAuthInformation.CROSS_ORIGIN_SUB_RESOURCE;
|
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
if (isNTLM)
|
|
|
|
expectedFlags |= nsIAuthInformation.NEED_DOMAIN;
|
|
|
|
|
2017-12-07 02:31:00 +03:00
|
|
|
const kAllKnownFlags = 127; // Don't fail test for newly added flags
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(expectedFlags, authInfo.flags & kAllKnownFlags);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
2007-05-04 07:31:30 +04:00
|
|
|
var expectedScheme = isNTLM ? "ntlm" : isDigest ? "digest" : "basic";
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(expectedScheme, authInfo.authenticationScheme);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
// No passwords in the URL -> nothing should be prefilled
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(authInfo.username, "");
|
|
|
|
Assert.equal(authInfo.password, "");
|
|
|
|
Assert.equal(authInfo.domain, "");
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
if (this.flags & FLAG_RETURN_FALSE)
|
2010-02-12 19:55:11 +03:00
|
|
|
{
|
|
|
|
this.flags |= FLAG_PREVIOUS_FAILED;
|
2006-08-27 01:42:54 +04:00
|
|
|
return false;
|
2010-02-12 19:55:11 +03:00
|
|
|
}
|
|
|
|
|
2017-12-07 02:31:00 +03:00
|
|
|
if (this.flags & FLAG_BOGUS_USER) {
|
2010-02-12 19:55:11 +03:00
|
|
|
this.user = "foo\nbar";
|
2017-12-07 02:31:00 +03:00
|
|
|
} else if (this.flags & FLAG_NON_ASCII_USER_PASSWORD) {
|
|
|
|
this.user = "é";
|
|
|
|
}
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
authInfo.username = this.user;
|
|
|
|
if (this.flags & FLAG_WRONG_PASSWORD) {
|
|
|
|
authInfo.password = this.pass + ".wrong";
|
2010-02-12 19:55:11 +03:00
|
|
|
this.flags |= FLAG_PREVIOUS_FAILED;
|
2006-08-27 01:42:54 +04:00
|
|
|
// Now clear the flag to avoid an infinite loop
|
|
|
|
this.flags &= ~FLAG_WRONG_PASSWORD;
|
2017-12-07 02:31:00 +03:00
|
|
|
} else if (this.flags & FLAG_NON_ASCII_USER_PASSWORD) {
|
|
|
|
authInfo.password = "é";
|
2006-08-27 01:42:54 +04:00
|
|
|
} else {
|
|
|
|
authInfo.password = this.pass;
|
2010-02-12 19:55:11 +03:00
|
|
|
this.flags &= ~FLAG_PREVIOUS_FAILED;
|
2006-08-27 01:42:54 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
asyncPromptAuth: function ap2_async(chan, cb, ctx, lvl, info) {
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
2006-08-27 01:42:54 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-02-12 19:55:11 +03:00
|
|
|
function Requestor(flags, versions) {
|
2006-08-27 01:42:54 +04:00
|
|
|
this.flags = flags;
|
|
|
|
this.versions = versions;
|
|
|
|
}
|
|
|
|
|
2006-07-27 03:10:48 +04:00
|
|
|
Requestor.prototype = {
|
|
|
|
QueryInterface: function requestor_qi(iid) {
|
2018-02-28 20:51:33 +03:00
|
|
|
if (iid.equals(Ci.nsISupports) ||
|
|
|
|
iid.equals(Ci.nsIInterfaceRequestor))
|
2006-07-27 03:10:48 +04:00
|
|
|
return this;
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
2006-07-27 03:10:48 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
getInterface: function requestor_gi(iid) {
|
2006-08-27 01:42:54 +04:00
|
|
|
if (this.versions & 1 &&
|
2018-02-28 20:51:33 +03:00
|
|
|
iid.equals(Ci.nsIAuthPrompt)) {
|
2006-08-02 01:47:04 +04:00
|
|
|
// Allow the prompt to store state by caching it here
|
|
|
|
if (!this.prompt1)
|
2010-02-12 19:55:11 +03:00
|
|
|
this.prompt1 = new AuthPrompt1(this.flags);
|
2006-08-02 01:47:04 +04:00
|
|
|
return this.prompt1;
|
|
|
|
}
|
2006-08-27 01:42:54 +04:00
|
|
|
if (this.versions & 2 &&
|
2018-02-28 20:51:33 +03:00
|
|
|
iid.equals(Ci.nsIAuthPrompt2)) {
|
2006-08-27 01:42:54 +04:00
|
|
|
// Allow the prompt to store state by caching it here
|
|
|
|
if (!this.prompt2)
|
2007-05-04 07:31:30 +04:00
|
|
|
this.prompt2 = new AuthPrompt2(this.flags);
|
2006-08-27 01:42:54 +04:00
|
|
|
return this.prompt2;
|
|
|
|
}
|
|
|
|
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
2006-08-02 01:47:04 +04:00
|
|
|
},
|
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
prompt1: null,
|
|
|
|
prompt2: null
|
2006-07-27 03:10:48 +04:00
|
|
|
};
|
|
|
|
|
2007-02-11 03:33:29 +03:00
|
|
|
function RealmTestRequestor() {}
|
|
|
|
|
|
|
|
RealmTestRequestor.prototype = {
|
|
|
|
QueryInterface: function realmtest_qi(iid) {
|
2018-02-28 20:51:33 +03:00
|
|
|
if (iid.equals(Ci.nsISupports) ||
|
|
|
|
iid.equals(Ci.nsIInterfaceRequestor) ||
|
|
|
|
iid.equals(Ci.nsIAuthPrompt2))
|
2007-02-11 03:33:29 +03:00
|
|
|
return this;
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
2007-02-11 03:33:29 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
getInterface: function realmtest_interface(iid) {
|
2018-02-28 20:51:33 +03:00
|
|
|
if (iid.equals(Ci.nsIAuthPrompt2))
|
2007-02-11 03:33:29 +03:00
|
|
|
return this;
|
|
|
|
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
2007-02-11 03:33:29 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
promptAuth: function realmtest_checkAuth(channel, level, authInfo) {
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(authInfo.realm, '\"foo_bar');
|
2007-02-11 03:33:29 +03:00
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
asyncPromptAuth: function realmtest_async(chan, cb, ctx, lvl, info) {
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
2007-02-11 03:33:29 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2006-07-27 03:10:48 +04:00
|
|
|
var listener = {
|
2010-02-12 19:55:11 +03:00
|
|
|
expectedCode: -1, // Uninitialized
|
2006-07-27 03:10:48 +04:00
|
|
|
|
|
|
|
onStartRequest: function test_onStartR(request, ctx) {
|
|
|
|
try {
|
|
|
|
if (!Components.isSuccessCode(request.status))
|
|
|
|
do_throw("Channel should have a success code!");
|
|
|
|
|
2018-02-28 20:51:33 +03:00
|
|
|
if (!(request instanceof Ci.nsIHttpChannel))
|
2006-07-27 03:10:48 +04:00
|
|
|
do_throw("Expecting an HTTP channel");
|
|
|
|
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(request.responseStatus, this.expectedCode);
|
2006-07-27 03:10:48 +04:00
|
|
|
// The request should be succeeded iff we expect 200
|
2017-12-21 13:08:17 +03:00
|
|
|
Assert.equal(request.requestSucceeded, this.expectedCode == 200);
|
2006-07-27 03:10:48 +04:00
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
do_throw("Unexpected exception: " + e);
|
|
|
|
}
|
|
|
|
|
2018-02-28 20:51:33 +03:00
|
|
|
throw Cr.NS_ERROR_ABORT;
|
2006-07-27 03:10:48 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
onDataAvailable: function test_ODA() {
|
|
|
|
do_throw("Should not get any data!");
|
|
|
|
},
|
|
|
|
|
|
|
|
onStopRequest: function test_onStopR(request, ctx, status) {
|
2018-02-28 20:51:33 +03:00
|
|
|
Assert.equal(status, Cr.NS_ERROR_ABORT);
|
2006-07-27 03:10:48 +04:00
|
|
|
|
2018-08-07 06:00:00 +03:00
|
|
|
moveToNextTest();
|
2006-07-27 03:10:48 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-06-06 02:06:00 +03:00
|
|
|
function makeChan(url, loadingUrl) {
|
|
|
|
var ios = Cc["@mozilla.org/network/io-service;1"].
|
|
|
|
getService(Ci.nsIIOService);
|
|
|
|
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
|
|
|
.getService(Ci.nsIScriptSecurityManager);
|
2017-01-09 22:27:26 +03:00
|
|
|
var principal = ssm.createCodebasePrincipal(ios.newURI(loadingUrl), {});
|
2016-06-06 02:06:00 +03:00
|
|
|
return NetUtil.newChannel(
|
|
|
|
{ uri: url, loadingPrincipal: principal,
|
2016-06-07 21:38:48 +03:00
|
|
|
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
2018-02-28 20:51:33 +03:00
|
|
|
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
|
2016-06-06 02:06:00 +03:00
|
|
|
});
|
2006-07-27 03:10:48 +04:00
|
|
|
}
|
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
var tests = [test_noauth, test_returnfalse1, test_wrongpw1, test_prompt1,
|
2016-06-06 02:06:00 +03:00
|
|
|
test_prompt1CrossOrigin, test_prompt2CrossOrigin,
|
2007-02-11 03:33:29 +03:00
|
|
|
test_returnfalse2, test_wrongpw2, test_prompt2, test_ntlm,
|
2017-12-07 02:31:00 +03:00
|
|
|
test_basicrealm, test_nonascii, test_digest_noauth, test_digest,
|
2017-02-17 18:44:36 +03:00
|
|
|
test_digest_bogus_user, test_short_digest, test_large_realm,
|
2018-08-07 06:00:00 +03:00
|
|
|
test_large_domain, test_nonascii_xhr];
|
2007-05-19 01:53:18 +04:00
|
|
|
|
2006-07-27 03:10:48 +04:00
|
|
|
var current_test = 0;
|
|
|
|
|
2006-08-02 06:02:37 +04:00
|
|
|
var httpserv = null;
|
|
|
|
|
2018-08-07 06:00:00 +03:00
|
|
|
function moveToNextTest() {
|
|
|
|
if (current_test < (tests.length - 1)) {
|
|
|
|
// First, gotta clear the auth cache
|
|
|
|
Cc["@mozilla.org/network/http-auth-manager;1"]
|
|
|
|
.getService(Ci.nsIHttpAuthManager)
|
|
|
|
.clearAll();
|
|
|
|
|
|
|
|
current_test++;
|
|
|
|
tests[current_test]();
|
|
|
|
} else {
|
|
|
|
do_test_pending();
|
|
|
|
httpserv.stop(do_test_finished);
|
|
|
|
}
|
|
|
|
|
|
|
|
do_test_finished();
|
|
|
|
}
|
|
|
|
|
2006-07-27 03:10:48 +04:00
|
|
|
function run_test() {
|
2012-08-14 18:06:04 +04:00
|
|
|
httpserv = new HttpServer();
|
2006-12-15 05:13:54 +03:00
|
|
|
|
|
|
|
httpserv.registerPathHandler("/auth", authHandler);
|
|
|
|
httpserv.registerPathHandler("/auth/ntlm/simple", authNtlmSimple);
|
2007-02-11 03:33:29 +03:00
|
|
|
httpserv.registerPathHandler("/auth/realm", authRealm);
|
2017-12-07 02:31:00 +03:00
|
|
|
httpserv.registerPathHandler("/auth/non_ascii", authNonascii);
|
2007-05-04 07:31:30 +04:00
|
|
|
httpserv.registerPathHandler("/auth/digest", authDigest);
|
2017-02-17 18:44:36 +03:00
|
|
|
httpserv.registerPathHandler("/auth/short_digest", authShortDigest);
|
2013-09-26 22:54:59 +04:00
|
|
|
httpserv.registerPathHandler("/largeRealm", largeRealm);
|
|
|
|
httpserv.registerPathHandler("/largeDomain", largeDomain);
|
2006-12-15 05:13:54 +03:00
|
|
|
|
2013-07-19 21:19:28 +04:00
|
|
|
httpserv.start(-1);
|
2006-12-15 05:13:54 +03:00
|
|
|
|
2006-07-27 03:10:48 +04:00
|
|
|
tests[0]();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_noauth() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth", URL);
|
2006-07-27 03:10:48 +04:00
|
|
|
|
2006-08-02 01:47:04 +04:00
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-08-02 01:47:04 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_returnfalse1() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth", URL);
|
2006-08-02 01:47:04 +04:00
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 1);
|
2006-08-02 01:47:04 +04:00
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-08-02 01:47:04 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_wrongpw1() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth", URL);
|
2006-08-02 01:47:04 +04:00
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_WRONG_PASSWORD, 1);
|
2006-08-02 01:47:04 +04:00
|
|
|
listener.expectedCode = 200; // OK
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-07-27 03:10:48 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_prompt1() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth", URL);
|
2006-07-27 03:10:48 +04:00
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
chan.notificationCallbacks = new Requestor(0, 1);
|
|
|
|
listener.expectedCode = 200; // OK
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2016-06-06 02:06:00 +03:00
|
|
|
function test_prompt1CrossOrigin() {
|
|
|
|
var chan = makeChan(URL + "/auth", "http://example.org");
|
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(16, 1);
|
|
|
|
listener.expectedCode = 200; // OK
|
|
|
|
chan.asyncOpen2(listener);
|
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_prompt2CrossOrigin() {
|
|
|
|
var chan = makeChan(URL + "/auth", "http://example.org");
|
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(16, 2);
|
|
|
|
listener.expectedCode = 200; // OK
|
|
|
|
chan.asyncOpen2(listener);
|
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
function test_returnfalse2() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth", URL);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 2);
|
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_wrongpw2() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth", URL);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_WRONG_PASSWORD, 2);
|
|
|
|
listener.expectedCode = 200; // OK
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_prompt2() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth", URL);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(0, 2);
|
2006-07-27 03:10:48 +04:00
|
|
|
listener.expectedCode = 200; // OK
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-07-27 03:10:48 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2006-08-27 01:42:54 +04:00
|
|
|
function test_ntlm() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth/ntlm/simple", URL);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 2);
|
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2006-08-27 01:42:54 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2014-01-25 03:07:37 +04:00
|
|
|
function test_basicrealm() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth/realm", URL);
|
2007-02-11 03:33:29 +03:00
|
|
|
|
|
|
|
chan.notificationCallbacks = new RealmTestRequestor();
|
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2007-02-11 03:33:29 +03:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2017-12-07 02:31:00 +03:00
|
|
|
function test_nonascii() {
|
|
|
|
var chan = makeChan(URL + "/auth/non_ascii", URL);
|
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_NON_ASCII_USER_PASSWORD, 2);
|
|
|
|
listener.expectedCode = 200; // OK
|
|
|
|
chan.asyncOpen2(listener);
|
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2018-08-07 06:00:00 +03:00
|
|
|
function test_nonascii_xhr() {
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.open("GET", URL + "/auth/non_ascii", true, "é", "é");
|
|
|
|
xhr.onreadystatechange = function(event) {
|
|
|
|
if (xhr.readyState == 4) {
|
|
|
|
Assert.equal(xhr.status, 200);
|
|
|
|
moveToNextTest();
|
|
|
|
xhr.onreadystatechange = null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
xhr.send(null);
|
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2007-05-04 07:31:30 +04:00
|
|
|
function test_digest_noauth() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth/digest", URL);
|
2007-05-04 07:31:30 +04:00
|
|
|
|
|
|
|
//chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 2);
|
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2007-05-04 07:31:30 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_digest() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth/digest", URL);
|
2007-05-04 07:31:30 +04:00
|
|
|
|
|
|
|
chan.notificationCallbacks = new Requestor(0, 2);
|
|
|
|
listener.expectedCode = 200; // OK
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2007-05-04 07:31:30 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_digest_bogus_user() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/auth/digest", URL);
|
2010-02-12 19:55:11 +03:00
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_BOGUS_USER, 2);
|
2007-05-04 07:31:30 +04:00
|
|
|
listener.expectedCode = 401; // unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2007-05-04 07:31:30 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2017-02-17 18:44:36 +03:00
|
|
|
// Test header "WWW-Authenticate: Digest" - bug 1338876.
|
|
|
|
function test_short_digest() {
|
|
|
|
var chan = makeChan(URL + "/auth/short_digest", URL);
|
|
|
|
chan.notificationCallbacks = new Requestor(FLAG_NO_REALM, 2);
|
|
|
|
listener.expectedCode = 401; // OK
|
|
|
|
chan.asyncOpen2(listener);
|
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
2006-12-15 05:13:54 +03:00
|
|
|
// PATH HANDLERS
|
|
|
|
|
|
|
|
// /auth
|
|
|
|
function authHandler(metadata, response) {
|
|
|
|
// btoa("guest:guest"), but that function is not available here
|
|
|
|
var expectedHeader = "Basic Z3Vlc3Q6Z3Vlc3Q=";
|
|
|
|
|
|
|
|
var body;
|
|
|
|
if (metadata.hasHeader("Authorization") &&
|
|
|
|
metadata.getHeader("Authorization") == expectedHeader)
|
|
|
|
{
|
|
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK, authorized");
|
|
|
|
response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
|
|
|
|
|
|
|
|
body = "success";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// didn't know guest:guest, failure
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
|
|
|
response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
|
|
|
|
|
|
|
|
body = "failed";
|
|
|
|
}
|
|
|
|
|
|
|
|
response.bodyOutputStream.write(body, body.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
// /auth/ntlm/simple
|
|
|
|
function authNtlmSimple(metadata, response) {
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
2008-03-18 20:42:39 +03:00
|
|
|
response.setHeader("WWW-Authenticate", "NTLM" /* + ' realm="secret"' */, false);
|
2006-12-15 05:13:54 +03:00
|
|
|
|
|
|
|
var body = "NOTE: This just sends an NTLM challenge, it never\n" +
|
|
|
|
"accepts the authentication. It also closes\n" +
|
|
|
|
"the connection after sending the challenge\n";
|
|
|
|
|
|
|
|
|
|
|
|
response.bodyOutputStream.write(body, body.length);
|
|
|
|
}
|
2007-02-11 03:33:29 +03:00
|
|
|
|
|
|
|
// /auth/realm
|
|
|
|
function authRealm(metadata, response) {
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
2014-01-25 03:07:37 +04:00
|
|
|
response.setHeader("WWW-Authenticate", 'Basic realm="\\"f\\oo_bar"', false);
|
2007-02-11 03:33:29 +03:00
|
|
|
var body = "success";
|
|
|
|
|
2017-12-07 02:31:00 +03:00
|
|
|
response.bodyOutputStream.write(body, body.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
// /auth/nonAscii
|
|
|
|
function authNonascii(metadata, response) {
|
|
|
|
// btoa("é:é"), but that function is not available here
|
|
|
|
var expectedHeader = "Basic w6k6w6k=";
|
|
|
|
|
|
|
|
var body;
|
|
|
|
if (metadata.hasHeader("Authorization") &&
|
|
|
|
metadata.getHeader("Authorization") == expectedHeader)
|
|
|
|
{
|
|
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK, authorized");
|
|
|
|
response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
|
|
|
|
|
2018-08-07 06:00:00 +03:00
|
|
|
// Use correct XML syntax since this function is also used for testing XHR.
|
|
|
|
body = "<?xml version='1.0' ?><root>success</root>";
|
2017-12-07 02:31:00 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// didn't know é:é, failure
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
|
|
|
response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
|
|
|
|
|
2018-08-07 06:00:00 +03:00
|
|
|
body = "<?xml version='1.0' ?><root>failed</root>";
|
2017-12-07 02:31:00 +03:00
|
|
|
}
|
|
|
|
|
2007-02-11 03:33:29 +03:00
|
|
|
response.bodyOutputStream.write(body, body.length);
|
|
|
|
}
|
2007-05-04 07:31:30 +04:00
|
|
|
|
|
|
|
//
|
|
|
|
// Digest functions
|
|
|
|
//
|
|
|
|
function bytesFromString(str) {
|
|
|
|
var converter =
|
2018-02-28 20:51:33 +03:00
|
|
|
Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
|
|
|
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
2007-05-04 07:31:30 +04:00
|
|
|
converter.charset = "UTF-8";
|
2009-11-12 13:07:00 +03:00
|
|
|
var data = converter.convertToByteArray(str);
|
2007-05-04 07:31:30 +04:00
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the two-digit hexadecimal code for a byte
|
|
|
|
function toHexString(charCode) {
|
|
|
|
return ("0" + charCode.toString(16)).slice(-2);
|
|
|
|
}
|
|
|
|
|
|
|
|
function H(str) {
|
|
|
|
var data = bytesFromString(str);
|
2018-02-28 20:51:33 +03:00
|
|
|
var ch = Cc["@mozilla.org/security/hash;1"]
|
|
|
|
.createInstance(Ci.nsICryptoHash);
|
|
|
|
ch.init(Ci.nsICryptoHash.MD5);
|
2007-05-04 07:31:30 +04:00
|
|
|
ch.update(data, data.length);
|
|
|
|
var hash = ch.finish(false);
|
2016-01-07 03:02:16 +03:00
|
|
|
return Array.from(hash, (c, i) => toHexString(hash.charCodeAt(i))).join("");
|
2007-05-04 07:31:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Digest handler
|
|
|
|
//
|
|
|
|
// /auth/digest
|
|
|
|
function authDigest(metadata, response) {
|
|
|
|
var nonce = "6f93719059cf8d568005727f3250e798";
|
|
|
|
var opaque = "1234opaque1234";
|
|
|
|
var cnonceRE = /cnonce="(\w+)"/;
|
|
|
|
var responseRE = /response="(\w+)"/;
|
|
|
|
var usernameRE = /username="(\w+)"/;
|
|
|
|
var authenticate = 'Digest realm="secret", domain="/", qop=auth,' +
|
|
|
|
'algorithm=MD5, nonce="' + nonce+ '" opaque="' +
|
|
|
|
opaque + '"';
|
|
|
|
var body;
|
|
|
|
// check creds if we have them
|
|
|
|
if (metadata.hasHeader("Authorization")) {
|
|
|
|
var auth = metadata.getHeader("Authorization");
|
|
|
|
var cnonce = (auth.match(cnonceRE))[1];
|
|
|
|
var clientDigest = (auth.match(responseRE))[1];
|
|
|
|
var username = (auth.match(usernameRE))[1];
|
|
|
|
var nc = "00000001";
|
|
|
|
|
|
|
|
if (username != "guest") {
|
|
|
|
response.setStatusLine(metadata.httpVersion, 400, "bad request");
|
|
|
|
body = "should never get here";
|
|
|
|
} else {
|
|
|
|
// see RFC2617 for the description of this calculation
|
|
|
|
var A1 = "guest:secret:guest";
|
|
|
|
var A2 = "GET:/auth/digest";
|
|
|
|
var noncebits = [nonce, nc, cnonce, "auth", H(A2)].join(":");
|
|
|
|
var digest = H([H(A1), noncebits].join(":"));
|
|
|
|
|
|
|
|
if (clientDigest == digest) {
|
|
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK, authorized");
|
|
|
|
body = "success";
|
|
|
|
} else {
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
|
|
|
response.setHeader("WWW-Authenticate", authenticate, false);
|
|
|
|
body = "auth failed";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// no header, send one
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
|
|
|
response.setHeader("WWW-Authenticate", authenticate, false);
|
|
|
|
body = "failed, no header";
|
|
|
|
}
|
|
|
|
|
|
|
|
response.bodyOutputStream.write(body, body.length);
|
|
|
|
}
|
2013-09-26 22:54:59 +04:00
|
|
|
|
2017-02-17 18:44:36 +03:00
|
|
|
function authShortDigest(metadata, response) {
|
|
|
|
// no header, send one
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
|
|
|
response.setHeader("WWW-Authenticate", 'Digest', false);
|
|
|
|
body = "failed, no header";
|
|
|
|
}
|
|
|
|
|
2018-09-06 00:09:00 +03:00
|
|
|
let buildLargePayload = (function() {
|
|
|
|
let size = 33 * 1024;
|
|
|
|
let ret = "";
|
|
|
|
return function() {
|
|
|
|
// Return cached value.
|
|
|
|
if (ret.length > 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
for (let i = 0; i < size; i++) {
|
|
|
|
ret += "a";
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2013-09-26 22:54:59 +04:00
|
|
|
function largeRealm(metadata, response) {
|
|
|
|
// test > 32KB realm tokens
|
|
|
|
var body;
|
|
|
|
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
|
|
|
response.setHeader("WWW-Authenticate",
|
2018-09-06 00:09:00 +03:00
|
|
|
'Digest realm="' + buildLargePayload() + '", domain="foo"');
|
2013-09-26 22:54:59 +04:00
|
|
|
|
|
|
|
body = "need to authenticate";
|
|
|
|
response.bodyOutputStream.write(body, body.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
function largeDomain(metadata, response) {
|
|
|
|
// test > 32KB domain tokens
|
|
|
|
var body;
|
|
|
|
|
|
|
|
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
|
|
|
|
response.setHeader("WWW-Authenticate",
|
2018-09-06 00:09:00 +03:00
|
|
|
'Digest realm="foo", domain="' + buildLargePayload() + '"');
|
2013-09-26 22:54:59 +04:00
|
|
|
|
|
|
|
body = "need to authenticate";
|
|
|
|
response.bodyOutputStream.write(body, body.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_large_realm() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/largeRealm", URL);
|
2013-09-26 22:54:59 +04:00
|
|
|
|
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2013-09-26 22:54:59 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_large_domain() {
|
2016-06-06 02:06:00 +03:00
|
|
|
var chan = makeChan(URL + "/largeDomain", URL);
|
2013-09-26 22:54:59 +04:00
|
|
|
|
|
|
|
listener.expectedCode = 401; // Unauthorized
|
2015-12-14 23:36:12 +03:00
|
|
|
chan.asyncOpen2(listener);
|
2013-09-26 22:54:59 +04:00
|
|
|
|
|
|
|
do_test_pending();
|
|
|
|
}
|