Fix for bug 32335. Fixes to make basic auth use the realm for authenticating. Thanks to darin@netscape.com r=gagan, sr=shaver.

This commit is contained in:
gagan%netscape.com 2000-10-13 04:01:48 +00:00
Родитель b1350427ed
Коммит bbeb713db3
5 изменённых файлов: 181 добавлений и 42 удалений

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

@ -89,6 +89,8 @@ interface nsIHTTPChannel : nsIChannel
attribute PRBool authTriedWithPrehost;
attribute string authRealm;
/*
We need a way to switch off gzip, etc. compression on the fly
so that SaveAs would work as expected. Eventually this needs to

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

@ -78,6 +78,11 @@ nsAuthEngine::GetAuthString(nsIURI* i_URI, char** o_AuthString)
// mAuthList may have been cleared from logout
if (!mAuthList) return NS_OK;
PRUint32 count=0;
(void)mAuthList->Count(&count);
if (count<=0)
return NS_OK; // not found
nsXPIDLCString host;
rv = i_URI->GetHost(getter_Copies(host));
if (NS_FAILED(rv)) return rv;
@ -98,10 +103,6 @@ nsAuthEngine::GetAuthString(nsIURI* i_URI, char** o_AuthString)
char *lastSlash = PL_strrchr(dir, '/');
if (lastSlash) lastSlash[1] = '\0';
PRUint32 count=0;
(void)mAuthList->Count(&count);
if (count<=0)
return NS_OK; // not found
for (PRInt32 i = count-1; i>=0; --i)
{
nsAuth* auth = (nsAuth*)mAuthList->ElementAt(i);
@ -167,6 +168,7 @@ nsAuthEngine::GetAuthString(nsIURI* i_URI, char** o_AuthString)
nsresult
nsAuthEngine::SetAuth(nsIURI* i_URI,
const char* i_AuthString,
const char* i_Realm,
PRBool bProxyAuth)
{
nsresult rv;
@ -209,7 +211,7 @@ nsAuthEngine::SetAuth(nsIURI* i_URI,
CRTFREEIF(unescaped_AuthString);
return rv;
}
nsAuth* auth = new nsAuth(i_URI, unescaped_AuthString);
nsAuth* auth = new nsAuth(i_URI, unescaped_AuthString, nsnull, nsnull, i_Realm);
CRTFREEIF(unescaped_AuthString);
if (!auth)
return NS_ERROR_OUT_OF_MEMORY;
@ -274,5 +276,52 @@ nsAuthEngine::SetProxyAuthString(const char* host,
rv = mIOService->NewURI(spec.GetBuffer(), nsnull, getter_AddRefs(uri));
if (NS_FAILED(rv)) return rv;
return SetAuth(uri, i_AuthString, PR_TRUE);
return SetAuth(uri, i_AuthString, nsnull, PR_TRUE);
}
nsresult
nsAuthEngine::GetAuthStringForRealm(nsIURI* i_URI, const char* i_Realm, char** o_AuthString)
{
nsresult rv = NS_OK;
if (!o_AuthString)
return NS_ERROR_NULL_POINTER;
if (!i_Realm)
return NS_ERROR_NULL_POINTER;
*o_AuthString = nsnull;
// list may have been cleared by logout...
if (!mAuthList)
return NS_OK;
PRUint32 count = 0;
mAuthList->Count(&count);
if (count <= 0)
return NS_OK; // not found
nsXPIDLCString host;
rv = i_URI->GetHost(getter_Copies(host));
if (NS_FAILED(rv)) return rv;
PRInt32 port;
rv = i_URI->GetPort(&port);
if (NS_FAILED(rv)) return rv;
for (PRInt32 i = count-1; i>=0; --i)
{
nsAuth* auth = (nsAuth*) mAuthList->ElementAt(i);
nsXPIDLCString authHost;
PRInt32 authPort;
auth->uri->GetHost(getter_Copies(authHost));
auth->uri->GetPort(&authPort);
if ((0 == nsCRT::strcasecmp(authHost, host)) &&
(0 == nsCRT::strcasecmp(auth->realm, i_Realm)) &&
(port == authPort))
{
*o_AuthString = nsCRT::strdup(auth->encodedString);
return (!*o_AuthString) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
}
}
return NS_OK; // not found
}

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

@ -63,6 +63,16 @@ public:
PRInt32 port,
const char* i_AuthString);
// Get an auth string for a particular host/port/realm
NS_IMETHOD GetAuthStringForRealm(nsIURI* i_URI,
const char* i_Realm,
char** o_AuthString);
// Set an auth string for a particular host/port/realm
NS_IMETHOD SetAuthStringForRealm(nsIURI* i_URI,
const char* i_Realm,
const char* i_AuthString);
/*
Expire all existing auth list entries including proxy auths.
*/
@ -72,6 +82,7 @@ protected:
NS_IMETHOD SetAuth(nsIURI* i_URI,
const char* i_AuthString,
const char* i_Realm = nsnull,
PRBool bProxyAuth = PR_FALSE);
nsCOMPtr<nsISupportsArray> mAuthList;
@ -89,4 +100,10 @@ nsAuthEngine::SetAuthString(nsIURI* i_URI, const char* i_AuthString)
return SetAuth(i_URI, i_AuthString);
}
inline nsresult
nsAuthEngine::SetAuthStringForRealm(nsIURI* i_URI, const char* i_Realm, const char* i_AuthString)
{
return SetAuth(i_URI, i_AuthString, i_Realm);
}
#endif /* _nsAuthEngine_h_ */

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

@ -93,6 +93,7 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL, nsHTTPHandler* i_Handler):
mFiredOpenOnStartRequest(PR_FALSE),
mFiredOpenOnStopRequest (PR_FALSE),
mAuthTriedWithPrehost(PR_FALSE),
mAuthRealm(nsnull),
mProxy(0),
mProxyPort(-1),
mProxyType(nsnull),
@ -139,6 +140,7 @@ nsHTTPChannel::~nsHTTPChannel()
mPrompter = null_nsCOMPtr();
mResponseContext = null_nsCOMPtr();
mLoadGroup = null_nsCOMPtr();
CRTFREEIF(mAuthRealm);
CRTFREEIF(mProxy);
CRTFREEIF(mProxyType);
}
@ -847,6 +849,27 @@ nsHTTPChannel::GetAuthTriedWithPrehost(PRBool* oTried)
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsHTTPChannel::SetAuthRealm(const char* aAuthRealm)
{
CRTFREEIF(mAuthRealm);
if (aAuthRealm)
mAuthRealm = nsCRT::strdup(aAuthRealm);
return NS_OK;
}
NS_IMETHODIMP
nsHTTPChannel::GetAuthRealm(char** aAuthRealm)
{
if (aAuthRealm)
{
*aAuthRealm = nsCRT::strdup(mAuthRealm);
return (*aAuthRealm) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
else
return NS_ERROR_NULL_POINTER;
}
// nsIInterfaceRequestor method
NS_IMETHODIMP
nsHTTPChannel::GetInterface(const nsIID &anIID, void **aResult )
@ -2029,7 +2052,7 @@ nsHTTPChannel::Authenticate(const char *iChallenge, PRBool iProxyAuth)
if (NS_FAILED(rv)) return rv;
//flush out existing records of this URI in authengine-
nsAuthEngine* pEngine;
nsAuthEngine* pEngine = nsnull;
if (NS_SUCCEEDED(mHandler->GetAuthEngine(&pEngine)))
{
rv = pEngine->SetAuthString(mURI, 0);
@ -2067,6 +2090,7 @@ nsHTTPChannel::Authenticate(const char *iChallenge, PRBool iProxyAuth)
nsXPIDLCString authString;
nsCAutoString authLine;
nsCOMPtr<nsIAuthenticator> auth;
nsCAutoString authRealm;
// multiple www-auth headers case
// go thru each to see if we support that.
@ -2123,8 +2147,6 @@ nsHTTPChannel::Authenticate(const char *iChallenge, PRBool iProxyAuth)
Throw a modal dialog box asking for
username, password. Prefill (!?!)
*/
if (!mPrompter)
return NS_ERROR_FAILURE;
PRBool retval = PR_FALSE;
//TODO localize it!
@ -2152,6 +2174,9 @@ nsHTTPChannel::Authenticate(const char *iChallenge, PRBool iProxyAuth)
if (realm != end) {
message.AppendWithConversion(realm, end - realm);
foundRealm = PR_TRUE;
// Remember this realm; we will set it as an attribute of the new channel.
authRealm.Assign(realm, end - realm);
}
}
@ -2159,44 +2184,74 @@ nsHTTPChannel::Authenticate(const char *iChallenge, PRBool iProxyAuth)
if (!foundRealm)
message.AppendWithConversion(authLine.GetBuffer());
// get the hostname
nsXPIDLCString hostname;
if (NS_SUCCEEDED(mURI->GetHost(getter_Copies(hostname))))
// but, if we did find a realm and this is the first time trying to
// authenticate this channel (indicated by mAuthRealm == NULL), then
// lookup the realm in the auth engine and try to authenticate using
// the response.
else if (!mAuthRealm)
{
// TODO localize
message.AppendWithConversion(" at ");
message.AppendWithConversion(hostname);
// Get the authentication string for the realm. If not found, then
// authString will be NULL, and we will be forced to prompt.
if (pEngine)
pEngine->GetAuthStringForRealm(mURI, authRealm, getter_Copies(authString));
#ifdef DEBUG_darin
fprintf(stderr, "\n>>>>> Authentication for Realm: [realm=%s, auth=%s]\n\n", (const char*) authRealm, (const char*) authString);
#endif
}
// Get url
nsXPIDLCString urlCString;
mURI->GetPrePath(getter_Copies(urlCString));
nsAutoString prePath; // XXX i18n
CopyASCIItoUCS2(nsLiteralCString(
NS_STATIC_CAST(const char*, urlCString)), prePath);
rv = mPrompter->PromptUsernameAndPassword(nsnull,
message.GetUnicode(),
prePath.GetUnicode(),
nsIPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(userBuf),
getter_Copies(passwdBuf),
&retval);
if (NS_FAILED(rv) || !retval) // let it go on if we cancelled auth...
// Skip prompting if we already have an authentication string.
if (!authString || !*authString)
{
// Delay this check until we absolutely would need the prompter
if (!mPrompter) {
NS_WARNING("Failed to prompt for username/password: nsHTTPChannel::mPrompter == NULL");
return NS_ERROR_FAILURE;
}
// get the hostname
nsXPIDLCString hostname;
if (NS_SUCCEEDED(mURI->GetHost(getter_Copies(hostname))))
{
// TODO localize
message.AppendWithConversion(" at ");
message.AppendWithConversion(hostname);
}
// Get url
nsXPIDLCString urlCString;
mURI->GetPrePath(getter_Copies(urlCString));
nsAutoString prePath; // XXX i18n
CopyASCIItoUCS2(nsLiteralCString(
NS_STATIC_CAST(const char*, urlCString)), prePath);
rv = mPrompter->PromptUsernameAndPassword(nsnull,
message.GetUnicode(),
prePath.GetUnicode(),
nsIPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(userBuf),
getter_Copies(passwdBuf),
&retval);
if (NS_FAILED(rv) || !retval) // let it go on if we cancelled auth...
return rv;
}
}
// Skip authentication if we already have an authentication string.
if (!authString || !*authString)
{
if (!userBuf && interactionType == nsIAuthenticator::INTERACTION_STANDARD) {
/* can't proceed without at least a username, can we? */
return NS_ERROR_FAILURE;
}
if (NS_FAILED(rv) ||
NS_FAILED(rv = auth->Authenticate(mURI, "http", authLine.GetBuffer(),
userBuf, passwdBuf, mPrompter,
getter_Copies(authString))))
return rv;
}
if (!userBuf && interactionType == nsIAuthenticator::INTERACTION_STANDARD) {
/* can't proceed without at least a username, can we? */
return NS_ERROR_FAILURE;
}
if (NS_FAILED(rv) ||
NS_FAILED(rv = auth->Authenticate(mURI, "http", authLine.GetBuffer(),
userBuf, passwdBuf, mPrompter,
getter_Copies(authString))))
return rv;
#if defined(DEBUG_shaver) || defined(DEBUG_gagan)
fprintf(stderr, "Auth string: %s\n", (const char *)authString);
#endif
@ -2230,6 +2285,10 @@ nsHTTPChannel::Authenticate(const char *iChallenge, PRBool iProxyAuth)
// Let it know that we have already tried prehost stuff...
httpChannel->SetAuthTriedWithPrehost(PR_TRUE);
// Let it know that we are trying to access a realm
if (authRealm)
httpChannel->SetAuthRealm(authRealm);
if (mResponseDataListener)
{
// Fire the new request...
@ -2315,10 +2374,21 @@ nsHTTPChannel::ProcessStatusCode(void)
{
rv = GetRequestHeader(nsHTTPAtoms::Authorization,
getter_Copies(authString));
pEngine->SetAuthString(mURI, authString);
#ifdef DEBUG_darin
fprintf(stderr, "\n>>>>> Auth Accepted!! [realm=%s, auth=%s]\n\n", mAuthRealm, (const char*) authString);
#endif
if (mAuthRealm)
pEngine->SetAuthStringForRealm(mURI, mAuthRealm, authString);
else
pEngine->SetAuthString(mURI, authString);
}
else // clear out entry from single signon and our cache.
{
#ifdef DEBUG_darin
rv = GetRequestHeader(nsHTTPAtoms::Authorization,
getter_Copies(authString));
fprintf(stderr, "\n>>>>> Auth Rejected!! [realm=%s, auth=%s]\n\n", mAuthRealm, (const char*) authString);
#endif
pEngine->SetAuthString(mURI, 0);
NS_WITH_SERVICE(nsIWalletService, walletService,

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

@ -181,6 +181,7 @@ protected:
And so we need to throw a dialog box!
*/
PRBool mAuthTriedWithPrehost;
char* mAuthRealm;
char* mProxy;
PRInt32 mProxyPort;