Bug 542318 - Firefox 3.6 needs constant re-auths when connecting through NTLM proxy with credentials different from currently logged in Windows user, r=bz

This commit is contained in:
Honza Bambas 2010-02-06 16:06:48 +01:00
parent 648f658133
commit d07221c060
9 changed files with 61 additions and 12 deletions

View File

@ -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");

View File

@ -51,7 +51,7 @@ interface nsIHttpChannel;
* where <auth-scheme> 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.

View File

@ -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

View File

@ -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,

View File

@ -135,7 +135,7 @@ nsHttpAuthManager::SetAuthIdentity(const nsACString & aScheme,
PromiseFlatCString(aRealm).get(),
nsnull, // credentials
nsnull, // challenge
ident,
&ident,
nsnull); // metadata
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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<nsIAuthModule> module = do_QueryInterface(*continuationState, &rv);