nsHttpChannelAuthProvider::GetCredentialsForChallenge returns wrong credentials

NEW
Unassigned

Status

()

Core
Networking: HTTP
P5
major
7 years ago
7 months ago

People

(Reporter: Michel Verbraak, Unassigned)

Tracking

({reproducible})

Trunk
x86_64
Linux
reproducible
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [necko-would-take])

(Reporter)

Description

7 years ago
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0) Gecko/20100101 Firefox/7.0
Build ID: 20110927153135

Steps to reproduce:

Trying to create multiple https connections to the same host and url with different username and passwords using xmlhttprequest.

URI = https://exchange2010.example.com/EWS/Exchange.asmx
users:
1. username = jane, domain=example, password=test1
2. username = john, domain=example, password=test2
3. username = karel, doman=example, password=test3
etc...


Actual results:

Three connections are created but the are all authenticated with the first set of credentials because the first is stored in cache and for the following this entry is used because credentials are stored in the authcache based on shema, host, port and realm. The key is the same for all connections.


Expected results:

The key for saving in cache should also contain the username or some other settable part.

I get it to work when i specify a different hostname for the same ip-address for each connection. Because the key will be different then and for each set of credentials a new key is saved. But this is not workable because normal users cannot control this.
(Reporter)

Updated

7 years ago
Severity: normal → major
Keywords: reproducible
See Also: → bug 654348, bug 547871
(Reporter)

Comment 1

7 years ago
The authentication credentials are stored in a hashtable which uses the scheme, host, port and realm as key to store the credentials. See following part in file "nsHttpChannelAuthProvider.cpp" method "nsHttpChannelAuthProvider::GetCredentialsForChallenge"

    nsHttpAuthEntry *entry = nsnull;
    authCache->GetAuthEntryForDomain(scheme.get(), host, port,
                                     realm.get(), &entry);

After this the check is done if the identity is valid. When not valid and NOT identFromURI and matching credentials from cache the specified credentials are replaced by the cached credentials.

In the case where we try to create three connections to the same server with different usernames it will always replace the specified credentials by the cached version.


    // hold reference to the auth session state (in case we clear our
    // reference to the entry).
    nsCOMPtr<nsISupports> sessionStateGrip;
    if (entry)
        sessionStateGrip = entry->mMetaData;

    // for digest auth, maybe our cached nonce value simply timed out...
    PRBool identityInvalid;
    nsISupports *sessionState = sessionStateGrip;
    rv = auth->ChallengeReceived(mAuthChannel,
                                 challenge,
                                 proxyAuth,
                                 &sessionState,
                                 &*continuationState,
                                 &identityInvalid);
    sessionStateGrip.swap(sessionState);
    if (NS_FAILED(rv)) return rv;

    LOG(("  identity invalid = %d\n", identityInvalid));

    if (identityInvalid) {
        if (entry) {
            if (ident->Equals(entry->Identity())) {
                LOG(("  clearing bad auth cache entry\n"));
                // ok, we've already tried this user identity, so clear the
                // corresponding entry from the auth cache.
                authCache->ClearAuthEntry(scheme.get(), host,
                                          port, realm.get());
                entry = nsnull;
                ident->Clear();
            }
            else if (!identFromURI ||
                     nsCRT::strcmp(ident->User(),
                                   entry->Identity().User()) == 0) {
                LOG(("  taking identity from auth cache\n"));
                // the password from the auth cache is more likely to be
                // correct than the one in the URL.  at least, we know that it
                // works with the given username.  it is possible for a server
                // to distinguish logons based on the supplied password alone,
                // but that would be quite unusual... and i don't think we need
                // to worry about such unorthodox cases.
                ident->Set(entry->Identity());
                identFromURI = PR_FALSE;
                if (entry->Creds()[0] != '\0') {
                    LOG(("    using cached credentials!\n"));
                    creds.Assign(entry->Creds());
                    return entry->AddPath(path.get());
                }
            }
        }
        else if (!identFromURI) {
            // hmm... identity invalid, but no auth entry!  the realm probably
            // changed (see bug 201986).
            ident->Clear();
        }
Status: UNCONFIRMED → NEW
Ever confirmed: true
Whiteboard: [necko-would-take]
You need to log in before you can comment on or make changes to this bug.