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 } }
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; }