Attachment #8714628: to do here as draft-ietf-httpauth-digest for bug #41489

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

(-)file_not_specified_in_diff (-79 / +221 lines)
Line     Link Here 
0
-- /e/mozilla-release-8168af494649/netwerk/protocol/http/nsHttpBasicAuth.cpp201
0
++ /c/mozilla-release-8168af494649/netwerk/protocol/http/nsHttpBasicAuth.cpp201
 Lines 4-19    Link Here 
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
// HttpLog.h should generally be included first
5
// HttpLog.h should generally be included first
6
#include "HttpLog.h"
6
#include "HttpLog.h"
7
#include "nsHttpBasicAuth.h"
7
#include "nsHttpBasicAuth.h"
8
#include "plbase64.h"
8
#include "plbase64.h"
9
#include "nsString.h"
9
#include "nsString.h"
10
#include "mozilla/Tokenizer.h"
10
namespace mozilla {
11
namespace mozilla {
11
namespace net {
12
namespace net {
12
//-----------------------------------------------------------------------------
13
//-----------------------------------------------------------------------------
13
// nsHttpBasicAuth <public>
14
// nsHttpBasicAuth <public>
14
//-----------------------------------------------------------------------------
15
//-----------------------------------------------------------------------------
 Lines 67-88   nsHttpBasicAuth::GenerateCredentials(nsI Link Here 
67
    NS_ENSURE_ARG_POINTER(creds);
68
    NS_ENSURE_ARG_POINTER(creds);
68
    *aFlags = 0;
69
    *aFlags = 0;
69
    // we only know how to deal with Basic auth for http.
70
    // we only know how to deal with Basic auth for http.
70
    bool isBasicAuth = !PL_strncasecmp(challenge, "basic", 5);
71
    bool isBasicAuth = !PL_strncasecmp(challenge, "basic", 5);
71
    NS_ENSURE_TRUE(isBasicAuth, NS_ERROR_UNEXPECTED);
72
    NS_ENSURE_TRUE(isBasicAuth, NS_ERROR_UNEXPECTED);
72
    // we work with ASCII around here
73
    nsAutoCString userpass;
73
    nsAutoCString userpass;
74
    LossyCopyUTF16toASCII(user, userpass);
74
         nsAutoCString charset;
75
    userpass.Append(':'); // always send a ':' (see bug 129565)
75
         Tokenizer p(challenge);
76
    if (password)
76
         Tokenizer::Token t;
77
        LossyAppendUTF16toASCII(password, userpass);
77
         while (p.Next(t)) {
78
           if (t.AsString() == "charset" && p.Next(t) && (t.AsChar() == '=')) {
79
             p.Record();
80
             while (p.Next(t) && !t.Equals(Tokenizer::Token::Char(',')));
81
             p.Claim(charset);
82
                   charset.StripChar('"', 0);
83
           }
84
         }
85
    if (charset.EqualsLiteral("UTF-8")) {
86
      CopyUTF16toUTF8(user, userpass);
87
      userpass.Append(':');
88
           if (password) {
89
                   AppendUTF16toUTF8(password, userpass);
90
           }
91
         } else {
92
      /**
93
            *Actually it is ISO-8859-1(not ASCII)
94
       */
95
           LossyCopyUTF16toASCII(user, userpass);
96
      userpass.Append(':');
97
           if (password) {
98
                   LossyAppendUTF16toASCII(password, userpass);
99
           }
100
         }
78
    // plbase64.h provides this worst-case output buffer size calculation.
101
    // plbase64.h provides this worst-case output buffer size calculation.
79
    // use calloc, since PL_Base64Encode does not null terminate.
102
    // use calloc, since PL_Base64Encode does not null terminate.
80
    *creds = (char *) calloc(6 + ((userpass.Length() + 2)/3)*4 + 1, 1);
103
    *creds = (char *) calloc(6 + ((userpass.Length() + 2)/3)*4 + 1, 1);
81
    if (!*creds)
104
    if (!*creds)
82
        return NS_ERROR_OUT_OF_MEMORY;
105
        return NS_ERROR_OUT_OF_MEMORY;
83
    memcpy(*creds, "Basic ", 6);
106
    memcpy(*creds, "Basic ", 6);
84
-- /e/mozilla-release-8168af494649/netwerk/protocol/http/nsHttpDigestAuth.cpp20
107
++ /c/mozilla-release-8168af494649/netwerk/protocol/http/nsHttpDigestAuth.cpp20
 Lines 38-78   nsHttpDigestAuth::~nsHttpDigestAuth() Link Here 
38
NS_IMPL_ISUPPORTS(nsHttpDigestAuth, nsIHttpAuthenticator)
38
NS_IMPL_ISUPPORTS(nsHttpDigestAuth, nsIHttpAuthenticator)
39
//-----------------------------------------------------------------------------
39
//-----------------------------------------------------------------------------
40
// nsHttpDigestAuth <protected>
40
// nsHttpDigestAuth <protected>
41
//-----------------------------------------------------------------------------
41
//-----------------------------------------------------------------------------
42
nsresult
42
nsresult
43
nsHttpDigestAuth::MD5Hash(const char *buf, uint32_t len)
43
nsHttpDigestAuth::DoHash(const char *buf, uint32_t len, uint16_t algorithm)
44
{
44
{
45
  nsresult rv;
45
  nsresult rv;
46
  // Cache a reference to the nsICryptoHash instance since we'll be calling
46
  // Cache a reference to the nsICryptoHash instance since we'll be calling
47
  // this function frequently.
47
  // this function frequently.
48
  if (!mVerifier) {
48
  if (!mVerifier) {
49
    mVerifier = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
49
    mVerifier = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
50
    if (NS_FAILED(rv)) {
50
    if (NS_FAILED(rv)) {
51
      LOG(("nsHttpDigestAuth: no crypto hash!\n"));
51
      LOG(("nsHttpDigestAuth: no crypto hash!\n"));
52
      return rv;
52
      return rv;
53
    }
53
    }
54
  }
54
  }
55
  rv = mVerifier->Init(nsICryptoHash::MD5);
55
  if (algorithm == ALGO_SHA256 || algorithm == ALGO_SHA256_SESS) {
56
         rv = mVerifier->Init(nsICryptoHash::SHA256);
57
  } else {
58
         rv = mVerifier->Init(nsICryptoHash::MD5);
59
  }
56
  if (NS_FAILED(rv)) return rv;
60
  if (NS_FAILED(rv)) return rv;
57
  rv = mVerifier->Update((unsigned char*)buf, len);
61
  rv = mVerifier->Update((unsigned char*)buf, len);
58
  if (NS_FAILED(rv)) return rv;
62
  if (NS_FAILED(rv)) return rv;
59
  nsAutoCString hashString;
63
  nsAutoCString hashString;
60
  rv = mVerifier->Finish(false, hashString);
64
  rv = mVerifier->Finish(false, hashString);
61
  if (NS_FAILED(rv)) return rv;
65
  if (NS_FAILED(rv)) return rv;
62
  NS_ENSURE_STATE(hashString.Length() == sizeof(mHashBuf));
63
  memcpy(mHashBuf, hashString.get(), hashString.Length());
66
  memcpy(mHashBuf, hashString.get(), hashString.Length());
64
  return rv;
67
  return rv;
65
}
68
}
66
nsresult
69
nsresult
67
nsHttpDigestAuth::GetMethodAndPath(nsIHttpAuthenticableChannel *authChannel,
70
nsHttpDigestAuth::GetMethodAndPath(nsIHttpAuthenticableChannel *authChannel,
68
                                   bool                         isProxyAuth,
71
                                   bool                         isProxyAuth,
 Lines 134-155   nsHttpDigestAuth::GetMethodAndPath(nsIHt Link Here 
134
NS_IMETHODIMP
137
NS_IMETHODIMP
135
nsHttpDigestAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
138
nsHttpDigestAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
136
                                    const char *challenge,
139
                                    const char *challenge,
137
                                    bool isProxyAuth,
140
                                    bool isProxyAuth,
138
                                    nsISupports **sessionState,
141
                                    nsISupports **sessionState,
139
                                    nsISupports **continuationState,
142
                                    nsISupports **continuationState,
140
                                    bool *result)
143
                                    bool *result)
141
{
144
{
142
  nsAutoCString realm, domain, nonce, opaque;
145
  nsAutoCString realm, domain, nonce, opaque, charset;
143
  bool stale;
146
  bool stale;
144
  uint16_t algorithm, qop;
147
  uint16_t algorithm, qop, userhash;
145
  nsresult rv = ParseChallenge(challenge, realm, domain, nonce, opaque,
148
  nsresult rv = ParseChallenge(challenge, realm, domain, nonce, opaque, charset
146
                               &stale, &algorithm, &qop);
149
                               &stale, &algorithm, &qop, &userhash);
147
  if (NS_FAILED(rv)) return rv;
150
  if (NS_FAILED(rv)) return rv;
148
  // if the challenge has the "stale" flag set, then the user identity is not
151
  // if the challenge has the "stale" flag set, then the user identity is not
149
  // necessarily invalid.  by returning FALSE here we can suppress username
152
  // necessarily invalid.  by returning FALSE here we can suppress username
150
  // and password prompting that usually accompanies a 401/407 challenge.
153
  // and password prompting that usually accompanies a 401/407 challenge.
151
  *result = !stale;
154
  *result = !stale;
152
  // clear any existing nonce_count since we have a new challenge.
155
  // clear any existing nonce_count since we have a new challenge.
 Lines 190-220   nsHttpDigestAuth::GenerateCredentials(ns Link Here 
190
  }
193
  }
191
  nsresult rv;
194
  nsresult rv;
192
  nsAutoCString httpMethod;
195
  nsAutoCString httpMethod;
193
  nsAutoCString path;
196
  nsAutoCString path;
194
  rv = GetMethodAndPath(authChannel, isProxyAuth, httpMethod, path);
197
  rv = GetMethodAndPath(authChannel, isProxyAuth, httpMethod, path);
195
  if (NS_FAILED(rv)) return rv;
198
  if (NS_FAILED(rv)) return rv;
196
  nsAutoCString realm, domain, nonce, opaque;
199
  nsAutoCString realm, domain, nonce, opaque, charset;
197
  bool stale;
200
  bool stale;
198
  uint16_t algorithm, qop;
201
  uint16_t algorithm, qop, userhash;
199
  rv = ParseChallenge(challenge, realm, domain, nonce, opaque,
202
  rv = ParseChallenge(challenge, realm, domain, nonce, opaque, charset,
200
                      &stale, &algorithm, &qop);
203
                      &stale, &algorithm, &qop, &userhash);
201
  if (NS_FAILED(rv)) {
204
  if (NS_FAILED(rv)) {
202
    LOG(("nsHttpDigestAuth::GenerateCredentials [ParseChallenge failed rv=%x]\n
205
    LOG(("nsHttpDigestAuth::GenerateCredentials [ParseChallenge failed rv=%x]\n
203
    return rv;
206
    return rv;
204
  }
207
  }
205
208
206
  char ha1_digest[EXPANDED_DIGEST_LENGTH+1];
209
  char ha1_digest[EXPANDED_DIGEST_SHA256_LENGTH+1];
207
  char ha2_digest[EXPANDED_DIGEST_LENGTH+1];
210
  char ha2_digest[EXPANDED_DIGEST_SHA256_LENGTH+1];
208
  char response_digest[EXPANDED_DIGEST_LENGTH+1];
211
  char response_digest[EXPANDED_DIGEST_SHA256_LENGTH+1];
209
  char upload_data_digest[EXPANDED_DIGEST_LENGTH+1];
212
  char upload_data_digest[EXPANDED_DIGEST_SHA256_LENGTH+1];
210
  if (qop & QOP_AUTH_INT) {
213
  if (qop & QOP_AUTH_INT) {
211
    // we do not support auth-int "quality of protection" currently
214
    // we do not support auth-int "quality of protection" currently
212
    qop &= ~QOP_AUTH_INT;
215
    qop &= ~QOP_AUTH_INT;
213
    NS_WARNING("no support for Digest authentication with data integrity qualit
216
    NS_WARNING("no support for Digest authentication with data integrity qualit
214
    /* TODO: to support auth-int, we need to get an MD5 digest of
217
    /* TODO: to support auth-int, we need to get an MD5 digest of
 Lines 231-254   nsHttpDigestAuth::GenerateCredentials(ns Link Here 
231
      NS_ENSURE_TRUE(uc, NS_ERROR_UNEXPECTED);
234
      NS_ENSURE_TRUE(uc, NS_ERROR_UNEXPECTED);
232
      uc->GetUploadStream(&upload);
235
      uc->GetUploadStream(&upload);
233
      if (upload) {
236
      if (upload) {
234
        char * upload_buffer;
237
        char * upload_buffer;
235
        int upload_buffer_length = 0;
238
        int upload_buffer_length = 0;
236
        //TODO: read input stream into buffer
239
        //TODO: read input stream into buffer
237
        const char * digest = (const char*)
240
        const char * digest = (const char*)
238
        nsNetwerkMD5Digest(upload_buffer, upload_buffer_length);
241
        nsNetwerkMD5Digest(upload_buffer, upload_buffer_length);
239
        ExpandToHex(digest, upload_data_digest);
242
        ExpandToHex(digest, algorithm, upload_data_digest);
240
        NS_RELEASE(upload);
243
        NS_RELEASE(upload);
241
      }
244
      }
242
    }
245
    }
243
#endif
246
#endif
244
  }
247
  }
245
  if (!(algorithm & ALGO_MD5 || algorithm & ALGO_MD5_SESS)) {
248
  if (!(algorithm == ALGO_MD5 || algorithm == ALGO_MD5_SESS ||
249
    algorithm == ALGO_SHA256 || algorithm == ALGO_SHA256_SESS)) {
246
    // they asked only for algorithms that we do not support
250
    // they asked only for algorithms that we do not support
247
    NS_WARNING("unsupported algorithm requested by Digest authentication");
251
    NS_WARNING("unsupported algorithm requested by Digest authentication");
248
    return NS_ERROR_NOT_IMPLEMENTED;
252
    return NS_ERROR_NOT_IMPLEMENTED;
249
  }
253
  }
250
  //
254
  //
251
  // the following are for increasing security.  see RFC 2617 for more
255
  // the following are for increasing security.  see RFC 2617 for more
252
  // information.
256
  // information.
 Lines 286-346   nsHttpDigestAuth::GenerateCredentials(ns Link Here 
286
    cnonce.Append(hexChar[(int)(15.0 * rand()/(RAND_MAX + 1.0))]);
290
    cnonce.Append(hexChar[(int)(15.0 * rand()/(RAND_MAX + 1.0))]);
287
  }
291
  }
288
  LOG(("   cnonce=%s\n", cnonce.get()));
292
  LOG(("   cnonce=%s\n", cnonce.get()));
289
  //
293
  //
290
  // calculate credentials
294
  // calculate credentials
291
  //
295
  //
292
  NS_ConvertUTF16toUTF8 cUser(username), cPass(password);
296
  nsAutoCString cUser;
297
  nsAutoCString cPass;
298
  if(charset.EqualsLiteral("ISO-8859-1")){
299
    /**
300
     *Actually it is ISO-8859-1
301
     */
302
    LossyCopyUTF16toASCII(username, cUser);
303
    LossyCopyUTF16toASCII(password, cPass);
304
  } else if (charset.EqualsLiteral("UTF-8")) {
305
    CopyUTF16toUTF8(username, cUser);
306
    CopyUTF16toUTF8(password, cPass);
307
  } else {
308
    /**
309
          *This true lossy convert UTF16 to ASCII
310
          *ASCII is an 7-bit encoding
311
     */
312
    const char16_t *p = username;
313
         cUser.Assign(*p % 128);
314
         p++;
315
         for (;*p != 0;p++) {
316
           cUser.Append(*p % 128);
317
         }
318
         p = password;
319
         cPass.Assign(*p % 128);
320
         p++;
321
         for (;*p != 0;p++) {
322
           cPass.Append(*p % 128);
323
         }
324
  }
325
293
  rv = CalculateHA1(cUser, cPass, realm, algorithm, nonce, cnonce, ha1_digest);
326
  rv = CalculateHA1(cUser, cPass, realm, algorithm, nonce, cnonce, ha1_digest);
294
  if (NS_FAILED(rv)) return rv;
327
  if (NS_FAILED(rv)) return rv;
295
  rv = CalculateHA2(httpMethod, path, qop, upload_data_digest, ha2_digest);
328
  rv = CalculateHA2(httpMethod, path, qop, algorithm, upload_data_digest,
329
                       ha2_digest);
296
  if (NS_FAILED(rv)) return rv;
330
  if (NS_FAILED(rv)) return rv;
297
  rv = CalculateResponse(ha1_digest, ha2_digest, nonce, qop, nonce_count,
331
  rv = CalculateResponse(ha1_digest, ha2_digest, nonce, qop, algorithm, nonce_c
298
                         cnonce, response_digest);
332
                         cnonce, response_digest);
299
  if (NS_FAILED(rv)) return rv;
333
  if (NS_FAILED(rv)) return rv;
300
  //
334
  //
301
  // Values that need to match the quoted-string production from RFC 2616:
335
  // Values that need to match the quoted-string production from RFC 2616:
302
  //
336
  //
303
  //    username
337
  //    username
304
  //    realm
338
  //    realm
305
  //    nonce
339
  //    nonce
306
  //    opaque
340
  //    opaque
307
  //    cnonce
341
  //    cnonce
308
  //
342
  //
309
  nsAutoCString authString;
343
  nsAutoCString authString;
310
  authString.AssignLiteral("Digest username=");
344
  if (userhash == 2) {
311
  rv = AppendQuotedString(cUser, authString);
345
         char hashuser[EXPANDED_DIGEST_SHA256_LENGTH+1];
312
  NS_ENSURE_SUCCESS(rv, rv);
346
    cUser.Append(":");
347
    cUser.Append(realm);
348
         rv = DoHash(cUser.get(), cUser.Length(), algorithm);
349
    if (NS_FAILED(rv)) return rv;
350
         ExpandToHex(mHashBuf, algorithm, hashuser);
351
         authString.AssignLiteral("Digest username=\"");
352
         authString += hashuser;
353
         authString += '\"';
354
  } else if (charset.EqualsLiteral("ISO-8859-1") ||
355
    charset.EqualsLiteral("UTF-8")) {
356
    if (charset.EqualsLiteral("ISO-8859-1")) {
357
      authString.AssignLiteral("Digest username*=ISO-8859-1\'\'");
358
    } else {
359
      authString.AssignLiteral("Digest username*=UTF-8\'\'");
360
    }
361
    nsAutoCString escUser;
362
    NS_Escape(cUser, escUser,  url_XAlphas);
363
    authString.Append(escUser);
364
  } else {
365
    authString.AssignLiteral("Digest username=");
366
    rv = AppendQuotedString(cUser, authString);
367
    NS_ENSURE_SUCCESS(rv, rv);
368
  }
313
  authString.AppendLiteral(", realm=");
369
  authString.AppendLiteral(", realm=");
314
  rv = AppendQuotedString(realm, authString);
370
  rv = AppendQuotedString(realm, authString);
315
  NS_ENSURE_SUCCESS(rv, rv);
371
  NS_ENSURE_SUCCESS(rv, rv);
316
  authString.AppendLiteral(", nonce=");
372
  authString.AppendLiteral(", nonce=");
317
  rv = AppendQuotedString(nonce, authString);
373
  rv = AppendQuotedString(nonce, authString);
318
  NS_ENSURE_SUCCESS(rv, rv);
374
  NS_ENSURE_SUCCESS(rv, rv);
319
  authString.AppendLiteral(", uri=\"");
375
  authString.AppendLiteral(", uri=\"");
320
  authString += path;
376
  authString += path;
321
  if (algorithm & ALGO_SPECIFIED) {
377
  authString.AppendLiteral("\", algorithm=");
322
    authString.AppendLiteral("\", algorithm=");
378
  if (algorithm == ALGO_SHA256_SESS) {
323
    if (algorithm & ALGO_MD5_SESS)
379
       authString.AppendLiteral("SHA-256-sess");
324
      authString.AppendLiteral("MD5-sess");
380
  } else if (algorithm == ALGO_SHA256) {
325
    else
381
         authString.AppendLiteral("SHA-256");
326
      authString.AppendLiteral("MD5");
382
  } else if (algorithm == ALGO_MD5_SESS) {
383
         authString.AppendLiteral("MD5-sess");
327
  } else {
384
  } else {
328
    authString += '\"';
385
         authString.AppendLiteral("MD5");
329
  }
386
  }
330
  authString.AppendLiteral(", response=\"");
387
  authString.AppendLiteral(", response=\"");
331
  authString += response_digest;
388
  authString += response_digest;
332
  authString += '\"';
389
  authString += '\"';
333
  if (!opaque.IsEmpty()) {
390
  if (!opaque.IsEmpty()) {
334
    authString.AppendLiteral(", opaque=");
391
    authString.AppendLiteral(", opaque=");
335
    rv = AppendQuotedString(opaque, authString);
392
    rv = AppendQuotedString(opaque, authString);
 Lines 359-374   nsHttpDigestAuth::GenerateCredentials(ns Link Here 
359
    authString.AppendLiteral(", nc=");
416
    authString.AppendLiteral(", nc=");
360
    authString += nonce_count;
417
    authString += nonce_count;
361
    authString.AppendLiteral(", cnonce=");
418
    authString.AppendLiteral(", cnonce=");
362
    rv = AppendQuotedString(cnonce, authString);
419
    rv = AppendQuotedString(cnonce, authString);
363
    NS_ENSURE_SUCCESS(rv, rv);
420
    NS_ENSURE_SUCCESS(rv, rv);
364
  }
421
  }
422
  if (userhash) {
423
    authString.AppendLiteral(", userhash=");
424
    if(userhash == 2){
425
      authString.AppendLiteral("true");
426
    } else {
427
      authString.AppendLiteral("false");
428
    }
429
  }
365
  *creds = ToNewCString(authString);
430
  *creds = ToNewCString(authString);
366
  return NS_OK;
431
  return NS_OK;
367
}
432
}
368
NS_IMETHODIMP
433
NS_IMETHODIMP
369
nsHttpDigestAuth::GetAuthFlags(uint32_t *flags)
434
nsHttpDigestAuth::GetAuthFlags(uint32_t *flags)
370
{
435
{
 Lines 380-558   nsHttpDigestAuth::GetAuthFlags(uint32_t Link Here 
380
  return NS_OK;
445
  return NS_OK;
381
}
446
}
382
nsresult
447
nsresult
383
nsHttpDigestAuth::CalculateResponse(const char * ha1_digest,
448
nsHttpDigestAuth::CalculateResponse(const char * ha1_digest,
384
                                    const char * ha2_digest,
449
                                    const char * ha2_digest,
385
                                    const nsAFlatCString & nonce,
450
                                    const nsAFlatCString & nonce,
386
                                    uint16_t qop,
451
                                    uint16_t qop,
452
                                    uint16_t algorithm,
387
                                    const char * nonce_count,
453
                                    const char * nonce_count,
388
                                    const nsAFlatCString & cnonce,
454
                                    const nsAFlatCString & cnonce,
389
                                    char * result)
455
                                    char * result)
390
{
456
{
391
  uint32_t len = 2*EXPANDED_DIGEST_LENGTH + nonce.Length() + 2;
457
  uint32_t len = nonce.Length() + 2 + ExpadedDigestLength(algorithm) * 2;
392
393
  if (qop & QOP_AUTH || qop & QOP_AUTH_INT) {
458
  if (qop & QOP_AUTH || qop & QOP_AUTH_INT) {
394
    len += cnonce.Length() + NONCE_COUNT_LENGTH + 3;
459
    len += cnonce.Length() + NONCE_COUNT_LENGTH + 3;
395
    if (qop & QOP_AUTH_INT)
460
    if (qop & QOP_AUTH_INT)
396
      len += 8; // length of "auth-int"
461
      len += 8; // length of "auth-int"
397
    else
462
    else
398
      len += 4; // length of "auth"
463
      len += 4; // length of "auth"
399
  }
464
  }
400
  nsAutoCString contents;
465
  nsAutoCString contents;
401
  contents.SetCapacity(len);
466
  contents.SetCapacity(len);
402
  contents.Assign(ha1_digest, EXPANDED_DIGEST_LENGTH);
467
       contents.Assign(ha1_digest, ExpadedDigestLength(algorithm));
403
  contents.Append(':');
468
  contents.Append(':');
404
  contents.Append(nonce);
469
  contents.Append(nonce);
405
  contents.Append(':');
470
  contents.Append(':');
406
  if (qop & QOP_AUTH || qop & QOP_AUTH_INT) {
471
  if (qop & QOP_AUTH || qop & QOP_AUTH_INT) {
407
    contents.Append(nonce_count, NONCE_COUNT_LENGTH);
472
    contents.Append(nonce_count, NONCE_COUNT_LENGTH);
408
    contents.Append(':');
473
    contents.Append(':');
409
    contents.Append(cnonce);
474
    contents.Append(cnonce);
410
    contents.Append(':');
475
    contents.Append(':');
411
    if (qop & QOP_AUTH_INT)
476
    if (qop & QOP_AUTH_INT)
412
      contents.AppendLiteral("auth-int:");
477
      contents.AppendLiteral("auth-int:");
413
    else
478
    else
414
      contents.AppendLiteral("auth:");
479
      contents.AppendLiteral("auth:");
415
  }
480
  }
416
  contents.Append(ha2_digest, EXPANDED_DIGEST_LENGTH);
481
       contents.Append(ha2_digest, ExpadedDigestLength(algorithm));
417
  nsresult rv = MD5Hash(contents.get(), contents.Length());
482
  nsresult rv = DoHash(contents.get(), contents.Length(), algorithm);
418
  if (NS_SUCCEEDED(rv))
483
  if (NS_SUCCEEDED(rv))
419
    rv = ExpandToHex(mHashBuf, result);
484
    rv = ExpandToHex(mHashBuf, algorithm, result);
420
  return rv;
485
  return rv;
421
}
486
}
422
nsresult
487
nsresult
423
nsHttpDigestAuth::ExpandToHex(const char * digest, char * result)
488
nsHttpDigestAuth::ExpandToHex(const char * digest, int16_t algorithm, char * re
424
{
489
{
425
  int16_t index, value;
490
  int16_t index, value, digestLen;
491
       digestLen = DigestLength(algorithm);
426
  for (index = 0; index < DIGEST_LENGTH; index++) {
492
  for (index = 0; index < digestLen; index++) {
427
    value = (digest[index] >> 4) & 0xf;
493
    value = (digest[index] >> 4) & 0xf;
428
    if (value < 10)
494
    if (value < 10)
429
      result[index*2] = value + '0';
495
      result[index*2] = value + '0';
430
    else
496
    else
431
      result[index*2] = value - 10 + 'a';
497
      result[index*2] = value - 10 + 'a';
432
    value = digest[index] & 0xf;
498
    value = digest[index] & 0xf;
433
    if (value < 10)
499
    if (value < 10)
434
      result[(index*2)+1] = value + '0';
500
      result[(index*2)+1] = value + '0';
435
    else
501
    else
436
      result[(index*2)+1] = value - 10 + 'a';
502
      result[(index*2)+1] = value - 10 + 'a';
437
  }
503
  }
438
  result[EXPANDED_DIGEST_LENGTH] = 0;
504
  result[digestLen * 2] = 0;
439
  return NS_OK;
505
  return NS_OK;
440
}
506
}
441
nsresult
507
nsresult
442
nsHttpDigestAuth::CalculateHA1(const nsAFlatCString & username,
508
nsHttpDigestAuth::CalculateHA1(const nsAFlatCString & username,
443
                               const nsAFlatCString & password,
509
                               const nsAFlatCString & password,
444
                               const nsAFlatCString & realm,
510
                               const nsAFlatCString & realm,
445
                               uint16_t algorithm,
511
                               uint16_t algorithm,
446
                               const nsAFlatCString & nonce,
512
                               const nsAFlatCString & nonce,
447
                               const nsAFlatCString & cnonce,
513
                               const nsAFlatCString & cnonce,
448
                               char * result)
514
                               char * result)
449
{
515
{
450
  int16_t len = username.Length() + password.Length() + realm.Length() + 2;
516
  int16_t len = username.Length() + password.Length() + realm.Length() + 2;
451
  if (algorithm & ALGO_MD5_SESS) {
452
    int16_t exlen = EXPANDED_DIGEST_LENGTH + nonce.Length() + cnonce.Length() +
453
2;
517
2;
518
  if (algorithm == ALGO_MD5_SESS || algorithm == ALGO_SHA256_SESS) {
519
    int16_t exlen = ExpadedDigestLength(algorithm) + nonce.Length() +
520
      cnonce.Length() + 2;
454
    if (exlen > len)
521
    if (exlen > len)
455
        len = exlen;
522
      len = exlen;
456
  }
523
  }
457
  nsAutoCString contents;
524
  nsAutoCString contents;
458
  contents.SetCapacity(len + 1);
525
  contents.SetCapacity(len + 1);
459
  contents.Assign(username);
526
  contents.Assign(username);
460
  contents.Append(':');
527
  contents.Append(':');
461
  contents.Append(realm);
528
  contents.Append(realm);
462
  contents.Append(':');
529
  contents.Append(':');
463
  contents.Append(password);
530
  contents.Append(password);
464
  nsresult rv;
531
  nsresult rv;
465
  rv = MD5Hash(contents.get(), contents.Length());
532
  rv = DoHash(contents.get(), contents.Length(), algorithm);
466
  if (NS_FAILED(rv))
533
  if (NS_FAILED(rv))
467
    return rv;
534
    return rv;
468
  if (algorithm & ALGO_MD5_SESS) {
535
  if (algorithm == ALGO_MD5_SESS || algorithm == ALGO_SHA256_SESS) {
469
    char part1[EXPANDED_DIGEST_LENGTH+1];
536
         char part1[EXPANDED_DIGEST_SHA256_LENGTH + 1];
470
    ExpandToHex(mHashBuf, part1);
537
         ExpandToHex(mHashBuf, algorithm, part1);
471
    contents.Assign(part1, EXPANDED_DIGEST_LENGTH);
538
       contents.Assign(part1, ExpadedDigestLength(algorithm));
472
    contents.Append(':');
539
    contents.Append(':');
473
    contents.Append(nonce);
540
    contents.Append(nonce);
474
    contents.Append(':');
541
    contents.Append(':');
475
    contents.Append(cnonce);
542
    contents.Append(cnonce);
476
    rv = MD5Hash(contents.get(), contents.Length());
543
    rv = DoHash(contents.get(), contents.Length(), algorithm);
477
    if (NS_FAILED(rv))
544
    if (NS_FAILED(rv))
478
      return rv;
545
      return rv;
479
  }
546
  }
480
  return ExpandToHex(mHashBuf, result);
547
  return ExpandToHex(mHashBuf, algorithm, result);
481
}
548
}
482
nsresult
549
nsresult
483
nsHttpDigestAuth::CalculateHA2(const nsAFlatCString & method,
550
nsHttpDigestAuth::CalculateHA2(const nsAFlatCString & method,
484
                               const nsAFlatCString & path,
551
                               const nsAFlatCString & path,
485
                               uint16_t qop,
552
                               uint16_t qop,
553
                               uint16_t algorithm,
486
                               const char * bodyDigest,
554
                               const char * bodyDigest,
487
                               char * result)
555
                               char * result)
488
{
556
{
489
  uint16_t methodLen = method.Length();
557
  uint16_t methodLen = method.Length();
490
  uint32_t pathLen = path.Length();
558
  uint32_t pathLen = path.Length();
491
  uint32_t len = methodLen + pathLen + 1;
559
  uint32_t len = methodLen + pathLen + 1;
492
  if (qop & QOP_AUTH_INT) {
560
  if (qop & QOP_AUTH_INT) {
493
    len += EXPANDED_DIGEST_LENGTH + 1;
561
           len += ExpadedDigestLength(algorithm) + 1;
494
  }
562
  }
495
  nsAutoCString contents;
563
  nsAutoCString contents;
496
  contents.SetCapacity(len);
564
  contents.SetCapacity(len);
497
  contents.Assign(method);
565
  contents.Assign(method);
498
  contents.Append(':');
566
  contents.Append(':');
499
  contents.Append(path);
567
  contents.Append(path);
500
  if (qop & QOP_AUTH_INT) {
568
  if (qop & QOP_AUTH_INT) {
501
    contents.Append(':');
569
    contents.Append(':');
502
    contents.Append(bodyDigest, EXPANDED_DIGEST_LENGTH);
570
         contents.Append(bodyDigest, ExpadedDigestLength(algorithm));
503
  }
571
  }
504
  nsresult rv = MD5Hash(contents.get(), contents.Length());
572
  nsresult rv = DoHash(contents.get(), contents.Length(), algorithm);
505
  if (NS_SUCCEEDED(rv))
573
  if (NS_SUCCEEDED(rv))
506
    rv = ExpandToHex(mHashBuf, result);
574
    rv = ExpandToHex(mHashBuf, algorithm, result);
507
  return rv;
575
  return rv;
508
}
576
}
509
nsresult
577
nsresult
510
nsHttpDigestAuth::ParseChallenge(const char * challenge,
578
nsHttpDigestAuth::ParseChallenge(const char * challenge,
511
                                 nsACString & realm,
579
                                 nsACString & realm,
512
                                 nsACString & domain,
580
                                 nsACString & domain,
513
                                 nsACString & nonce,
581
                                 nsACString & nonce,
514
                                 nsACString & opaque,
582
                                 nsACString & opaque,
583
                                 nsACString & charset,
515
                                 bool * stale,
584
                                 bool * stale,
516
                                 uint16_t * algorithm,
585
                                 uint16_t * algorithm,
517
                                 uint16_t * qop)
586
                                 uint16_t * qop,
587
                                 uint16_t * userhash)
518
{
588
{
519
  // put an absurd, but maximum, length cap on the challenge so
589
  // put an absurd, but maximum, length cap on the challenge so
520
  // that calculations are 32 bit safe
590
  // that calculations are 32 bit safe
521
  if (strlen(challenge) > 16000000) {
591
  if (strlen(challenge) > 16000000) {
522
    return NS_ERROR_INVALID_ARG;
592
    return NS_ERROR_INVALID_ARG;
523
  }
593
  }
524
  const char *p = challenge + 7; // first 7 characters are "Digest "
594
  const char *p = challenge + 7; // first 7 characters are "Digest "
595
  *userhash = 0;
525
  *stale = false;
596
  *stale = false;
526
  *algorithm = ALGO_MD5; // default is MD5
597
  *algorithm = ALGO_MD5; // default is MD5
527
  *qop = 0;
598
  *qop = 0;
528
  for (;;) {
599
  for (;;) {
529
    while (*p && (*p == ',' || nsCRT::IsAsciiSpace(*p)))
600
    while (*p && (*p == ',' || nsCRT::IsAsciiSpace(*p)))
530
      ++p;
601
      ++p;
531
    if (!*p)
602
    if (!*p)
 Lines 609-643   nsHttpDigestAuth::ParseChallenge(const c Link Here 
609
    {
680
    {
610
      nonce.Assign(challenge+valueStart, valueLength);
681
      nonce.Assign(challenge+valueStart, valueLength);
611
    }
682
    }
612
    else if (nameLength == 6 &&
683
    else if (nameLength == 6 &&
613
        nsCRT::strncasecmp(challenge+nameStart, "opaque", 6) == 0)
684
        nsCRT::strncasecmp(challenge+nameStart, "opaque", 6) == 0)
614
    {
685
    {
615
      opaque.Assign(challenge+valueStart, valueLength);
686
      opaque.Assign(challenge+valueStart, valueLength);
616
    }
687
    }
688
    else if (nameLength == 7 &&
689
             nsCRT::strncasecmp(challenge+nameStart, "charset", 7) == 0)
690
    {
691
      charset.Assign(challenge+valueStart, valueLength);
692
    }
693
    else if (nameLength == 8 &&
694
             nsCRT::strncasecmp(challenge+nameStart, "userhash", 8) == 0)
695
    {
696
      if (nsCRT::strncasecmp(challenge+valueStart, "true", 4) == 0){
697
        *userhash = 2;
698
      }
699
      else{
700
        *userhash = 1;
701
      }
702
    }
617
    else if (nameLength == 5 &&
703
    else if (nameLength == 5 &&
618
        nsCRT::strncasecmp(challenge+nameStart, "stale", 5) == 0)
704
        nsCRT::strncasecmp(challenge+nameStart, "stale", 5) == 0)
619
    {
705
    {
620
      if (nsCRT::strncasecmp(challenge+valueStart, "true", 4) == 0)
706
      if (nsCRT::strncasecmp(challenge+valueStart, "true", 4) == 0)
621
        *stale = true;
707
        *stale = true;
622
      else
708
      else
623
        *stale = false;
709
        *stale = false;
624
    }
710
    }
625
    else if (nameLength == 9 &&
711
    else if (nameLength == 9 &&
626
        nsCRT::strncasecmp(challenge+nameStart, "algorithm", 9) == 0)
712
        nsCRT::strncasecmp(challenge+nameStart, "algorithm", 9) == 0)
627
    {
713
    {
628
      // we want to clear the default, so we use = not |= here
629
      *algorithm = ALGO_SPECIFIED;
714
      *algorithm = ALGO_SPECIFIED;
630
      if (valueLength == 3 &&
715
      if (valueLength == 3 &&
631
          nsCRT::strncasecmp(challenge+valueStart, "MD5", 3) == 0)
716
          nsCRT::strncasecmp(challenge+valueStart, "MD5", 3) == 0) {
632
        *algorithm |= ALGO_MD5;
717
        *algorithm = ALGO_MD5;
718
      }
633
      else if (valueLength == 8 &&
719
      else if (valueLength == 8 &&
634
          nsCRT::strncasecmp(challenge+valueStart, "MD5-sess", 8) == 0)
720
          nsCRT::strncasecmp(challenge+valueStart, "MD5-sess", 8) == 0) {
635
        *algorithm |= ALGO_MD5_SESS;
721
        *algorithm = ALGO_MD5_SESS;
722
      }
723
      else if (valueLength == 7 &&
724
               nsCRT::strncasecmp(challenge+valueStart, "SHA-256", 7) == 0) {
725
        *algorithm = ALGO_SHA256;
726
      }
727
      else if (valueLength == 12 &&
728
               nsCRT::strncasecmp(challenge+valueStart, "SHA-256-sess", 12) ==
729
        *algorithm = ALGO_SHA256_SESS;
730
      }
636
    }
731
    }
637
    else if (nameLength == 3 &&
732
    else if (nameLength == 3 &&
638
        nsCRT::strncasecmp(challenge+nameStart, "qop", 3) == 0)
733
        nsCRT::strncasecmp(challenge+nameStart, "qop", 3) == 0)
639
    {
734
    {
640
      int32_t ipos = valueStart;
735
      int32_t ipos = valueStart;
641
      while (ipos < valueStart+valueLength) {
736
      while (ipos < valueStart+valueLength) {
642
        while (ipos < valueStart+valueLength &&
737
        while (ipos < valueStart+valueLength &&
643
               (nsCRT::IsAsciiSpace(challenge[ipos]) ||
738
               (nsCRT::IsAsciiSpace(challenge[ipos]) ||
 Lines 683-701   nsHttpDigestAuth::AppendQuotedString(con Link Here 
683
    // Escape two syntactically significant characters
778
    // Escape two syntactically significant characters
684
    if (*s == '"' || *s == '\\') {
779
    if (*s == '"' || *s == '\\') {
685
      quoted.Append('\\');
780
      quoted.Append('\\');
686
    }
781
    }
687
    quoted.Append(*s);
782
    quoted.Append(*s);
688
  }
783
  }
689
  // FIXME: bug 41489
690
  // We should RFC2047-encode non-Latin-1 values according to spec
691
  quoted.Append('"');
784
  quoted.Append('"');
692
  aHeaderLine.Append(quoted);
785
  aHeaderLine.Append(quoted);
693
  return NS_OK;
786
  return NS_OK;
694
}
787
}
788
int16_t
789
nsHttpDigestAuth::DigestLength(int16_t algorithm)
790
{
791
  MOZ_ASSERT(algorithm >= ALGO_SPECIFIED && algorithm <= ALGO_SHA256_SESS);
792
  int16_t len;
793
  if (algorithm == ALGO_SHA256 || algorithm == ALGO_SHA256_SESS) {
794
    len = DIGEST_SHA256_LENGTH;
795
  } else {
796
    len = DIGEST_LENGTH;
797
  }
798
  return len;
799
}
800
801
int16_t
802
nsHttpDigestAuth::ExpadedDigestLength(int16_t algorithm)
803
{
804
  return DigestLength(algorithm) * 2;
805
}
806
695
} // namespace net
807
} // namespace net
696
} // namespace mozilla
808
} // namespace mozilla
697
// vim: ts=2 sw=2
809
// vim: ts=2 sw=2
698
-- /e/mozilla-release-8168af494649/netwerk/protocol/http/nsHttpDigestAuth.h2016
810
++ /c/mozilla-release-8168af494649/netwerk/protocol/http/nsHttpDigestAuth.h2016
699
01-19 19:38:08 +0700
700
01-29 04:12:20 +0700
 Lines 13-34    Link Here 
13
#include "mozilla/Attributes.h"
13
#include "mozilla/Attributes.h"
14
class nsICryptoHash;
14
class nsICryptoHash;
15
namespace mozilla { namespace net {
15
namespace mozilla { namespace net {
16
#define ALGO_SPECIFIED 0x01
16
#define ALGO_SPECIFIED 0x01
17
#define ALGO_MD5 0x02
17
#define ALGO_MD5 0x02
18
#define ALGO_MD5_SESS 0x04
18
#define ALGO_MD5_SESS 0x03
19
#define ALGO_SHA256 0x04
20
#define ALGO_SHA256_SESS 0x05
19
#define QOP_AUTH 0x01
21
#define QOP_AUTH 0x01
20
#define QOP_AUTH_INT 0x02
22
#define QOP_AUTH_INT 0x02
21
#define DIGEST_LENGTH 16
23
#define DIGEST_LENGTH 16
22
#define EXPANDED_DIGEST_LENGTH 32
24
#define DIGEST_SHA256_LENGTH 32
25
#define EXPANDED_DIGEST_SHA256_LENGTH 64
23
#define NONCE_COUNT_LENGTH 8
26
#define NONCE_COUNT_LENGTH 8
24
//-----------------------------------------------------------------------------
27
//-----------------------------------------------------------------------------
25
// nsHttpDigestAuth
28
// nsHttpDigestAuth
26
//-----------------------------------------------------------------------------
29
//-----------------------------------------------------------------------------
27
class nsHttpDigestAuth final : public nsIHttpAuthenticator
30
class nsHttpDigestAuth final : public nsIHttpAuthenticator
28
{
31
{
 Lines 36-95   class nsHttpDigestAuth final : public ns Link Here 
36
    NS_DECL_ISUPPORTS
39
    NS_DECL_ISUPPORTS
37
    NS_DECL_NSIHTTPAUTHENTICATOR
40
    NS_DECL_NSIHTTPAUTHENTICATOR
38
    nsHttpDigestAuth();
41
    nsHttpDigestAuth();
39
  protected:
42
  protected:
40
    ~nsHttpDigestAuth();
43
    ~nsHttpDigestAuth();
41
    nsresult ExpandToHex(const char * digest, char * result);
44
    nsresult ExpandToHex(const char * digest, int16_t algorithm, char * result)
42
    nsresult CalculateResponse(const char * ha1_digest,
45
    nsresult CalculateResponse(const char * ha1_digest,
43
                               const char * ha2_digest,
46
                               const char * ha2_digest,
44
                               const nsAFlatCString & nonce,
47
                               const nsAFlatCString & nonce,
45
                               uint16_t qop,
48
                               uint16_t qop,
49
                               uint16_t algorithm,
46
                               const char * nonce_count,
50
                               const char * nonce_count,
47
                               const nsAFlatCString & cnonce,
51
                               const nsAFlatCString & cnonce,
48
                               char * result);
52
                               char * result);
49
    nsresult CalculateHA1(const nsAFlatCString & username,
53
    nsresult CalculateHA1(const nsAFlatCString & username,
50
                          const nsAFlatCString & password,
54
                          const nsAFlatCString & password,
51
                          const nsAFlatCString & realm,
55
                          const nsAFlatCString & realm,
52
                          uint16_t algorithm,
56
                          uint16_t algorithm,
53
                          const nsAFlatCString & nonce,
57
                          const nsAFlatCString & nonce,
54
                          const nsAFlatCString & cnonce,
58
                          const nsAFlatCString & cnonce,
55
                          char * result);
59
                          char * result);
56
    nsresult CalculateHA2(const nsAFlatCString & http_method,
60
    nsresult CalculateHA2(const nsAFlatCString & http_method,
57
                          const nsAFlatCString & http_uri_path,
61
                          const nsAFlatCString & http_uri_path,
58
                          uint16_t qop,
62
                          uint16_t qop,
63
                          uint16_t algorithm,
59
                          const char * body_digest,
64
                          const char * body_digest,
60
                          char * result);
65
                          char * result);
61
    nsresult ParseChallenge(const char * challenge,
66
    nsresult ParseChallenge(const char * challenge,
62
                            nsACString & realm,
67
                            nsACString & realm,
63
                            nsACString & domain,
68
                            nsACString & domain,
64
                            nsACString & nonce,
69
                            nsACString & nonce,
65
                            nsACString & opaque,
70
                            nsACString & opaque,
71
                            nsACString & charset,
66
                            bool * stale,
72
                            bool * stale,
67
                            uint16_t * algorithm,
73
                            uint16_t * algorithm,
68
                            uint16_t * qop);
74
                            uint16_t * qop,
75
                            uint16_t * userhash);
69
    // result is in mHashBuf
76
    // result is in mHashBuf
70
    nsresult MD5Hash(const char *buf, uint32_t len);
77
    nsresult DoHash(const char *buf, uint32_t len, uint16_t algorithm);
71
    nsresult GetMethodAndPath(nsIHttpAuthenticableChannel *,
78
    nsresult GetMethodAndPath(nsIHttpAuthenticableChannel *,
72
                              bool, nsCString &, nsCString &);
79
                              bool, nsCString &, nsCString &);
73
    // append the quoted version of value to aHeaderLine
80
    // append the quoted version of value to aHeaderLine
74
    nsresult AppendQuotedString(const nsACString & value,
81
    nsresult AppendQuotedString(const nsACString & value,
75
                                nsACString & aHeaderLine);
82
                                nsACString & aHeaderLine);
83
    int16_t DigestLength(int16_t algorithm);
84
    int16_t ExpadedDigestLength(int16_t algorithm);
76
  protected:
85
  protected:
77
    nsCOMPtr<nsICryptoHash>        mVerifier;
86
    nsCOMPtr<nsICryptoHash>        mVerifier;
78
    char                           mHashBuf[DIGEST_LENGTH];
87
    char                           mHashBuf[DIGEST_SHA256_LENGTH];
79
};
88
};
80
} // namespace net
89
} // namespace net
81
} // namespace mozilla
90
} // namespace mozilla

Return to bug 41489