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