Attachment #8821683: patch for test digest for bug #41489

View | Details | Raw Unified | Return to bug 41489
Collapse All | Expand All

(-)a/netwerk/test/unit/test_authentication.js (-6 / +93 lines)
Line     Link Here 
 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
}

Return to bug 41489