|
---|
Lines 17-32
XPCOMUtils.defineLazyGetter(this, "PORT"
|
Link Here
|
---|
|
---|
17 |
return httpserv.identity.primaryPort; |
17 |
return httpserv.identity.primaryPort; |
18 |
}); |
18 |
}); |
19 |
|
19 |
|
20 |
const FLAG_RETURN_FALSE = 1 << 0; |
20 |
const FLAG_RETURN_FALSE = 1 << 0; |
21 |
const FLAG_WRONG_PASSWORD = 1 << 1; |
21 |
const FLAG_WRONG_PASSWORD = 1 << 1; |
22 |
const FLAG_BOGUS_USER = 1 << 2; |
22 |
const FLAG_BOGUS_USER = 1 << 2; |
23 |
const FLAG_PREVIOUS_FAILED = 1 << 3; |
23 |
const FLAG_PREVIOUS_FAILED = 1 << 3; |
24 |
const CROSS_ORIGIN = 1 << 4; |
24 |
const CROSS_ORIGIN = 1 << 4; |
|
|
25 |
const FLAG_UTF8_USER = 1 << 5; |
25 |
|
26 |
|
26 |
const nsIAuthPrompt2 = Components.interfaces.nsIAuthPrompt2; |
27 |
const nsIAuthPrompt2 = Components.interfaces.nsIAuthPrompt2; |
27 |
const nsIAuthInformation = Components.interfaces.nsIAuthInformation; |
28 |
const nsIAuthInformation = Components.interfaces.nsIAuthInformation; |
28 |
|
29 |
|
29 |
|
30 |
|
30 |
function AuthPrompt1(flags) { |
31 |
function AuthPrompt1(flags) { |
31 |
this.flags = flags; |
32 |
this.flags = flags; |
32 |
} |
33 |
} |
Lines 150-165
AuthPrompt2.prototype = {
|
Link Here
|
---|
|
---|
150 |
if (this.flags & FLAG_RETURN_FALSE) |
151 |
if (this.flags & FLAG_RETURN_FALSE) |
151 |
{ |
152 |
{ |
152 |
this.flags |= FLAG_PREVIOUS_FAILED; |
153 |
this.flags |= FLAG_PREVIOUS_FAILED; |
153 |
return false; |
154 |
return false; |
154 |
} |
155 |
} |
155 |
|
156 |
|
156 |
if (this.flags & FLAG_BOGUS_USER) |
157 |
if (this.flags & FLAG_BOGUS_USER) |
157 |
this.user = "foo\nbar"; |
158 |
this.user = "foo\nbar"; |
|
|
159 |
if (this.flags & FLAG_UTF8_USER) |
160 |
this.user = "\u0443\u0442\u04448"; |
158 |
|
161 |
|
159 |
authInfo.username = this.user; |
162 |
authInfo.username = this.user; |
160 |
if (this.flags & FLAG_WRONG_PASSWORD) { |
163 |
if (this.flags & FLAG_WRONG_PASSWORD) { |
161 |
authInfo.password = this.pass + ".wrong"; |
164 |
authInfo.password = this.pass + ".wrong"; |
162 |
this.flags |= FLAG_PREVIOUS_FAILED; |
165 |
this.flags |= FLAG_PREVIOUS_FAILED; |
163 |
// Now clear the flag to avoid an infinite loop |
166 |
// Now clear the flag to avoid an infinite loop |
164 |
this.flags &= ~FLAG_WRONG_PASSWORD; |
167 |
this.flags &= ~FLAG_WRONG_PASSWORD; |
165 |
} else { |
168 |
} else { |
Lines 297-327
function makeChan(url, loadingUrl) {
|
Link Here
|
---|
|
---|
297 |
contentPolicyType: Components.interfaces.nsIContentPolicy.TYPE_OTHER |
300 |
contentPolicyType: Components.interfaces.nsIContentPolicy.TYPE_OTHER |
298 |
}); |
301 |
}); |
299 |
} |
302 |
} |
300 |
|
303 |
|
301 |
var tests = [test_noauth, test_returnfalse1, test_wrongpw1, test_prompt1, |
304 |
var tests = [test_noauth, test_returnfalse1, test_wrongpw1, test_prompt1, |
302 |
test_prompt1CrossOrigin, test_prompt2CrossOrigin, |
305 |
test_prompt1CrossOrigin, test_prompt2CrossOrigin, |
303 |
test_returnfalse2, test_wrongpw2, test_prompt2, test_ntlm, |
306 |
test_returnfalse2, test_wrongpw2, test_prompt2, test_ntlm, |
304 |
test_basicrealm, test_digest_noauth, test_digest, |
307 |
test_basicrealm, test_digest_noauth, test_digest, |
305 |
test_digest_bogus_user, test_large_realm, test_large_domain]; |
308 |
test_digest_bogus_user, test_large_realm, test_large_domain, |
|
|
309 |
test_userhash, test_charset]; |
306 |
|
310 |
|
307 |
var current_test = 0; |
311 |
var current_test = 0; |
308 |
|
312 |
|
309 |
var httpserv = null; |
313 |
var httpserv = null; |
310 |
|
314 |
|
311 |
function run_test() { |
315 |
function run_test() { |
312 |
httpserv = new HttpServer(); |
316 |
httpserv = new HttpServer(); |
313 |
|
317 |
|
314 |
httpserv.registerPathHandler("/auth", authHandler); |
318 |
httpserv.registerPathHandler("/auth", authHandler); |
315 |
httpserv.registerPathHandler("/auth/ntlm/simple", authNtlmSimple); |
319 |
httpserv.registerPathHandler("/auth/ntlm/simple", authNtlmSimple); |
316 |
httpserv.registerPathHandler("/auth/realm", authRealm); |
320 |
httpserv.registerPathHandler("/auth/realm", authRealm); |
317 |
httpserv.registerPathHandler("/auth/digest", authDigest); |
321 |
httpserv.registerPathHandler("/auth/digest", authDigest); |
318 |
httpserv.registerPathHandler("/largeRealm", largeRealm); |
322 |
httpserv.registerPathHandler("/largeRealm", largeRealm); |
319 |
httpserv.registerPathHandler("/largeDomain", largeDomain); |
323 |
httpserv.registerPathHandler("/largeDomain", largeDomain); |
|
|
324 |
httpserv.registerPathHandler("/auth/digest/authUserhash", authUserhash); |
325 |
httpserv.registerPathHandler("/auth/digest/authCharset", authCharset); |
320 |
|
326 |
|
321 |
httpserv.start(-1); |
327 |
httpserv.start(-1); |
322 |
|
328 |
|
323 |
tests[0](); |
329 |
tests[0](); |
324 |
} |
330 |
} |
325 |
|
331 |
|
326 |
function test_noauth() { |
332 |
function test_noauth() { |
327 |
var chan = makeChan(URL + "/auth", URL); |
333 |
var chan = makeChan(URL + "/auth", URL); |
Lines 456-471
function test_digest_bogus_user() {
|
Link Here
|
---|
|
---|
456 |
var chan = makeChan(URL + "/auth/digest", URL); |
462 |
var chan = makeChan(URL + "/auth/digest", URL); |
457 |
chan.notificationCallbacks = new Requestor(FLAG_BOGUS_USER, 2); |
463 |
chan.notificationCallbacks = new Requestor(FLAG_BOGUS_USER, 2); |
458 |
listener.expectedCode = 401; // unauthorized |
464 |
listener.expectedCode = 401; // unauthorized |
459 |
chan.asyncOpen2(listener); |
465 |
chan.asyncOpen2(listener); |
460 |
|
466 |
|
461 |
do_test_pending(); |
467 |
do_test_pending(); |
462 |
} |
468 |
} |
463 |
|
469 |
|
|
|
470 |
function test_userhash() { |
471 |
var chan = makeChan(URL + "/auth/digest/authUserhash", URL); |
472 |
|
473 |
chan.notificationCallbacks = new Requestor(0, 2); |
474 |
listener.expectedCode = 200; // OK |
475 |
chan.asyncOpen2(listener); |
476 |
|
477 |
do_test_pending(); |
478 |
} |
479 |
|
480 |
function test_charset() { |
481 |
var chan = makeChan(URL + "/auth/digest/authCharset", URL); |
482 |
|
483 |
chan.notificationCallbacks = new Requestor(FLAG_UTF8_USER, 2); |
484 |
listener.expectedCode = 200; // OK |
485 |
chan.asyncOpen2(listener); |
486 |
|
487 |
do_test_pending(); |
488 |
} |
489 |
|
464 |
// PATH HANDLERS |
490 |
// PATH HANDLERS |
465 |
|
491 |
|
466 |
// /auth |
492 |
// /auth |
467 |
function authHandler(metadata, response) { |
493 |
function authHandler(metadata, response) { |
468 |
// btoa("guest:guest"), but that function is not available here |
494 |
// btoa("guest:guest"), but that function is not available here |
469 |
var expectedHeader = "Basic Z3Vlc3Q6Z3Vlc3Q="; |
495 |
var expectedHeader = "Basic Z3Vlc3Q6Z3Vlc3Q="; |
470 |
|
496 |
|
471 |
var body; |
497 |
var body; |
Lines 523-579
function bytesFromString(str) {
|
Link Here
|
---|
|
---|
523 |
return data; |
549 |
return data; |
524 |
} |
550 |
} |
525 |
|
551 |
|
526 |
// return the two-digit hexadecimal code for a byte |
552 |
// return the two-digit hexadecimal code for a byte |
527 |
function toHexString(charCode) { |
553 |
function toHexString(charCode) { |
528 |
return ("0" + charCode.toString(16)).slice(-2); |
554 |
return ("0" + charCode.toString(16)).slice(-2); |
529 |
} |
555 |
} |
530 |
|
556 |
|
531 |
function H(str) { |
557 |
function H(str, algorithm) { |
532 |
var data = bytesFromString(str); |
558 |
var data = bytesFromString(str); |
533 |
var ch = Components.classes["@mozilla.org/security/hash;1"] |
559 |
var ch = Components.classes["@mozilla.org/security/hash;1"] |
534 |
.createInstance(Components.interfaces.nsICryptoHash); |
560 |
.createInstance(Components.interfaces.nsICryptoHash); |
535 |
ch.init(Components.interfaces.nsICryptoHash.MD5); |
561 |
if (algorithm == "MD5") { |
|
|
562 |
ch.init(Components.interfaces.nsICryptoHash.MD5); |
563 |
} else if (algorithm == "SHA-256") { |
564 |
ch.init(Components.interfaces.nsICryptoHash.SHA256); |
565 |
} else { |
566 |
do_throw("Algorithm not set!"); |
567 |
} |
536 |
ch.update(data, data.length); |
568 |
ch.update(data, data.length); |
537 |
var hash = ch.finish(false); |
569 |
var hash = ch.finish(false); |
538 |
return Array.from(hash, (c, i) => toHexString(hash.charCodeAt(i))).join(""); |
570 |
return Array.from(hash, (c, i) => toHexString(hash.charCodeAt(i))).join(""); |
539 |
} |
571 |
} |
540 |
|
572 |
|
541 |
// |
573 |
// |
542 |
// Digest handler |
574 |
// Digest handler |
543 |
// |
575 |
// |
544 |
// /auth/digest |
576 |
// /auth/digest |
545 |
function authDigest(metadata, response) { |
577 |
function authDigest(metadata, response) { |
546 |
var nonce = "6f93719059cf8d568005727f3250e798"; |
578 |
var nonce = "6f93719059cf8d568005727f3250e798"; |
547 |
var opaque = "1234opaque1234"; |
579 |
var opaque = "1234opaque1234"; |
548 |
var cnonceRE = /cnonce="(\w+)"/; |
580 |
var cnonceRE = /cnonce="(\w+)"/; |
549 |
var responseRE = /response="(\w+)"/; |
581 |
var responseRE = /response="(\w+)"/; |
550 |
var usernameRE = /username="(\w+)"/; |
582 |
var usernameRE = /username="(\w+)"/; |
|
|
583 |
var algorithmRE = /algorithm=(\w+[-\d]*)/; |
551 |
var authenticate = 'Digest realm="secret", domain="/", qop=auth,' + |
584 |
var authenticate = 'Digest realm="secret", domain="/", qop=auth,' + |
552 |
'algorithm=MD5, nonce="' + nonce+ '" opaque="' + |
585 |
'algorithm=MD5, nonce="' + nonce+ '" opaque="' + |
553 |
opaque + '"'; |
586 |
opaque + '"' + ', algorithm=SHA-256'; |
554 |
var body; |
587 |
var body; |
555 |
// check creds if we have them |
588 |
// check creds if we have them |
556 |
if (metadata.hasHeader("Authorization")) { |
589 |
if (metadata.hasHeader("Authorization")) { |
557 |
var auth = metadata.getHeader("Authorization"); |
590 |
var auth = metadata.getHeader("Authorization"); |
558 |
var cnonce = (auth.match(cnonceRE))[1]; |
591 |
var cnonce = (auth.match(cnonceRE))[1]; |
559 |
var clientDigest = (auth.match(responseRE))[1]; |
592 |
var clientDigest = (auth.match(responseRE))[1]; |
560 |
var username = (auth.match(usernameRE))[1]; |
593 |
var username = (auth.match(usernameRE))[1]; |
|
|
594 |
var algorithm = (auth.match(algorithmRE))[1]; |
561 |
var nc = "00000001"; |
595 |
var nc = "00000001"; |
562 |
|
596 |
|
563 |
if (username != "guest") { |
597 |
if (username != "guest") { |
564 |
response.setStatusLine(metadata.httpVersion, 400, "bad request"); |
598 |
response.setStatusLine(metadata.httpVersion, 400, "bad request"); |
565 |
body = "should never get here"; |
599 |
body = "should never get here"; |
566 |
} else { |
600 |
} else { |
567 |
// see RFC2617 for the description of this calculation |
601 |
// see RFC2617 for the description of this calculation |
568 |
var A1 = "guest:secret:guest"; |
602 |
var A1 = "guest:secret:guest"; |
569 |
var A2 = "GET:/auth/digest"; |
603 |
var A2 = "GET:/auth/digest"; |
570 |
var noncebits = [nonce, nc, cnonce, "auth", H(A2)].join(":"); |
604 |
var noncebits = [nonce, nc, cnonce, "auth", H(A2, algorithm)].join(":"); |
571 |
var digest = H([H(A1), noncebits].join(":")); |
605 |
var digest = H([H(A1, algorithm), noncebits].join(":"), algorithm); |
572 |
|
606 |
|
573 |
if (clientDigest == digest) { |
607 |
if (clientDigest == digest) { |
574 |
response.setStatusLine(metadata.httpVersion, 200, "OK, authorized"); |
608 |
response.setStatusLine(metadata.httpVersion, 200, "OK, authorized"); |
575 |
body = "success"; |
609 |
body = "success"; |
576 |
} else { |
610 |
} else { |
577 |
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized"); |
611 |
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized"); |
578 |
response.setHeader("WWW-Authenticate", authenticate, false); |
612 |
response.setHeader("WWW-Authenticate", authenticate, false); |
579 |
body = "auth failed"; |
613 |
body = "auth failed"; |
Lines 2050-2065
function largeDomain(metadata, response)
|
Link Here
|
---|
|
---|
2050 |
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + |
2084 |
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + |
2051 |
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + |
2085 |
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + |
2052 |
'"'); |
2086 |
'"'); |
2053 |
|
2087 |
|
2054 |
body = "need to authenticate"; |
2088 |
body = "need to authenticate"; |
2055 |
response.bodyOutputStream.write(body, body.length); |
2089 |
response.bodyOutputStream.write(body, body.length); |
2056 |
} |
2090 |
} |
2057 |
|
2091 |
|
|
|
2092 |
function authUserhash(metadata, response) { |
2093 |
var usernameRE = /username="(\w+)"/; |
2094 |
var algorithmRE = /algorithm=(\w+[-\d]*)/; |
2095 |
var userhashRE = /userhash=(\w+)/; |
2096 |
var authenticate = 'Digest realm="secret", algorithm=SHA-256, userhash=true'; |
2097 |
var body; |
2098 |
if (metadata.hasHeader("Authorization")) { |
2099 |
var auth = metadata.getHeader("Authorization"); |
2100 |
var username = (auth.match(usernameRE))[1]; |
2101 |
var algorithm = (auth.match(algorithmRE))[1]; |
2102 |
var userhash = (auth.match(userhashRE))[1]; |
2103 |
if (userhash == "true") { |
2104 |
if (username != H("guest:secret", algorithm)) { |
2105 |
response.setStatusLine(metadata.httpVersion, 400, "bad request"); |
2106 |
body = "should never get here"; |
2107 |
} else { |
2108 |
response.setStatusLine(metadata.httpVersion, 200, "OK, authorized"); |
2109 |
body = "success"; |
2110 |
} |
2111 |
} else { |
2112 |
response.setStatusLine(metadata.httpVersion, 400, "bad request"); |
2113 |
body = "need userhash"; |
2114 |
} |
2115 |
} else { |
2116 |
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized"); |
2117 |
response.setHeader("WWW-Authenticate", authenticate, false); |
2118 |
var body = "failed, no header"; |
2119 |
} |
2120 |
response.bodyOutputStream.write(body, body.length); |
2121 |
} |
2122 |
|
2123 |
function authCharset(metadata, response) { |
2124 |
var usernameRE = /username\*=UTF-8''([%\w]+)/; |
2125 |
var authenticate = 'Digest realm="secret", charset=UTF-8'; |
2126 |
var body; |
2127 |
if (metadata.hasHeader("Authorization")) { |
2128 |
var auth = metadata.getHeader("Authorization"); |
2129 |
var username = decodeURI((auth.match(usernameRE))[1]); |
2130 |
if (username != "\u0443\u0442\u04448") { |
2131 |
response.setStatusLine(metadata.httpVersion, 400, "bad request"); |
2132 |
body = "should never get here"; |
2133 |
} else { |
2134 |
response.setStatusLine(metadata.httpVersion, 200, "OK, authorized"); |
2135 |
body = "success"; |
2136 |
} |
2137 |
} else { |
2138 |
response.setStatusLine(metadata.httpVersion, 401, "Unauthorized"); |
2139 |
response.setHeader("WWW-Authenticate", authenticate, false); |
2140 |
var body = "failed, no header"; |
2141 |
} |
2142 |
response.bodyOutputStream.write(body, body.length); |
2143 |
} |
2144 |
|
2058 |
function test_large_realm() { |
2145 |
function test_large_realm() { |
2059 |
var chan = makeChan(URL + "/largeRealm", URL); |
2146 |
var chan = makeChan(URL + "/largeRealm", URL); |
2060 |
|
2147 |
|
2061 |
listener.expectedCode = 401; // Unauthorized |
2148 |
listener.expectedCode = 401; // Unauthorized |
2062 |
chan.asyncOpen2(listener); |
2149 |
chan.asyncOpen2(listener); |
2063 |
|
2150 |
|
2064 |
do_test_pending(); |
2151 |
do_test_pending(); |
2065 |
} |
2152 |
} |