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

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

@ -17,61 +17,97 @@
* by Sun Microsystem. All Rights Reserved. * by Sun Microsystem. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
* Darin Fisher <darin@netscape.com> * Darin Fisher <darin@meer.net>
* Louie Zhao <louie.zhao@sun.com> * Louie Zhao <louie.zhao@sun.com>
*/ */
#include "nsISupports.idl" #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 interface nsIHttpAuthManager : nsISupports
{ {
/** /**
* Lookup auth identity. * Lookup auth identity.
* *
* @param hostPort * @param aScheme
* the "host:port" of the server issuing a challenge. * the URL scheme (e.g., "http"). NOTE: for proxy authentication,
* @param realm * 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. * optional string identifying auth realm.
* @param path * @param aPath
* optional string identifying auth path. empty for proxy auth. * optional string identifying auth path. empty for proxy auth.
* @param userDomain * @param aUserDomain
* return value containing user domain. * return value containing user domain.
* @param userName * @param aUserName
* return value containing user name. * return value containing user name.
* @param userPassword * @param aUserPassword
* return value containing user password. * return value containing user password.
*/ */
void getAuthIdentity(in ACString aHost, void getAuthIdentity(in ACString aScheme,
in ACString aHost,
in PRInt32 aPort, in PRInt32 aPort,
in ACString aAuthType,
in ACString aRealm, in ACString aRealm,
in ACString aPath, in ACString aPath,
out AString aUserDomain, out AString aUserDomain,
out AString aUserName, out AString aUserName,
out AString aUserPassword); out AString aUserPassword);
/** /**
* Store auth identity. * Store auth identity.
* *
* @param hostPort * @param aScheme
* the "host:port" of the server issuing a challenge. * the URL scheme (e.g., "http"). NOTE: for proxy authentication,
* @param realm * 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. * optional string identifying auth realm.
* @param path * @param aPath
* optional string identifying auth path. empty for proxy auth. * optional string identifying auth path. empty for proxy auth.
* @param userDomain * @param aUserDomain
* optional string containing user domain. * optional string containing user domain.
* @param userName * @param aUserName
* optional string containing user name. * optional string containing user name.
* @param userPassword * @param aUserPassword
* optional string containing user password. * optional string containing user password.
*/ */
void setAuthIdentity(in ACString aHost, void setAuthIdentity(in ACString aScheme,
in ACString aHost,
in PRInt32 aPort, in PRInt32 aPort,
in ACString aAuthType,
in ACString aRealm, in ACString aRealm,
in ACString aPath, in ACString aPath,
in AString aUserDomain, in AString aUserDomain,
in AString aUserName, in AString aUserName,
in AString aUserPassword); in AString aUserPassword);
/** /**
* Clear all auth cache. * Clear all auth cache.
*/ */

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

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

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

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

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

@ -49,13 +49,22 @@ nsHttpAuthManager::nsHttpAuthManager()
nsresult nsHttpAuthManager::Init() 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) { if (!gHttpHandler) {
nsresult rv; nsresult rv;
nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv); nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIProtocolHandler> handler; nsCOMPtr<nsIProtocolHandler> handler;
rv = ios->GetProtocolHandler("http", getter_AddRefs(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(); mAuthCache = gHttpHandler->AuthCache();
@ -68,8 +77,10 @@ nsHttpAuthManager::~nsHttpAuthManager()
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHttpAuthManager::GetAuthIdentity(const nsACString & aHost, nsHttpAuthManager::GetAuthIdentity(const nsACString & aScheme,
const nsACString & aHost,
PRInt32 aPort, PRInt32 aPort,
const nsACString & aAuthType,
const nsACString & aRealm, const nsACString & aRealm,
const nsACString & aPath, const nsACString & aPath,
nsAString & aUserDomain, nsAString & aUserDomain,
@ -79,30 +90,34 @@ nsHttpAuthManager::GetAuthIdentity(const nsACString & aHost,
nsHttpAuthEntry * entry = nsnull; nsHttpAuthEntry * entry = nsnull;
nsresult rv; nsresult rv;
if (!aPath.IsEmpty()) if (!aPath.IsEmpty())
rv = mAuthCache->GetAuthEntryForPath(PromiseFlatCString(aHost).get(), rv = mAuthCache->GetAuthEntryForPath(PromiseFlatCString(aScheme).get(),
PromiseFlatCString(aHost).get(),
aPort, aPort,
PromiseFlatCString(aPath).get(), PromiseFlatCString(aPath).get(),
&entry); &entry);
else else
rv = mAuthCache->GetAuthEntryForDomain(PromiseFlatCString(aHost).get(), rv = mAuthCache->GetAuthEntryForDomain(PromiseFlatCString(aScheme).get(),
aPort, PromiseFlatCString(aHost).get(),
PromiseFlatCString(aRealm).get(), aPort,
&entry); PromiseFlatCString(aRealm).get(),
&entry);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
if (!entry) if (!entry)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
aUserDomain.Assign(entry->Domain());
aUserName.Assign(entry->User()); aUserName.Assign(entry->User());
aUserPassword.Assign(entry->Pass()); aUserPassword.Assign(entry->Pass());
//TODO: nsHttpAuthEntry has no "domain", which will be solved in bug 159015.
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHttpAuthManager::SetAuthIdentity(const nsACString & aHost, nsHttpAuthManager::SetAuthIdentity(const nsACString & aScheme,
const nsACString & aHost,
PRInt32 aPort, PRInt32 aPort,
const nsACString & aAuthType,
const nsACString & aRealm, const nsACString & aRealm,
const nsACString & aPath, const nsACString & aPath,
const nsAString & aUserDomain, const nsAString & aUserDomain,
@ -113,7 +128,8 @@ nsHttpAuthManager::SetAuthIdentity(const nsACString & aHost,
PromiseFlatString(aUserName).get(), PromiseFlatString(aUserName).get(),
PromiseFlatString(aUserPassword).get()); PromiseFlatString(aUserPassword).get());
return mAuthCache->SetAuthEntry(PromiseFlatCString(aHost).get(), return mAuthCache->SetAuthEntry(PromiseFlatCString(aScheme).get(),
PromiseFlatCString(aHost).get(),
aPort, aPort,
PromiseFlatCString(aPath).get(), PromiseFlatCString(aPath).get(),
PromiseFlatCString(aRealm).get(), PromiseFlatCString(aRealm).get(),

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

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

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

@ -146,17 +146,17 @@ private:
nsresult OnDoneReadingPartialCacheEntry(PRBool *streamDone); nsresult OnDoneReadingPartialCacheEntry(PRBool *streamDone);
// auth specific methods // 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 GetCredentials(const char *challenges, PRBool proxyAuth, nsAFlatCString &creds);
nsresult GetCredentialsForChallenge(const char *challenge, const char *scheme, PRBool proxyAuth, nsIHttpAuthenticator *auth, 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 ParseChallenge(const char *challenge, nsCString &scheme, nsIHttpAuthenticator **auth);
void ParseRealm(const char *challenge, nsACString &realm); void ParseRealm(const char *challenge, nsACString &realm);
void GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&); void GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&);
nsresult PromptForIdentity(const char *host, PRInt32 port, PRBool proxyAuth, const char *realm, const char *scheme, PRUint32 authFlags, nsHttpAuthIdentity &); 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 *host, PRInt32 port, const char *path, nsHttpAuthIdentity &ident); void SetAuthorizationHeader(nsHttpAuthCache *, nsHttpAtom header, const char *scheme, const char *host, PRInt32 port, const char *path, nsHttpAuthIdentity &ident);
void AddAuthorizationHeaders(); void AddAuthorizationHeaders();
nsresult GetCurrentPath(nsACString &); 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 *); nsresult DoAuthRetry(nsAHttpConnection *);
static void *PR_CALLBACK AsyncCall_EventHandlerFunc(PLEvent *); static void *PR_CALLBACK AsyncCall_EventHandlerFunc(PLEvent *);