diff --git a/extensions/auth/nsHttpNegotiateAuth.cpp b/extensions/auth/nsHttpNegotiateAuth.cpp index 1e1d9c57a3f..598193aec57 100644 --- a/extensions/auth/nsHttpNegotiateAuth.cpp +++ b/extensions/auth/nsHttpNegotiateAuth.cpp @@ -221,12 +221,15 @@ nsHttpNegotiateAuth::GenerateCredentials(nsIHttpChannel *httpChannel, const PRUnichar *password, nsISupports **sessionState, nsISupports **continuationState, + PRUint32 *flags, char **creds) { // ChallengeReceived must have been called previously. nsIAuthModule *module = (nsIAuthModule *) *continuationState; NS_ENSURE_TRUE(module, NS_ERROR_NOT_INITIALIZED); + *flags = USING_INTERNAL_IDENTITY; + LOG(("nsHttpNegotiateAuth::GenerateCredentials() [challenge=%s]\n", challenge)); NS_ASSERTION(creds, "null param"); diff --git a/netwerk/protocol/http/public/nsIHttpAuthenticator.idl b/netwerk/protocol/http/public/nsIHttpAuthenticator.idl index 7f165696e87..4798b725212 100644 --- a/netwerk/protocol/http/public/nsIHttpAuthenticator.idl +++ b/netwerk/protocol/http/public/nsIHttpAuthenticator.idl @@ -51,7 +51,7 @@ interface nsIHttpChannel; * where is the lower-cased value of the authentication scheme * found in the server challenge per the rules of RFC 2617. */ -[scriptable, uuid(0f331436-8bc8-4c68-a124-d0253a19d06f)] +[scriptable, uuid(36402c9d-c280-4860-b4b0-2e7eb35b0aaf)] interface nsIHttpAuthenticator : nsISupports { /** @@ -118,6 +118,8 @@ interface nsIHttpAuthenticator : nsISupports * generateCredentials, assuming multiple calls are required * to authenticate. this state is held for at most the lifetime of * the channel. + * @param aFlags + * authenticator may return one of the generate flags bellow. */ string generateCredentials(in nsIHttpChannel aChannel, in string aChallenge, @@ -126,7 +128,20 @@ interface nsIHttpAuthenticator : nsISupports in wstring aUser, in wstring aPassword, inout nsISupports aSessionState, - inout nsISupports aContinuationState); + inout nsISupports aContinuationState, + out unsigned long aFlags); + + /** + * Generate flags + */ + + /** + * Indicates that the authenticator has used an out-of-band or internal + * source of identity and tells the consumer that it must not cache + * the returned identity because it might not be valid and would overwrite + * the cached identity. See bug 542318 comment 32. + */ + const unsigned long USING_INTERNAL_IDENTITY = (1<<0); /** * Flags defining various properties of the authenticator. diff --git a/netwerk/protocol/http/src/nsHttpAuthCache.cpp b/netwerk/protocol/http/src/nsHttpAuthCache.cpp index cd3a7e36d7b..58b76d2294c 100644 --- a/netwerk/protocol/http/src/nsHttpAuthCache.cpp +++ b/netwerk/protocol/http/src/nsHttpAuthCache.cpp @@ -146,7 +146,7 @@ nsHttpAuthCache::SetAuthEntry(const char *scheme, const char *realm, const char *creds, const char *challenge, - const nsHttpAuthIdentity &ident, + const nsHttpAuthIdentity *ident, nsISupports *metadata) { nsresult rv; @@ -387,7 +387,7 @@ nsHttpAuthEntry::Set(const char *path, const char *realm, const char *creds, const char *chall, - const nsHttpAuthIdentity &ident, + const nsHttpAuthIdentity *ident, nsISupports *metadata) { char *newRealm, *newCreds, *newChall; @@ -415,7 +415,17 @@ nsHttpAuthEntry::Set(const char *path, memcpy(newChall, chall, challLen); newChall[challLen] = 0; - nsresult rv = mIdent.Set(ident); + nsresult rv; + if (ident) { + rv = mIdent.Set(*ident); + } + else if (mIdent.IsEmpty()) { + // If we are not given an identity and our cached identity has not been + // initialized yet (so is currently empty), initialize it now by + // filling it with nulls. We need to do that because consumers expect + // that mIdent is initialized after this function returns. + rv = mIdent.Set(nsnull, nsnull, nsnull); + } if (NS_FAILED(rv)) { free(newRealm); return rv; @@ -512,7 +522,7 @@ nsHttpAuthNode::SetAuthEntry(const char *path, const char *realm, const char *creds, const char *challenge, - const nsHttpAuthIdentity &ident, + const nsHttpAuthIdentity *ident, nsISupports *metadata) { // look for an entry with a matching realm diff --git a/netwerk/protocol/http/src/nsHttpAuthCache.h b/netwerk/protocol/http/src/nsHttpAuthCache.h index 46cfd4e2ed2..0cf6d2938cc 100644 --- a/netwerk/protocol/http/src/nsHttpAuthCache.h +++ b/netwerk/protocol/http/src/nsHttpAuthCache.h @@ -127,7 +127,7 @@ private: const char *realm, const char *creds, const char *challenge, - const nsHttpAuthIdentity &ident, + const nsHttpAuthIdentity *ident, nsISupports *metadata) : mRoot(nsnull) , mTail(nsnull) @@ -141,7 +141,7 @@ private: const char *realm, const char *creds, const char *challenge, - const nsHttpAuthIdentity &ident, + const nsHttpAuthIdentity *ident, nsISupports *metadata); nsHttpAuthIdentity mIdent; @@ -181,7 +181,7 @@ private: const char *realm, const char *credentials, const char *challenge, - const nsHttpAuthIdentity &ident, + const nsHttpAuthIdentity *ident, nsISupports *metadata); void ClearAuthEntry(const char *realm); @@ -237,7 +237,7 @@ public: const char *realm, const char *credentials, const char *challenge, - const nsHttpAuthIdentity &ident, + const nsHttpAuthIdentity *ident, nsISupports *metadata); void ClearAuthEntry(const char *scheme, diff --git a/netwerk/protocol/http/src/nsHttpAuthManager.cpp b/netwerk/protocol/http/src/nsHttpAuthManager.cpp index 4238774fdb5..760de9681c6 100644 --- a/netwerk/protocol/http/src/nsHttpAuthManager.cpp +++ b/netwerk/protocol/http/src/nsHttpAuthManager.cpp @@ -135,7 +135,7 @@ nsHttpAuthManager::SetAuthIdentity(const nsACString & aScheme, PromiseFlatCString(aRealm).get(), nsnull, // credentials nsnull, // challenge - ident, + &ident, nsnull); // metadata } diff --git a/netwerk/protocol/http/src/nsHttpBasicAuth.cpp b/netwerk/protocol/http/src/nsHttpBasicAuth.cpp index 8eeadda9937..a86342790ae 100644 --- a/netwerk/protocol/http/src/nsHttpBasicAuth.cpp +++ b/netwerk/protocol/http/src/nsHttpBasicAuth.cpp @@ -92,6 +92,7 @@ nsHttpBasicAuth::GenerateCredentials(nsIHttpChannel *httpChannel, const PRUnichar *password, nsISupports **sessionState, nsISupports **continuationState, + PRUint32 *aFlags, char **creds) { @@ -99,6 +100,8 @@ nsHttpBasicAuth::GenerateCredentials(nsIHttpChannel *httpChannel, NS_ENSURE_ARG_POINTER(creds); + *aFlags = 0; + // we only know how to deal with Basic auth for http. PRBool isBasicAuth = !PL_strncasecmp(challenge, "basic", 5); NS_ENSURE_TRUE(isBasicAuth, NS_ERROR_UNEXPECTED); diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index d66e1d4842c..b637773c816 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -3112,6 +3112,7 @@ nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth, continuationState = &mAuthContinuationState; } + PRUint32 generateFlags; rv = auth->GenerateCredentials(this, challenge, proxyAuth, @@ -3120,6 +3121,7 @@ nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth, ident.Password(), &ss, &*continuationState, + &generateFlags, result); sessionState.swap(ss); @@ -3137,6 +3139,9 @@ nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth, PRBool saveChallenge = 0 != (authFlags & nsIHttpAuthenticator::REUSABLE_CHALLENGE); + PRBool saveIdentity = + 0 == (generateFlags & nsIHttpAuthenticator::USING_INTERNAL_IDENTITY); + // this getter never fails nsHttpAuthCache *authCache = gHttpHandler->AuthCache(); @@ -3149,7 +3154,8 @@ nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth, rv = authCache->SetAuthEntry(scheme, host, port, directory, realm, saveCreds ? *result : nsnull, saveChallenge ? challenge : nsnull, - ident, sessionState); + saveIdentity ? &ident : nsnull, + sessionState); return rv; } diff --git a/netwerk/protocol/http/src/nsHttpDigestAuth.cpp b/netwerk/protocol/http/src/nsHttpDigestAuth.cpp index 092bbdef046..22fe10d08db 100644 --- a/netwerk/protocol/http/src/nsHttpDigestAuth.cpp +++ b/netwerk/protocol/http/src/nsHttpDigestAuth.cpp @@ -205,6 +205,7 @@ nsHttpDigestAuth::GenerateCredentials(nsIHttpChannel *httpChannel, const PRUnichar *password, nsISupports **sessionState, nsISupports **continuationState, + PRUint32 *aFlags, char **creds) { @@ -212,6 +213,8 @@ nsHttpDigestAuth::GenerateCredentials(nsIHttpChannel *httpChannel, NS_ENSURE_ARG_POINTER(creds); + *aFlags = 0; + PRBool isDigestAuth = !PL_strncasecmp(challenge, "digest ", 7); NS_ENSURE_TRUE(isDigestAuth, NS_ERROR_UNEXPECTED); diff --git a/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp b/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp index 3022dc3d126..4b8bec851de 100644 --- a/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp +++ b/netwerk/protocol/http/src/nsHttpNTLMAuth.cpp @@ -324,12 +324,21 @@ nsHttpNTLMAuth::GenerateCredentials(nsIHttpChannel *httpChannel, const PRUnichar *pass, nsISupports **sessionState, nsISupports **continuationState, + PRUint32 *aFlags, char **creds) { LOG(("nsHttpNTLMAuth::GenerateCredentials\n")); *creds = nsnull; + *aFlags = 0; + + // if user or password is empty, ChallengeReceived returned + // identityInvalid = PR_FALSE, that means we are using default user + // credentials; see nsAuthSSPI::Init method for explanation of this + // condition + if (!user || !pass) + *aFlags = USING_INTERNAL_IDENTITY; nsresult rv; nsCOMPtr module = do_QueryInterface(*continuationState, &rv);