示例#1
0
nsresult
nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header, const nsACString &value)
{
    nsEntry *entry = nsnull;
    PRInt32 index;

    index = LookupEntry(header, &entry);

    if (!entry) {
        if (value.IsEmpty()) {
            if (!TrackEmptyHeader(header)) {
                LOG(("Ignoring Empty Header: %s\n", header.get()));
                return NS_OK; // ignore empty headers by default
            }
        }
        entry = mHeaders.AppendElement(); //new nsEntry(header, value);
        if (!entry)
            return NS_ERROR_OUT_OF_MEMORY;
        entry->header = header;
        entry->value = value;
    } else if (!IsSingletonHeader(header)) {
        MergeHeader(header, entry, value);
    } else {
        // Multiple instances of non-mergeable header received from network
        // - ignore if same value
        if (!entry->value.Equals(value)) {
            if (IsSuspectDuplicateHeader(header)) {
                // reply may be corrupt/hacked (ex: CLRF injection attacks)
                return NS_ERROR_CORRUPTED_CONTENT;
            } // else silently drop value: keep value from 1st header seen
            LOG(("Header %s silently dropped as non mergeable header\n",
                 header.get()));
        }
    }

    return NS_OK;
}
nsresult
nsHttpHeaderArray::SetHeader_internal(nsHttpAtom header,
                                      const nsACString &headerName,
                                      const nsACString &value,
                                      nsHttpHeaderArray::HeaderVariety variety)
{
    nsEntry *entry =  mHeaders.AppendElement();
    if (!entry) {
        return NS_ERROR_OUT_OF_MEMORY;
    }
    entry->header = header;
    // Only save original form of a header if it is different than the header
    // atom string.
    if (!headerName.Equals(header.get())) {
        entry->headerNameOriginal = headerName;
    }
    entry->value = value;
    entry->variety = variety;
    return NS_OK;
}
void
nsHttpChannelAuthProvider::SetAuthorizationHeader(nsHttpAuthCache    *authCache,
                                                  nsHttpAtom          header,
                                                  const char         *scheme,
                                                  const char         *host,
                                                  int32_t             port,
                                                  const char         *path,
                                                  nsHttpAuthIdentity &ident)
{
    nsHttpAuthEntry *entry = nullptr;
    nsresult rv;

    // set informations that depend on whether
    // we're authenticating against a proxy
    // or a webserver
    nsISupports **continuationState;

    if (header == nsHttp::Proxy_Authorization) {
        continuationState = &mProxyAuthContinuationState;
    } else {
        continuationState = &mAuthContinuationState;
    }

    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.
        // we only want to do this, however, if we know the URL requires auth
        // based on the presence of an auth cache entry for this URL (which is
        // true since we are here).  but, if the username from the URL matches
        // the username from the cache, then we should prefer the password
        // stored in the cache since that is most likely to be valid.
        if (header == nsHttp::Authorization && entry->Domain()[0] == '\0') {
            GetIdentityFromURI(0, ident);
            // if the usernames match, then clear the ident so we will pick
            // up the one from the auth cache instead.
            if (nsCRT::strcmp(ident.User(), entry->User()) == 0)
                ident.Clear();
        }
        bool identFromURI;
        if (ident.IsEmpty()) {
            ident.Set(entry->Identity());
            identFromURI = false;
        }
        else
            identFromURI = true;

        nsXPIDLCString temp;
        const char *creds     = entry->Creds();
        const char *challenge = entry->Challenge();
        // we can only send a preemptive Authorization header if we have either
        // stored credentials or a stored challenge from which to derive
        // 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 = GetAuthenticator(challenge, unused, getter_AddRefs(auth));
            if (NS_SUCCEEDED(rv)) {
                bool proxyAuth = (header == nsHttp::Proxy_Authorization);
                rv = GenCredsAndSetEntry(auth, proxyAuth, scheme, host, port,
                                         path, entry->Realm(), challenge, ident,
                                         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(*continuationState);
            }
        }
        if (creds[0]) {
            LOG(("   adding \"%s\" request header\n", header.get()));
            if (header == nsHttp::Proxy_Authorization)
                mAuthChannel->SetProxyCredentials(nsDependentCString(creds));
            else
                mAuthChannel->SetWWWCredentials(nsDependentCString(creds));

            // suppress defensive auth prompting for this channel since we know
            // that we already prompted at least once this session.  we only do
            // this for non-proxy auth since the URL's userpass is not used for
            // proxy auth.
            if (header == nsHttp::Authorization)
                mSuppressDefensiveAuth = true;
        }
        else
            ident.Clear(); // don't remember the identity
    }
}
示例#4
0
nsresult
nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
                                    const nsACString &value,
                                    bool response)
{
    // mHeader holds the consolidated (merged or updated) headers.
    // mHeader for response header will keep the original heades as well.
    nsEntry *entry = nullptr;

    LookupEntry(header, &entry);

    if (!entry) {
        if (value.IsEmpty()) {
            if (!gHttpHandler->KeepEmptyResponseHeadersAsEmtpyString() &&
                !TrackEmptyHeader(header)) {
                LOG(("Ignoring Empty Header: %s\n", header.get()));
                if (response) {
                    // Set header as original but not as response header.
                    return SetHeader_internal(header, value,
                                              eVarietyResponseNetOriginal);
                }
                return NS_OK; // ignore empty headers by default
            }
        }
        HeaderVariety variety = eVarietyRequestOverride;
        if (response) {
            variety = eVarietyResponseNetOriginalAndResponse;
        }
        return SetHeader_internal(header, value, variety);

    } else if (!IsSingletonHeader(header)) {
        HeaderVariety variety = eVarietyRequestOverride;
        if (response) {
            variety = eVarietyResponse;
        }
        nsresult rv = MergeHeader(header, entry, value, variety);
        if (NS_FAILED(rv)) {
            return rv;
        }
        if (response) {
            rv = SetHeader_internal(header, value,
                                    eVarietyResponseNetOriginal);
        }
        return rv;
    } else {
        // Multiple instances of non-mergeable header received from network
        // - ignore if same value
        if (!entry->value.Equals(value)) {
            if (IsSuspectDuplicateHeader(header)) {
                // reply may be corrupt/hacked (ex: CLRF injection attacks)
                return NS_ERROR_CORRUPTED_CONTENT;
            } // else silently drop value: keep value from 1st header seen
            LOG(("Header %s silently dropped as non mergeable header\n",
                 header.get()));

        }
        if (response) {
            return SetHeader_internal(header, value,
                                      eVarietyResponseNetOriginal);
        }
    }

    return NS_OK;
}