fixes bug 256949 "browser not using the right credentials for proxy authentication" r=cneberg sr=bzbarsky

This commit is contained in:
darin%meer.net 2004-10-17 20:19:47 +00:00
parent 5180cb29d8
commit ae50a08b3d
3 changed files with 73 additions and 18 deletions

View File

@ -2106,10 +2106,14 @@ nsHttpChannel::GetCredentials(const char *challenges,
PRBool proxyAuth,
nsAFlatCString &creds)
{
nsCAutoString challenge, scheme;
nsCOMPtr<nsIHttpAuthenticator> auth;
nsCAutoString challenge;
nsCString authType; // force heap allocation to enable string sharing since
// we'll be assigning this value into mAuthType.
nsresult rv = NS_ERROR_NOT_AVAILABLE;
PRBool gotCreds = PR_FALSE;
// figure out which challenge we can handle and which authenticator to use.
for (const char *eol = challenges - 1; eol; ) {
@ -2121,8 +2125,17 @@ nsHttpChannel::GetCredentials(const char *challenges,
else
challenge.Assign(p);
rv = ParseChallenge(challenge.get(), scheme, getter_AddRefs(auth));
rv = GetAuthenticator(challenge.get(), authType, getter_AddRefs(auth));
if (NS_SUCCEEDED(rv)) {
//
// if we've already selected an auth type from a previous challenge
// received while processing this channel, then skip others until
// we find a challenge corresponding to the previously tried auth
// type.
//
if (!mAuthType.IsEmpty() && authType != mAuthType)
continue;
//
// we allow the routines to run all the way through before we
// decide if they are valid.
@ -2137,12 +2150,26 @@ nsHttpChannel::GetCredentials(const char *challenges,
// if a particular auth method only knows 1 thing, like a
// non-identity based authentication method)
//
rv = GetCredentialsForChallenge(challenge.get(), scheme.get(),
rv = GetCredentialsForChallenge(challenge.get(), authType.get(),
proxyAuth, auth, creds);
if (NS_SUCCEEDED(rv))
if (NS_SUCCEEDED(rv)) {
gotCreds = PR_TRUE;
mAuthType = authType;
break;
}
// reset the auth type and continuation state
mAuthType.Truncate();
NS_IF_RELEASE(mAuthContinuationState);
}
}
if (!gotCreds && !mAuthType.IsEmpty()) {
// looks like we never found the auth type we were looking for.
// reset the auth type and continuation state, and try again.
mAuthType.Truncate();
NS_IF_RELEASE(mAuthContinuationState);
rv = GetCredentials(challenges, proxyAuth, creds);
}
return rv;
}
@ -2238,6 +2265,8 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
sessionStateGrip.swap(sessionState);
if (NS_FAILED(rv)) return rv;
LOG((" identity invalid = %d\n", identityInvalid));
if (identityInvalid) {
if (entry) {
if (ident->Equals(entry->Identity())) {
@ -2317,11 +2346,11 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
}
nsresult
nsHttpChannel::ParseChallenge(const char *challenge,
nsCString &authType,
nsIHttpAuthenticator **auth)
nsHttpChannel::GetAuthenticator(const char *challenge,
nsCString &authType,
nsIHttpAuthenticator **auth)
{
LOG(("nsHttpChannel::ParseChallenge [this=%x]\n", this));
LOG(("nsHttpChannel::GetAuthenticator [this=%x]\n", this));
const char *p;
@ -2614,7 +2643,6 @@ nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
const char *path,
nsHttpAuthIdentity &ident)
{
nsCOMPtr<nsIHttpAuthenticator> auth;
nsHttpAuthEntry *entry = nsnull;
nsresult rv;
@ -2650,8 +2678,9 @@ nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
// credentials. if the identity is from the URI, then we cannot use
// the stored credentials.
if ((!creds[0] || identFromURI) && challenge[0]) {
nsCOMPtr<nsIHttpAuthenticator> auth;
nsCAutoString unused;
rv = ParseChallenge(challenge, unused, getter_AddRefs(auth));
rv = GetAuthenticator(challenge, unused, getter_AddRefs(auth));
if (NS_SUCCEEDED(rv)) {
PRBool proxyAuth = (header == nsHttp::Proxy_Authorization);
rv = GenCredsAndSetEntry(auth, proxyAuth, scheme, host, port, path,
@ -2659,6 +2688,9 @@ nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
entry->mMetaData, getter_Copies(temp));
if (NS_SUCCEEDED(rv))
creds = temp.get();
// make sure the continuation state is null since we do not
// support mixing preemptive and 'multirequest' authentication.
NS_IF_RELEASE(mAuthContinuationState);
}
}
if (creds[0]) {

View File

@ -169,7 +169,7 @@ private:
nsresult GenCredsAndSetEntry(nsIHttpAuthenticator *, PRBool proxyAuth, const char *scheme, const char *host, PRInt32 port, const char *dir, const char *realm, const char *challenge, const nsHttpAuthIdentity &ident, nsCOMPtr<nsISupports> &session, char **result);
nsresult GetCredentials(const char *challenges, PRBool proxyAuth, nsAFlatCString &creds);
nsresult GetCredentialsForChallenge(const char *challenge, const char *scheme, PRBool proxyAuth, nsIHttpAuthenticator *auth, nsAFlatCString &creds);
nsresult ParseChallenge(const char *challenge, nsCString &scheme, nsIHttpAuthenticator **auth);
nsresult GetAuthenticator(const char *challenge, nsCString &scheme, nsIHttpAuthenticator **auth);
void ParseRealm(const char *challenge, nsACString &realm);
void GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&);
nsresult PromptForIdentity(const char *scheme, const char *host, PRInt32 port, PRBool proxyAuth, const char *realm, const char *authType, PRUint32 authFlags, nsHttpAuthIdentity &);
@ -227,6 +227,7 @@ private:
// auth specific data
nsISupports *mAuthContinuationState;
nsCString mAuthType;
nsHttpAuthIdentity mIdent;
nsHttpAuthIdentity mProxyIdent;

View File

@ -196,6 +196,15 @@ CanUseSysNTLM(nsIHttpChannel *channel, PRBool isProxyAuth)
return PR_FALSE;
}
// Dummy class for session state object. This class doesn't hold any data.
// Instead we use its existance as a flag. See ChallengeReceived.
class nsNTLMSessionState : public nsISupports
{
public:
NS_DECL_ISUPPORTS
};
NS_IMPL_ISUPPORTS0(nsNTLMSessionState);
#endif
//-----------------------------------------------------------------------------
@ -217,8 +226,14 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpChannel *channel,
*identityInvalid = PR_FALSE;
// start new auth sequence if challenge is exactly "NTLM"
if (PL_strcasecmp(challenge, "NTLM") == 0) {
nsCOMPtr<nsIAuthModule> module;
nsCOMPtr<nsISupports> module;
#ifdef XP_WIN
//
// our session state is non-null to indicate that we've flagged
// this auth domain as not accepting the system's default login.
//
PRBool trySysNTLM = (*sessionState == nsnull);
//
// on windows, we may have access to the built-in SSPI library,
// which could be used to authenticate the user without prompting.
@ -229,13 +244,22 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpChannel *channel,
// may send a weak LMv1 hash of the user's password, we cannot just
// send it to any server.
//
if (!*continuationState && CanUseSysNTLM(channel, isProxyAuth))
if (trySysNTLM && !*continuationState && CanUseSysNTLM(channel, isProxyAuth))
module = do_CreateInstance(NS_AUTH_MODULE_CONTRACTID_PREFIX "sys-ntlm");
// it's possible that there is no ntlm-sspi auth module...
if (!module)
#endif
if (!module) {
if (!*sessionState) {
// remember the fact that we cannot use the "sys-ntlm" module,
// so we don't ever bother trying again for this auth domain.
*sessionState = new nsNTLMSessionState();
if (!*sessionState)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*sessionState);
}
#else
{
#endif
module = do_CreateInstance(NS_AUTH_MODULE_CONTRACTID_PREFIX "ntlm");
// prompt user for domain, username, and password...
@ -248,9 +272,7 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpChannel *channel,
// non-null continuation state implies that we failed to authenticate.
// blow away the old authentication state, and use the new one.
NS_IF_RELEASE(*continuationState);
NS_ADDREF(*continuationState = module);
module.swap(*continuationState);
}
return NS_OK;
}