fixes bug 226278 "HTTP authentication cache should include URI scheme in its key" r=cneberg@sandia.gov sr=dveditz a=chofmann

This commit is contained in:
darin%meer.net 2004-04-07 23:34:35 +00:00
Родитель 1c888c7563
Коммит 4e96b346fa
7 изменённых файлов: 248 добавлений и 129 удалений

Просмотреть файл

@ -143,7 +143,7 @@ nsJVMAuthTools::GetAuthenticationInfo(const char* protocol,
const char* realm,
nsIAuthenticationInfo **_retval)
{
if (!protocol || !host || !realm)
if (!protocol || !host || !scheme || !realm)
return NS_ERROR_INVALID_ARG;
if (!PL_strcasecmp(protocol, "HTTP") && !PL_strcasecmp(protocol, "HTTPS"))
@ -153,29 +153,32 @@ nsJVMAuthTools::GetAuthenticationInfo(const char* protocol,
if (!authManager)
return NS_ERROR_FAILURE;
nsDependentCString protocolString(protocol);
nsDependentCString hostString(host);
nsDependentCString schemeString(scheme);
nsDependentCString realmString(realm);
nsAutoString domainString, username, password;
nsresult rv = authManager->GetAuthIdentity(hostString,
nsresult rv = authManager->GetAuthIdentity(protocolString,
hostString,
port,
schemeString,
realmString,
nsCString(),
EmptyCString(),
domainString,
username,
password);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
else {
nsAuthenticationInfoImp* authInfo = new nsAuthenticationInfoImp(
ToNewUTF8String(username),
ToNewUTF8String(password));
NS_ENSURE_TRUE(authInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(authInfo);
*_retval = authInfo;
return NS_OK;
}
nsAuthenticationInfoImp* authInfo = new nsAuthenticationInfoImp(
ToNewUTF8String(username),
ToNewUTF8String(password));
NS_ENSURE_TRUE(authInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(authInfo);
*_retval = authInfo;
return NS_OK;
}
NS_METHOD
@ -187,7 +190,7 @@ nsJVMAuthTools::SetAuthenticationInfo(const char* protocol,
const char *username,
const char *password)
{
if (!protocol || !host || !realm)
if (!protocol || !host || !scheme || !realm)
return NS_ERROR_INVALID_ARG;
if (!PL_strcasecmp(protocol, "HTTP") && !PL_strcasecmp(protocol, "HTTPS"))
@ -197,13 +200,17 @@ nsJVMAuthTools::SetAuthenticationInfo(const char* protocol,
if (!authManager)
return NS_ERROR_FAILURE;
nsDependentCString protocolString(protocol);
nsDependentCString hostString(host);
nsDependentCString schemeString(scheme);
nsDependentCString realmString(realm);
nsresult rv = authManager->SetAuthIdentity(hostString,
nsresult rv = authManager->SetAuthIdentity(protocolString,
hostString,
port,
schemeString,
realmString,
nsCString(),
EmptyCString(),
nsString(),
NS_ConvertUTF8toUCS2(username),
NS_ConvertUTF8toUCS2(password));

Просмотреть файл

@ -17,61 +17,97 @@
* by Sun Microsystem. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@netscape.com>
* Darin Fisher <darin@meer.net>
* Louie Zhao <louie.zhao@sun.com>
*/
#include "nsISupports.idl"
[scriptable, uuid(81328d02-74df-4724-8a53-8fac43841c5c)]
/**
* nsIHttpAuthManager
*
* This service provides access to cached HTTP authentication
* user credentials (domain, username, password) for sites
* visited during the current browser session.
*
* This interface exists to provide other HTTP stacks with the
* ability to share HTTP authentication credentials with Necko.
* This is currently used by the Java plugin (version 1.5 and
* higher) to avoid duplicate authentication prompts when the
* Java client fetches content from a HTTP site that the user
* has already logged into.
*/
[scriptable, uuid(7ce8e9d1-8b4b-4883-a307-66fe12a50153)]
interface nsIHttpAuthManager : nsISupports
{
/**
* Lookup auth identity.
*
* @param hostPort
* the "host:port" of the server issuing a challenge.
* @param realm
* @param aScheme
* the URL scheme (e.g., "http"). NOTE: for proxy authentication,
* this should be "http" (this includes authentication for SSL
* tunneling).
* @param aHost
* the host of the server issuing a challenge (ASCII only).
* @param aPort
* the port of the server issuing a challenge.
* @param aAuthType
* optional string identifying auth type used (e.g., "basic")
* @param aRealm
* optional string identifying auth realm.
* @param path
* @param aPath
* optional string identifying auth path. empty for proxy auth.
* @param userDomain
* @param aUserDomain
* return value containing user domain.
* @param userName
* @param aUserName
* return value containing user name.
* @param userPassword
* @param aUserPassword
* return value containing user password.
*/
void getAuthIdentity(in ACString aHost,
void getAuthIdentity(in ACString aScheme,
in ACString aHost,
in PRInt32 aPort,
in ACString aAuthType,
in ACString aRealm,
in ACString aPath,
out AString aUserDomain,
out AString aUserName,
out AString aUserPassword);
/**
* Store auth identity.
*
* @param hostPort
* the "host:port" of the server issuing a challenge.
* @param realm
* @param aScheme
* the URL scheme (e.g., "http"). NOTE: for proxy authentication,
* this should be "http" (this includes authentication for SSL
* tunneling).
* @param aHost
* the host of the server issuing a challenge (ASCII only).
* @param aPort
* the port of the server issuing a challenge.
* @param aAuthType
* optional string identifying auth type used (e.g., "basic")
* @param aRealm
* optional string identifying auth realm.
* @param path
* @param aPath
* optional string identifying auth path. empty for proxy auth.
* @param userDomain
* @param aUserDomain
* optional string containing user domain.
* @param userName
* @param aUserName
* optional string containing user name.
* @param userPassword
* @param aUserPassword
* optional string containing user password.
*/
void setAuthIdentity(in ACString aHost,
void setAuthIdentity(in ACString aScheme,
in ACString aHost,
in PRInt32 aPort,
in ACString aAuthType,
in ACString aRealm,
in ACString aPath,
in AString aUserDomain,
in AString aUserName,
in AString aUserPassword);
/**
* Clear all auth cache.
*/

Просмотреть файл

@ -29,10 +29,12 @@
#include "prprf.h"
static inline void
GetAuthKey(const char *host, PRInt32 port, nsCString &key)
GetAuthKey(const char *scheme, const char *host, PRInt32 port, nsCString &key)
{
key.Assign(host);
key.Append(':');
key.Assign(nsDependentCString(scheme) +
NS_LITERAL_CSTRING("://") +
nsDependentCString(host) +
NS_LITERAL_CSTRING(":"));
key.AppendInt(port);
}
@ -83,16 +85,17 @@ nsHttpAuthCache::Init()
}
nsresult
nsHttpAuthCache::GetAuthEntryForPath(const char *host,
nsHttpAuthCache::GetAuthEntryForPath(const char *scheme,
const char *host,
PRInt32 port,
const char *path,
nsHttpAuthEntry **entry)
{
LOG(("nsHttpAuthCache::GetAuthEntryForPath [host=%s:%d path=%s]\n",
host, port, path));
LOG(("nsHttpAuthCache::GetAuthEntryForPath [key=%s://%s:%d path=%s]\n",
scheme, host, port, path));
nsCAutoString key;
nsHttpAuthNode *node = LookupAuthNode(host, port, key);
nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, key);
if (!node)
return NS_ERROR_NOT_AVAILABLE;
@ -101,17 +104,18 @@ nsHttpAuthCache::GetAuthEntryForPath(const char *host,
}
nsresult
nsHttpAuthCache::GetAuthEntryForDomain(const char *host,
nsHttpAuthCache::GetAuthEntryForDomain(const char *scheme,
const char *host,
PRInt32 port,
const char *realm,
nsHttpAuthEntry **entry)
{
LOG(("nsHttpAuthCache::GetAuthEntryForDomain [host=%s:%d realm=%s]\n",
host, port, realm));
LOG(("nsHttpAuthCache::GetAuthEntryForDomain [key=%s://%s:%d realm=%s]\n",
scheme, host, port, realm));
nsCAutoString key;
nsHttpAuthNode *node = LookupAuthNode(host, port, key);
nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, key);
if (!node)
return NS_ERROR_NOT_AVAILABLE;
@ -120,7 +124,8 @@ nsHttpAuthCache::GetAuthEntryForDomain(const char *host,
}
nsresult
nsHttpAuthCache::SetAuthEntry(const char *host,
nsHttpAuthCache::SetAuthEntry(const char *scheme,
const char *host,
PRInt32 port,
const char *path,
const char *realm,
@ -131,8 +136,8 @@ nsHttpAuthCache::SetAuthEntry(const char *host,
{
nsresult rv;
LOG(("nsHttpAuthCache::SetAuthEntry [host=%s:%d realm=%s path=%s metadata=%x]\n",
host, port, realm, path, metadata));
LOG(("nsHttpAuthCache::SetAuthEntry [key=%s://%s:%d realm=%s path=%s metadata=%x]\n",
scheme, host, port, realm, path, metadata));
if (!mDB) {
rv = Init();
@ -140,7 +145,7 @@ nsHttpAuthCache::SetAuthEntry(const char *host,
}
nsCAutoString key;
nsHttpAuthNode *node = LookupAuthNode(host, port, key);
nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, key);
if (!node) {
// create a new entry node and set the given entry
@ -159,7 +164,8 @@ nsHttpAuthCache::SetAuthEntry(const char *host,
}
void
nsHttpAuthCache::ClearAuthEntry(const char *host,
nsHttpAuthCache::ClearAuthEntry(const char *scheme,
const char *host,
PRInt32 port,
const char *realm)
{
@ -167,7 +173,7 @@ nsHttpAuthCache::ClearAuthEntry(const char *host,
return;
nsCAutoString key;
GetAuthKey(host, port, key);
GetAuthKey(scheme, host, port, key);
PL_HashTableRemove(mDB, key.get());
}
@ -188,12 +194,15 @@ nsHttpAuthCache::ClearAll()
//-----------------------------------------------------------------------------
nsHttpAuthNode *
nsHttpAuthCache::LookupAuthNode(const char *host, PRInt32 port, nsCString &key)
nsHttpAuthCache::LookupAuthNode(const char *scheme,
const char *host,
PRInt32 port,
nsCString &key)
{
if (!mDB)
return nsnull;
GetAuthKey(host, port, key);
GetAuthKey(scheme, host, port, key);
return (nsHttpAuthNode *) PL_HashTableLookup(mDB, key.get());
}

Просмотреть файл

@ -205,28 +205,31 @@ public:
nsresult Init();
// |host| and |port| are required
// |scheme|, |host|, and |port| are required
// |path| can be null
// |entry| is either null or a weak reference
nsresult GetAuthEntryForPath(const char *host,
nsresult GetAuthEntryForPath(const char *scheme,
const char *host,
PRInt32 port,
const char *path,
nsHttpAuthEntry **entry);
// |host| and |port| are required
// |scheme|, |host|, and |port| are required
// |realm| must not be null
// |entry| is either null or a weak reference
nsresult GetAuthEntryForDomain(const char *host,
nsresult GetAuthEntryForDomain(const char *scheme,
const char *host,
PRInt32 port,
const char *realm,
nsHttpAuthEntry **entry);
// |host| and |port| are required
// |scheme|, |host|, and |port| are required
// |path| can be null
// |realm| must not be null
// if |credentials|, |user|, |pass|, and |challenge| are each
// null, then the entry is deleted.
nsresult SetAuthEntry(const char *host,
nsresult SetAuthEntry(const char *scheme,
const char *host,
PRInt32 port,
const char *directory,
const char *realm,
@ -235,7 +238,8 @@ public:
const nsHttpAuthIdentity &ident,
nsISupports *metadata);
void ClearAuthEntry(const char *host,
void ClearAuthEntry(const char *scheme,
const char *host,
PRInt32 port,
const char *realm);
@ -243,7 +247,10 @@ public:
nsresult ClearAll();
private:
nsHttpAuthNode *LookupAuthNode(const char *host, PRInt32 port, nsCString &key);
nsHttpAuthNode *LookupAuthNode(const char *scheme,
const char *host,
PRInt32 port,
nsCString &key);
// hash table allocation functions
static void* PR_CALLBACK AllocTable(void *, PRSize size);

Просмотреть файл

@ -49,13 +49,22 @@ nsHttpAuthManager::nsHttpAuthManager()
nsresult nsHttpAuthManager::Init()
{
// get reference to the auth cache. we assume that we will live
// as long as gHttpHandler. instantiate it if necessary.
if (!gHttpHandler) {
nsresult rv;
nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIProtocolHandler> handler;
rv = ios->GetProtocolHandler("http", getter_AddRefs(handler));
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return rv;
// maybe someone is overriding our HTTP handler implementation?
NS_ENSURE_TRUE(gHttpHandler, NS_ERROR_UNEXPECTED);
}
mAuthCache = gHttpHandler->AuthCache();
@ -68,8 +77,10 @@ nsHttpAuthManager::~nsHttpAuthManager()
}
NS_IMETHODIMP
nsHttpAuthManager::GetAuthIdentity(const nsACString & aHost,
nsHttpAuthManager::GetAuthIdentity(const nsACString & aScheme,
const nsACString & aHost,
PRInt32 aPort,
const nsACString & aAuthType,
const nsACString & aRealm,
const nsACString & aPath,
nsAString & aUserDomain,
@ -79,30 +90,34 @@ nsHttpAuthManager::GetAuthIdentity(const nsACString & aHost,
nsHttpAuthEntry * entry = nsnull;
nsresult rv;
if (!aPath.IsEmpty())
rv = mAuthCache->GetAuthEntryForPath(PromiseFlatCString(aHost).get(),
rv = mAuthCache->GetAuthEntryForPath(PromiseFlatCString(aScheme).get(),
PromiseFlatCString(aHost).get(),
aPort,
PromiseFlatCString(aPath).get(),
&entry);
else
rv = mAuthCache->GetAuthEntryForDomain(PromiseFlatCString(aHost).get(),
aPort,
PromiseFlatCString(aRealm).get(),
&entry);
&entry);
else
rv = mAuthCache->GetAuthEntryForDomain(PromiseFlatCString(aScheme).get(),
PromiseFlatCString(aHost).get(),
aPort,
PromiseFlatCString(aRealm).get(),
&entry);
if (NS_FAILED(rv))
return rv;
if (!entry)
return NS_ERROR_UNEXPECTED;
aUserDomain.Assign(entry->Domain());
aUserName.Assign(entry->User());
aUserPassword.Assign(entry->Pass());
//TODO: nsHttpAuthEntry has no "domain", which will be solved in bug 159015.
return NS_OK;
}
NS_IMETHODIMP
nsHttpAuthManager::SetAuthIdentity(const nsACString & aHost,
nsHttpAuthManager::SetAuthIdentity(const nsACString & aScheme,
const nsACString & aHost,
PRInt32 aPort,
const nsACString & aAuthType,
const nsACString & aRealm,
const nsACString & aPath,
const nsAString & aUserDomain,
@ -113,7 +128,8 @@ nsHttpAuthManager::SetAuthIdentity(const nsACString & aHost,
PromiseFlatString(aUserName).get(),
PromiseFlatString(aUserPassword).get());
return mAuthCache->SetAuthEntry(PromiseFlatCString(aHost).get(),
return mAuthCache->SetAuthEntry(PromiseFlatCString(aScheme).get(),
PromiseFlatCString(aHost).get(),
aPort,
PromiseFlatCString(aPath).get(),
PromiseFlatCString(aRealm).get(),

Просмотреть файл

@ -54,6 +54,7 @@
#include "nsICookieService.h"
static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID);
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
static NS_METHOD DiscardSegments(nsIInputStream *input,
void *closure,
@ -216,14 +217,7 @@ nsHttpChannel::Init(nsIURI *uri,
nsresult
nsHttpChannel::AsyncCall(nsAsyncCallback funcPtr)
{
nsCOMPtr<nsIEventQueueService> eqs;
nsCOMPtr<nsIEventQueue> eventQ;
gHttpHandler->GetEventQueueService(getter_AddRefs(eqs));
if (eqs)
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(eventQ));
if (!eventQ)
return NS_ERROR_FAILURE;
nsresult rv;
nsAsyncCallEvent *event = new nsAsyncCallEvent;
if (!event)
@ -237,7 +231,7 @@ nsHttpChannel::AsyncCall(nsAsyncCallback funcPtr)
nsHttpChannel::AsyncCall_EventHandlerFunc,
nsHttpChannel::AsyncCall_EventCleanupFunc);
nsresult rv = eventQ->PostEvent(event);
rv = mEventQ->PostEvent(event);
if (NS_FAILED(rv)) {
PL_DestroyEvent(event);
NS_RELEASE_THIS();
@ -349,8 +343,7 @@ nsHttpChannel::AsyncAbort(nsresult status)
// create a proxy for the listener..
nsCOMPtr<nsIRequestObserver> observer;
NS_NewRequestObserverProxy(getter_AddRefs(observer),
mListener, NS_CURRENT_EVENTQ);
NS_NewRequestObserverProxy(getter_AddRefs(observer), mListener, mEventQ);
if (observer) {
observer->OnStartRequest(this, mListenerContext);
observer->OnStopRequest(this, mListenerContext, mStatus);
@ -518,14 +511,6 @@ nsHttpChannel::SetupTransaction()
mRequestHead.SetHeader(nsHttp::Pragma, NS_LITERAL_CSTRING("no-cache"), PR_TRUE);
}
if (!mEventQ) {
// grab a reference to the calling thread's event queue.
nsCOMPtr<nsIEventQueueService> eqs;
gHttpHandler->GetEventQueueService(getter_AddRefs(eqs));
if (eqs)
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mEventQ));
}
// create the transaction object
mTransaction = new nsHttpTransaction();
if (!mTransaction)
@ -1486,11 +1471,31 @@ nsHttpChannel::ReadFromCache()
rv = mCacheEntry->OpenInputStream(0, getter_AddRefs(stream));
if (NS_FAILED(rv)) return rv;
rv = NS_NewInputStreamPump(getter_AddRefs(mCachePump),
stream, -1, -1, 0, 0, PR_TRUE);
// the cache stream implements blocking reads, so we want to read from
// it using the stream transport service.
nsCOMPtr<nsIStreamTransportService> sts =
do_GetService(kStreamTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
return mCachePump->AsyncRead(this, mListenerContext);
nsCOMPtr<nsITransport> transport;
rv = sts->CreateInputTransport(stream, 0, -1, PR_TRUE, getter_AddRefs(transport));
if (NS_FAILED(rv)) return rv;
// collect progress notifications from the stream as it is read.
rv = transport->SetEventSink(this, mEventQ);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIInputStream> wrapper;
rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
if (NS_FAILED(rv)) return rv;
rv = NS_NewInputStreamPump(getter_AddRefs(mCachePump),
wrapper, -1, -1, 0, 0, PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = mCachePump->AsyncRead(this, mListenerContext);
return rv;
}
nsresult
@ -1908,6 +1913,7 @@ SetIdent(nsHttpAuthIdentity &ident,
nsresult
nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth,
PRBool proxyAuth,
const char *scheme,
const char *host,
PRInt32 port,
const char *directory,
@ -1957,7 +1963,7 @@ nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth,
//
// if the credentials are not reusable, then we don't bother sticking
// them in the auth cache.
rv = authCache->SetAuthEntry(host, port, directory, realm,
rv = authCache->SetAuthEntry(scheme, host, port, directory, realm,
saveCreds ? *result : nsnull,
saveChallenge ? challenge : nsnull,
ident, sessionState);
@ -2042,7 +2048,7 @@ nsHttpChannel::GetCredentials(const char *challenges,
nsresult
nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
const char *scheme,
const char *authType,
PRBool proxyAuth,
nsIHttpAuthenticator *auth,
nsAFlatCString &creds)
@ -2060,14 +2066,14 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
nsCAutoString realm;
ParseRealm(challenge, realm);
// if no realm, then use the auth scheme as the realm. ToUpperCase so the
// if no realm, then use the auth type as the realm. ToUpperCase so the
// ficticious realm stands out a bit more.
// XXX this will cause some single signon misses!
// XXX this will cause problems when we expose the auth cache to OJI!
// XXX this was meant to be used with NTLM, which supplies no realm.
/*
if (realm.IsEmpty()) {
realm = scheme;
realm = authType;
ToUpperCase(realm);
}
*/
@ -2075,7 +2081,7 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
const char *host;
PRInt32 port;
nsHttpAuthIdentity *ident;
nsCAutoString path;
nsCAutoString path, scheme;
PRBool identFromURI = PR_FALSE;
// it is possible for the origin server to fake a proxy challenge. if
@ -2083,10 +2089,11 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
// domain. otherwise, we could inadvertantly expose the user's proxy
// credentials to an origin server.
if (proxyAuth && mConnectionInfo->ProxyHost()) {
if (proxyAuth && mConnectionInfo->UsingHttpProxy()) {
host = mConnectionInfo->ProxyHost();
port = mConnectionInfo->ProxyPort();
ident = &mProxyIdent;
scheme = NS_LITERAL_CSTRING("http");
}
else {
host = mConnectionInfo->Host();
@ -2096,6 +2103,9 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
rv = GetCurrentPath(path);
if (NS_FAILED(rv)) return rv;
rv = mURI->GetScheme(scheme);
if (NS_FAILED(rv)) return rv;
// if this is the first challenge, then try using the identity
// specified in the URL.
if (mIdent.IsEmpty()) {
@ -2111,7 +2121,7 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
// try instead.
//
nsHttpAuthEntry *entry = nsnull;
authCache->GetAuthEntryForDomain(host, port, realm.get(), &entry);
authCache->GetAuthEntryForDomain(scheme.get(), host, port, realm.get(), &entry);
// hold reference to the auth session state (in case we clear our
// reference to the entry).
@ -2137,8 +2147,8 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
LOG((" clearing bad auth cache entry\n"));
// ok, we've already tried this user identity, so clear the
// corresponding entry from the auth cache.
ClearPasswordManagerEntry(host, port, realm.get(), entry->User());
authCache->ClearAuthEntry(host, port, realm.get());
ClearPasswordManagerEntry(scheme.get(), host, port, realm.get(), entry->User());
authCache->ClearAuthEntry(scheme.get(), host, port, realm.get());
entry = nsnull;
ident->Clear();
}
@ -2168,8 +2178,8 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
if (!entry && ident->IsEmpty()) {
// at this point we are forced to interact with the user to get
// their username and password for this domain.
rv = PromptForIdentity(host, port, proxyAuth, realm.get(),
scheme, authFlags, *ident);
rv = PromptForIdentity(scheme.get(), host, port, proxyAuth, realm.get(),
authType, authFlags, *ident);
if (NS_FAILED(rv)) return rv;
identFromURI = PR_FALSE;
}
@ -2186,7 +2196,7 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
// expecting to authenticate as.
//
nsXPIDLCString result;
rv = GenCredsAndSetEntry(auth, proxyAuth, host, port, path.get(),
rv = GenCredsAndSetEntry(auth, proxyAuth, scheme.get(), host, port, path.get(),
realm.get(), challenge, *ident, sessionStateGrip,
getter_Copies(result));
if (NS_SUCCEEDED(rv))
@ -2196,7 +2206,7 @@ nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
nsresult
nsHttpChannel::ParseChallenge(const char *challenge,
nsCString &scheme,
nsCString &authType,
nsIHttpAuthenticator **auth)
{
LOG(("nsHttpChannel::ParseChallenge [this=%x]\n", this));
@ -2205,16 +2215,16 @@ nsHttpChannel::ParseChallenge(const char *challenge,
// get the challenge type
if ((p = strchr(challenge, ' ')) != nsnull)
scheme.Assign(challenge, p - challenge);
authType.Assign(challenge, p - challenge);
else
scheme.Assign(challenge);
authType.Assign(challenge);
// normalize to lowercase
ToLowerCase(scheme);
ToLowerCase(authType);
nsCAutoString contractid;
contractid.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
contractid.Append(scheme);
contractid.Append(authType);
return CallGetService(contractid.get(), auth);
}
@ -2272,16 +2282,19 @@ nsHttpChannel::ParseRealm(const char *challenge, nsACString &realm)
}
nsresult
nsHttpChannel::PromptForIdentity(const char *host,
PRInt32 port,
PRBool proxyAuth,
nsHttpChannel::PromptForIdentity(const char *scheme,
const char *host,
PRInt32 port,
PRBool proxyAuth,
const char *realm,
const char *scheme,
const char *authType,
PRUint32 authFlags,
nsHttpAuthIdentity &ident)
{
LOG(("nsHttpChannel::PromptForIdentity [this=%x]\n", this));
// XXX authType should be included in the prompt
// XXX i18n: IDN not supported.
nsCOMPtr<nsIAuthPrompt> authPrompt;
@ -2296,6 +2309,11 @@ nsHttpChannel::PromptForIdentity(const char *host,
// in password maanger. THE FORMAT OF THIS KEY IS SACROSANCT!! do not
// even think about changing the format of this key.
//
// XXX we need to prefix this with "scheme://" at some point. however, that
// has to be done very carefully and probably with some cooperation from the
// password manager to ensure that passwords remembered under the old key
// format are not lost.
//
nsAutoString key;
key.AssignWithConversion(host);
key.Append(PRUnichar(':'));
@ -2339,6 +2357,12 @@ nsHttpChannel::PromptForIdentity(const char *host,
realmU.AppendWithConversion(realm);
realmU.Append(PRUnichar('\"'));
// prepend "scheme://" displayHost
nsAutoString schemeU;
schemeU.AssignWithConversion(scheme);
schemeU.Append(NS_LITERAL_STRING("://"));
displayHost.Insert(schemeU, 0);
const PRUnichar *strings[] = { realmU.get(), displayHost.get() };
rv = bundle->FormatStringFromName(
NS_LITERAL_STRING("EnterUserPasswordForRealm").get(),
@ -2369,6 +2393,7 @@ nsHttpChannel::PromptForIdentity(const char *host,
void
nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
nsHttpAtom header,
const char *scheme,
const char *host,
PRInt32 port,
const char *path,
@ -2378,7 +2403,7 @@ nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
nsHttpAuthEntry *entry = nsnull;
nsresult rv;
rv = authCache->GetAuthEntryForPath(host, port, path, &entry);
rv = authCache->GetAuthEntryForPath(scheme, host, port, path, &entry);
if (NS_SUCCEEDED(rv)) {
// if we are trying to add a header for origin server auth and if the
// URL contains an explicit username, then try the given username first.
@ -2414,7 +2439,7 @@ nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
rv = ParseChallenge(challenge, unused, getter_AddRefs(auth));
if (NS_SUCCEEDED(rv)) {
PRBool proxyAuth = (header == nsHttp::Proxy_Authorization);
rv = GenCredsAndSetEntry(auth, proxyAuth, host, port, path,
rv = GenCredsAndSetEntry(auth, proxyAuth, scheme, host, port, path,
entry->Realm(), challenge, ident,
entry->mMetaData, getter_Copies(temp));
if (NS_SUCCEEDED(rv))
@ -2440,20 +2465,23 @@ nsHttpChannel::AddAuthorizationHeaders()
// check if proxy credentials should be sent
const char *proxyHost = mConnectionInfo->ProxyHost();
if (proxyHost)
if (proxyHost && mConnectionInfo->UsingHttpProxy())
SetAuthorizationHeader(authCache, nsHttp::Proxy_Authorization,
proxyHost, mConnectionInfo->ProxyPort(),
"http", proxyHost, mConnectionInfo->ProxyPort(),
nsnull, // proxy has no path
mProxyIdent);
// check if server credentials should be sent
nsCAutoString path;
if (NS_SUCCEEDED(GetCurrentPath(path)))
nsCAutoString path, scheme;
if (NS_SUCCEEDED(GetCurrentPath(path)) &&
NS_SUCCEEDED(mURI->GetScheme(scheme))) {
SetAuthorizationHeader(authCache, nsHttp::Authorization,
scheme.get(),
mConnectionInfo->Host(),
mConnectionInfo->Port(),
path.get(),
mIdent);
}
}
nsresult
@ -2759,8 +2787,18 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
NS_ENSURE_ARG_POINTER(listener);
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
nsresult rv;
// we want to grab a reference to the calling thread's event queue at
// this point. we will proxy all events back to the current thread via
// this event queue.
if (!mEventQ) {
rv = gHttpHandler->GetCurrentEventQ(getter_AddRefs(mEventQ));
if (NS_FAILED(rv)) return rv;
}
PRInt32 port;
nsresult rv = mURI->GetPort(&port);
rv = mURI->GetPort(&port);
if (NS_FAILED(rv))
return rv;
@ -3651,8 +3689,14 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
}
void
nsHttpChannel::ClearPasswordManagerEntry(const char *host, PRInt32 port, const char *realm, const PRUnichar *user)
nsHttpChannel::ClearPasswordManagerEntry(const char *scheme,
const char *host,
PRInt32 port,
const char *realm,
const PRUnichar *user)
{
// XXX scheme is currently unused. see comments in PromptForIdentity
nsresult rv;
nsCOMPtr<nsIPasswordManager> passWordManager = do_GetService(NS_PASSWORDMANAGER_CONTRACTID, &rv);
if (passWordManager) {

Просмотреть файл

@ -146,17 +146,17 @@ private:
nsresult OnDoneReadingPartialCacheEntry(PRBool *streamDone);
// auth specific methods
nsresult GenCredsAndSetEntry(nsIHttpAuthenticator *, PRBool proxyAuth, const char *host, PRInt32 port, const char *dir, const char *realm, const char *challenge, const nsHttpAuthIdentity &ident, nsCOMPtr<nsISupports> &session, char **result);
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);
void ParseRealm(const char *challenge, nsACString &realm);
void GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&);
nsresult PromptForIdentity(const char *host, PRInt32 port, PRBool proxyAuth, const char *realm, const char *scheme, PRUint32 authFlags, nsHttpAuthIdentity &);
void SetAuthorizationHeader(nsHttpAuthCache *, nsHttpAtom header, const char *host, PRInt32 port, const char *path, nsHttpAuthIdentity &ident);
nsresult PromptForIdentity(const char *scheme, const char *host, PRInt32 port, PRBool proxyAuth, const char *realm, const char *scheme, PRUint32 authFlags, nsHttpAuthIdentity &);
void SetAuthorizationHeader(nsHttpAuthCache *, nsHttpAtom header, const char *scheme, const char *host, PRInt32 port, const char *path, nsHttpAuthIdentity &ident);
void AddAuthorizationHeaders();
nsresult GetCurrentPath(nsACString &);
void ClearPasswordManagerEntry(const char *host, PRInt32 port, const char *realm, const PRUnichar *user);
void ClearPasswordManagerEntry(const char *scheme, const char *host, PRInt32 port, const char *realm, const PRUnichar *user);
nsresult DoAuthRetry(nsAHttpConnection *);
static void *PR_CALLBACK AsyncCall_EventHandlerFunc(PLEvent *);