/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// HttpLog.h should generally be included first #include"HttpLog.h"
// Cache a reference to the nsICryptoHash instance since we'll be calling // this function frequently. if (!mVerifier) {
mVerifier = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv); if (NS_FAILED(rv)) {
LOG(("nsHttpDigestAuth: no crypto hash!\n")); return rv;
}
}
nsresult nsHttpDigestAuth::GetMethodAndPath(
nsIHttpAuthenticableChannel* authChannel, bool isProxyAuth,
nsCString& httpMethod, nsCString& path) {
nsresult rv, rv2;
nsCOMPtr<nsIURI> uri;
rv = authChannel->GetURI(getter_AddRefs(uri)); if (NS_SUCCEEDED(rv)) { bool proxyMethodIsConnect;
rv = authChannel->GetProxyMethodIsConnect(&proxyMethodIsConnect); if (NS_SUCCEEDED(rv)) { if (proxyMethodIsConnect && isProxyAuth) {
httpMethod.AssignLiteral("CONNECT"); // // generate hostname:port string. (unfortunately uri->GetHostPort // leaves out the port if it matches the default value, so we can't // just call it.) //
int32_t port;
rv = uri->GetAsciiHost(path);
rv2 = uri->GetPort(&port); if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv2)) {
path.Append(':');
path.AppendInt(port < 0 ? NS_HTTPS_DEFAULT_PORT : port);
}
} else {
rv = authChannel->GetRequestMethod(httpMethod);
rv2 = uri->GetPathQueryRef(path); if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv2)) { // // strip any fragment identifier from the URL path. //
int32_t ref = path.RFindChar('#'); if (ref != kNotFound) path.Truncate(ref); // // make sure we escape any UTF-8 characters in the URI path. the // digest auth uri attribute needs to match the request-URI. // // XXX we should really ask the HTTP channel for this string // instead of regenerating it here. //
nsAutoCString buf;
rv = NS_EscapeURL(path, esc_OnlyNonASCII | esc_Spaces, buf,
mozilla::fallible); if (NS_SUCCEEDED(rv)) {
path = buf;
}
}
}
}
} return rv;
}
if (!(algorithm &
(ALGO_MD5 | ALGO_MD5_SESS | ALGO_SHA256 | ALGO_SHA256_SESS))) { // they asked for an algorithm that we do not support yet (like SHA-512/256)
NS_WARNING("unsupported algorithm requested by Digest authentication"); return NS_ERROR_NOT_IMPLEMENTED;
}
if (NS_FAILED(rv)) return rv;
// if the challenge has the "stale" flag set, then the user identity is not // necessarily invalid. by returning FALSE here we can suppress username // and password prompting that usually accompanies a 401/407 challenge.
*result = !stale;
// clear any existing nonce_count since we have a new challenge.
NS_IF_RELEASE(*sessionState); return NS_OK;
}
if (qop & QOP_AUTH_INT) { // we do not support auth-int "quality of protection" currently
qop &= ~QOP_AUTH_INT;
NS_WARNING( "no support for Digest authentication with data integrity quality of " "protection");
/* TODO: to support auth-int, we need to get an MD5 digest of * TODO: the data uploaded with this request. * TODO: however, i am not sure how to read in the file in without * TODO: disturbing the channel''s use of it. do i need to copy it * TODO: somehow?
*/ #if 0 if (http_channel != nullptr)
{
nsIInputStream * upload;
nsCOMPtr<nsIUploadChannel> uc = do_QueryInterface(http_channel);
NS_ENSURE_TRUE(uc, NS_ERROR_UNEXPECTED);
uc->GetUploadStream(&upload); if (upload) { char * upload_buffer; int upload_buffer_length = 0; //TODO: read input stream into buffer constchar * digest = (constchar*)
nsNetwerkMD5Digest(upload_buffer, upload_buffer_length);
ExpandToHex(digest, upload_data_digest);
NS_RELEASE(upload);
}
} #endif
}
if (!(algorithm &
(ALGO_MD5 | ALGO_MD5_SESS | ALGO_SHA256 | ALGO_SHA256_SESS))) { // they asked only for algorithms that we do not support
NS_WARNING("unsupported algorithm requested by Digest authentication"); return NS_ERROR_NOT_IMPLEMENTED;
}
// // the following are for increasing security. see RFC 2617 for more // information. // // nonce_count allows the server to keep track of auth challenges (to help // prevent spoofing). we increase this count every time. // char nonce_count[NONCE_COUNT_LENGTH + 1] = "00000001"; // in hex if (*sessionState) {
nsCOMPtr<nsISupportsPRUint32> v(do_QueryInterface(*sessionState)); if (v) {
uint32_t nc;
v->GetData(&nc);
SprintfLiteral(nonce_count, "%08x", ++nc);
v->SetData(nc);
}
} else {
nsCOMPtr<nsISupportsPRUint32> v(
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID)); if (v) {
v->SetData(1);
v.forget(sessionState);
}
}
LOG((" nonce_count=%s\n", nonce_count));
// // this lets the client verify the server response (via a server // returned Authentication-Info header). also used for session info. //
nsAutoCString cnonce;
nsTArray<uint8_t> cnonceBuf;
cnonceBuf.SetLength(StaticPrefs::network_http_digest_auth_cnonce_length() /
2);
PK11_GenerateRandom(reinterpret_cast<unsignedchar*>(cnonceBuf.Elements()),
cnonceBuf.Length()); for (auto byte : cnonceBuf) {
cnonce.AppendPrintf("%02x", byte);
}
LOG((" cnonce=%s\n", cnonce.get()));
NS_IMETHODIMP
nsHttpDigestAuth::GetAuthFlags(uint32_t* flags) {
*flags = REQUEST_BASED | REUSABLE_CHALLENGE | IDENTITY_ENCRYPTED; // // NOTE: digest auth credentials must be uniquely computed for each request, // so we do not set the REUSABLE_CREDENTIALS flag. // return NS_OK;
}
nsresult nsHttpDigestAuth::ParseChallenge(const nsACString& aChallenge,
nsACString& realm, nsACString& domain,
nsACString& nonce, nsACString& opaque, bool* stale, uint16_t* algorithm,
uint16_t* qop) { // put an absurd, but maximum, length cap on the challenge so // that calculations are 32 bit safe if (aChallenge.Length() > 16000000) { return NS_ERROR_INVALID_ARG;
}
constchar* challenge = aChallenge.BeginReading(); constchar* end = aChallenge.EndReading(); constchar* p = challenge + 6; // first 6 characters are "Digest" if (p >= end) { return NS_ERROR_INVALID_ARG;
}
// // Encode string according to RFC 2616 quoted-string production //
quoted.Append('"'); for (; s != e; ++s) { // // CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)> // if (*s <= 31 || *s == 127) { return NS_ERROR_FAILURE;
}
// Escape two syntactically significant characters if (*s == '"' || *s == '\\') {
quoted.Append('\\');
}
quoted.Append(*s);
} // FIXME: bug 41489 // We should RFC2047-encode non-Latin-1 values according to spec
quoted.Append('"');
aHeaderLine.Append(quoted); return NS_OK;
}
} // namespace net
} // namespace mozilla
// vim: ts=2 sw=2
¤ Dauer der Verarbeitung: 0.31 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.