From 2b344f2a186d09cb5d4cb037f59180c458df0c30 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 26 May 2016 11:25:35 +0200 Subject: Move negotiate auth off the main thread, allow negotiate auth for all https:// pages which offers www-authenticate:Negotiate header --- firefox-redhat-default-prefs.js | 4 +- firefox.spec | 7 +- mozilla-890908-async-negotiate.patch | 727 +++++++++++++++++++++++++++++++++++ 3 files changed, 736 insertions(+), 2 deletions(-) create mode 100644 mozilla-890908-async-negotiate.patch diff --git a/firefox-redhat-default-prefs.js b/firefox-redhat-default-prefs.js index d7ed1c5..13fc643 100644 --- a/firefox-redhat-default-prefs.js +++ b/firefox-redhat-default-prefs.js @@ -26,4 +26,6 @@ pref("media.gmp-gmpopenh264.enabled",false); pref("plugins.notifyMissingFlash", false); /* See https://bugzilla.redhat.com/show_bug.cgi?id=1226489 */ pref("browser.display.use_system_colors", false); -pref("layers.use-image-offscreen-surfaces", false); \ No newline at end of file +pref("layers.use-image-offscreen-surfaces", false); +/* Allow sending credetials to all https:// sites */ +pref("network.negotiate-auth.trusted-uris", "https://") diff --git a/firefox.spec b/firefox.spec index 8dade14..b35348f 100644 --- a/firefox.spec +++ b/firefox.spec @@ -85,7 +85,7 @@ Summary: Mozilla Firefox Web browser Name: firefox Version: 46.0.1 -Release: 8%{?pre_tag}%{?dist} +Release: 9%{?pre_tag}%{?dist} URL: https://www.mozilla.org/firefox/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -133,6 +133,7 @@ Patch403: mozilla-1216658.patch Patch404: mozilla-1270046.patch # Remove when mozbz#1269319 lands Patch405: mozilla-1245783.patch +Patch406: mozilla-890908-async-negotiate.patch # Debian patches Patch500: mozilla-440908.patch @@ -280,6 +281,7 @@ cd %{tarballdir} %patch403 -p1 -b .1216658 %patch404 -p1 -b .1270046 %patch405 -p1 -b .1245783 +%patch406 -p1 -b .890908-async-negotiate # Debian extension patch %patch500 -p1 -b .440908 @@ -791,6 +793,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog +* Thu May 26 2016 Jan Horak - 46.0.1-9 +- Negotiate authentication is made off the main thread (mozbz#890908) + * Mon May 23 2016 Martin Stransky - 46.0.1-8 - Rebuilt for new bookmarks (rhbz#1338010) - Fixed build issue in Gtk3.20 patch diff --git a/mozilla-890908-async-negotiate.patch b/mozilla-890908-async-negotiate.patch new file mode 100644 index 0000000..e67faa4 --- /dev/null +++ b/mozilla-890908-async-negotiate.patch @@ -0,0 +1,727 @@ +diff -up firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp.890908-async-negotiate firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp +--- firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp.890908-async-negotiate 2016-05-03 07:31:11.000000000 +0200 ++++ firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp 2016-05-26 10:58:14.754420347 +0200 +@@ -38,6 +38,10 @@ + #include "prnetdb.h" + #include "mozilla/Likely.h" + #include "mozilla/Snprintf.h" ++#include "nsThreadUtils.h" ++#include "nsIHttpAuthenticatorCallback.h" ++#include "mozilla/Mutex.h" ++#include "nsICancelable.h" + + //----------------------------------------------------------------------------- + +@@ -49,6 +53,7 @@ static const char kNegotiateAuthAllowNon + static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi"; + + #define kNegotiateLen (sizeof(kNegotiate)-1) ++#define DEFAULT_THREAD_TIMEOUT_MS 30000 + + //----------------------------------------------------------------------------- + +@@ -172,7 +177,237 @@ nsHttpNegotiateAuth::ChallengeReceived(n + } + + NS_IMPL_ISUPPORTS(nsHttpNegotiateAuth, nsIHttpAuthenticator) +- ++ ++namespace { ++ ++// ++// GetNextTokenCompleteEvent ++// ++// This event is fired on main thread when async call of ++// nsHttpNegotiateAuth::GenerateCredentials is finished. During the Run() ++// method the nsIHttpAuthenticatorCallback::OnCredsAvailable is called with ++// obtained credentials, flags and NS_OK when successful, otherwise ++// NS_ERROR_FAILURE is returned as a result of failed operation. ++// ++class GetNextTokenCompleteEvent final : public nsIRunnable, ++ public nsICancelable ++{ ++ virtual ~GetNextTokenCompleteEvent() ++ { ++ if (mCreds) { ++ free(mCreds); ++ } ++ }; ++ ++public: ++ NS_DECL_THREADSAFE_ISUPPORTS ++ ++ explicit GetNextTokenCompleteEvent(nsIHttpAuthenticatorCallback* aCallback) ++ : mCallback(aCallback) ++ , mCreds(nullptr) ++ , mCancelled(false) ++ { ++ } ++ ++ NS_IMETHODIMP DispatchSuccess(char *aCreds, ++ uint32_t aFlags, ++ nsISupports *aSessionState, ++ nsISupports *aContinuationState) ++ { ++ // Called from worker thread ++ MOZ_ASSERT(!NS_IsMainThread()); ++ ++ mCreds = aCreds; ++ mFlags = aFlags; ++ mResult = NS_OK; ++ mSessionState = aSessionState; ++ mContinuationState = aContinuationState; ++ return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); ++ } ++ ++ NS_IMETHODIMP DispatchError() ++ { ++ // Called from worker thread ++ MOZ_ASSERT(!NS_IsMainThread()); ++ ++ mResult = NS_ERROR_FAILURE; ++ return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); ++ } ++ ++ NS_IMETHODIMP Run() override ++ { ++ // Runs on main thread ++ MOZ_ASSERT(NS_IsMainThread()); ++ ++ if (!mCancelled) { ++ nsCOMPtr callback; ++ callback.swap(mCallback); ++ callback->OnCredsGenerated(mCreds, mFlags, mResult, mSessionState, mContinuationState); ++ } ++ return NS_OK; ++ } ++ ++ NS_IMETHODIMP Cancel(nsresult aReason) override ++ { ++ // Supposed to be called from main thread ++ MOZ_ASSERT(NS_IsMainThread()); ++ ++ mCancelled = true; ++ return NS_OK; ++ } ++ ++private: ++ nsCOMPtr mCallback; ++ char *mCreds; // This class owns it, freed in destructor ++ uint32_t mFlags; ++ nsresult mResult; ++ bool mCancelled; ++ nsCOMPtr mSessionState; ++ nsCOMPtr mContinuationState; ++}; ++ ++NS_IMPL_ISUPPORTS(GetNextTokenCompleteEvent, nsIRunnable, nsICancelable) ++ ++// ++// GetNextTokenRunnable ++// ++// This runnable is created by GenerateCredentialsAsync and it runs ++// in nsHttpNegotiateAuth::mNegotiateThread and calling GenerateCredentials. ++// ++class GetNextTokenRunnable final : public mozilla::Runnable ++{ ++ virtual ~GetNextTokenRunnable() {} ++ public: ++ GetNextTokenRunnable(nsIHttpAuthenticableChannel *authChannel, ++ const char *challenge, ++ bool isProxyAuth, ++ const char16_t *domain, ++ const char16_t *username, ++ const char16_t *password, ++ nsISupports *sessionState, ++ nsISupports *continuationState, ++ GetNextTokenCompleteEvent *aCompleteEvent ++ ) ++ : mAuthChannel(authChannel) ++ , mChallenge(challenge) ++ , mIsProxyAuth(isProxyAuth) ++ , mDomain(domain) ++ , mUsername(username) ++ , mPassword(password) ++ , mSessionState(sessionState) ++ , mContinuationState(continuationState) ++ , mCompleteEvent(aCompleteEvent) ++ { ++ } ++ ++ NS_IMETHODIMP Run() override ++ { ++ // Runs on worker thread ++ MOZ_ASSERT(!NS_IsMainThread()); ++ ++ char *creds; ++ uint32_t flags; ++ nsresult rv = ObtainCredentialsAndFlags(&creds, &flags); ++ if (NS_FAILED(rv)) { ++ return mCompleteEvent->DispatchError(); ++ } ++ ++ return mCompleteEvent->DispatchSuccess(creds, flags, mSessionState, mContinuationState); ++ } ++ ++ NS_IMETHODIMP ObtainCredentialsAndFlags(char **aCreds, uint32_t *aFlags) ++ { ++ // Use negotiate service to call GenerateCredentials outside of main thread ++ nsAutoCString contractId; ++ contractId.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX); ++ contractId.Append("negotiate"); ++ nsresult rv; ++ nsCOMPtr authenticator = do_GetService(contractId.get(), &rv); ++ NS_ENSURE_SUCCESS(rv, rv); ++ nsISupports *sessionState = mSessionState; ++ nsISupports *continuationState = mContinuationState; ++ // The continuationState is for the sake of completeness propagated ++ // to the caller (despite it is not changed in any GenerateCredentials ++ // implementation). ++ // ++ // The only implementation that use sessionState is the ++ // nsHttpDigestAuth::GenerateCredentials. Since there's no reason ++ // to implement nsHttpDigestAuth::GenerateCredentialsAsync ++ // because digest auth does not block the main thread, we won't ++ // propagate changes to sessionState to the caller because of ++ // the change is too complicated on the caller side. ++ rv = authenticator->GenerateCredentials(mAuthChannel, ++ mChallenge.get(), ++ mIsProxyAuth, ++ mDomain.get(), ++ mUsername.get(), ++ mPassword.get(), ++ &sessionState, ++ &continuationState, ++ aFlags, ++ aCreds); ++ mSessionState = sessionState; ++ mContinuationState = continuationState; ++ return rv; ++ } ++ private: ++ nsCOMPtr mAuthChannel; ++ nsCString mChallenge; ++ bool mIsProxyAuth; ++ nsString mDomain; ++ nsString mUsername; ++ nsString mPassword; ++ nsCOMPtr mSessionState; ++ nsCOMPtr mContinuationState; ++ RefPtr mCompleteEvent; ++}; ++ ++} // anonymous namespace ++ ++NS_IMETHODIMP ++nsHttpNegotiateAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, ++ nsIHttpAuthenticatorCallback* aCallback, ++ const char *challenge, ++ bool isProxyAuth, ++ const char16_t *domain, ++ const char16_t *username, ++ const char16_t *password, ++ nsISupports *sessionState, ++ nsISupports *continuationState, ++ nsICancelable **aCancelable) ++{ ++ NS_ENSURE_ARG(aCallback); ++ NS_ENSURE_ARG_POINTER(aCancelable); ++ ++ RefPtr cancelEvent = ++ new GetNextTokenCompleteEvent(aCallback); ++ ++ ++ nsCOMPtr getNextTokenRunnable = ++ new GetNextTokenRunnable(authChannel, ++ challenge, ++ isProxyAuth, ++ domain, ++ username, ++ password, ++ sessionState, ++ continuationState, ++ cancelEvent); ++ cancelEvent.forget(aCancelable); ++ ++ nsresult rv; ++ if (!mNegotiateThread) { ++ mNegotiateThread = ++ new mozilla::LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS, ++ NS_LITERAL_CSTRING("NegotiateAuth")); ++ NS_ENSURE_TRUE(mNegotiateThread, NS_ERROR_OUT_OF_MEMORY); ++ } ++ rv = mNegotiateThread->Dispatch(getNextTokenRunnable, NS_DISPATCH_NORMAL); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ return NS_OK; ++} ++ + // + // GenerateCredentials + // +diff -up firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.h.890908-async-negotiate firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.h +--- firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.h.890908-async-negotiate 2016-05-03 07:31:11.000000000 +0200 ++++ firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.h 2016-05-26 10:51:14.816550760 +0200 +@@ -10,6 +10,7 @@ + #include "nsIURI.h" + #include "nsSubstring.h" + #include "mozilla/Attributes.h" ++#include "mozilla/LazyIdleThread.h" + + // The nsHttpNegotiateAuth class provides responses for the GSS-API Negotiate method + // as specified by Microsoft in draft-brezak-spnego-http-04.txt +@@ -17,7 +18,7 @@ + class nsHttpNegotiateAuth final : public nsIHttpAuthenticator + { + public: +- NS_DECL_ISUPPORTS ++ NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIHTTPAUTHENTICATOR + + private: +@@ -37,5 +38,7 @@ private: + int32_t port, + const char *baseStart, + const char *baseEnd); ++ // Thread for GenerateCredentialsAsync ++ RefPtr mNegotiateThread; + }; + #endif /* nsHttpNegotiateAuth_h__ */ +diff -up firefox-46.0.1/netwerk/base/moz.build.rej.890908-async-negotiate firefox-46.0.1/netwerk/base/moz.build.rej +diff -up firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl.890908-async-negotiate firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl +--- firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl.890908-async-negotiate 2016-05-26 10:51:14.816550760 +0200 ++++ firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl 2016-05-26 10:51:14.816550760 +0200 +@@ -0,0 +1,31 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "nsISupports.idl" ++ ++[scriptable, uuid(d989cb03-e446-4086-b9e6-46842cb97bd5)] ++interface nsIHttpAuthenticatorCallback : nsISupports ++{ ++ /** ++ * Authentication data for a header is available. ++ * ++ * @param aCreds ++ * Credentials which were obtained asynchonously. ++ * @param aFlags ++ * Flags set by asynchronous call. ++ * @param aResult ++ * Result status of credentials generation ++ * @param aSessionState ++ * Modified session state to be passed to caller ++ * @param aContinuationState ++ * Modified continuation state to be passed to caller ++ */ ++ void onCredsGenerated(in string aCreds, ++ in unsigned long aFlags, ++ in nsresult aResult, ++ in nsISupports aSessionsState, ++ in nsISupports aContinuationState); ++ ++}; ++ +diff -up firefox-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp +--- firefox-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200 ++++ firefox-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp 2016-05-26 10:51:14.816550760 +0200 +@@ -49,6 +49,20 @@ nsHttpBasicAuth::ChallengeReceived(nsIHt + *identityInvalid = true; + return NS_OK; + } ++NS_IMETHODIMP ++nsHttpBasicAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, ++ nsIHttpAuthenticatorCallback* aCallback, ++ const char *challenge, ++ bool isProxyAuth, ++ const char16_t *domain, ++ const char16_t *username, ++ const char16_t *password, ++ nsISupports *sessionState, ++ nsISupports *continuationState, ++ nsICancelable **aCancellable) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} + + NS_IMETHODIMP + nsHttpBasicAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel, +diff -up firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp +--- firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200 ++++ firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp 2016-05-26 10:51:14.817550760 +0200 +@@ -267,6 +267,11 @@ nsHttpChannelAuthProvider::Cancel(nsresu + mAsyncPromptAuthCancelable->Cancel(status); + mAsyncPromptAuthCancelable = nullptr; + } ++ ++ if (mGenerateCredentialsCancelable) { ++ mGenerateCredentialsCancelable->Cancel(status); ++ mGenerateCredentialsCancelable = nullptr; ++ } + return NS_OK; + } + +@@ -280,6 +285,11 @@ nsHttpChannelAuthProvider::Disconnect(ns + mAsyncPromptAuthCancelable = nullptr; + } + ++ if (mGenerateCredentialsCancelable) { ++ mGenerateCredentialsCancelable->Cancel(status); ++ mGenerateCredentialsCancelable = nullptr; ++ } ++ + NS_IF_RELEASE(mProxyAuthContinuationState); + NS_IF_RELEASE(mAuthContinuationState); + +@@ -355,11 +365,6 @@ nsHttpChannelAuthProvider::GenCredsAndSe + char **result) + { + nsresult rv; +- uint32_t authFlags; +- +- rv = auth->GetAuthFlags(&authFlags); +- if (NS_FAILED(rv)) return rv; +- + nsISupports *ss = sessionState; + + // set informations that depend on whether +@@ -373,6 +378,22 @@ nsHttpChannelAuthProvider::GenCredsAndSe + continuationState = &mAuthContinuationState; + } + ++ rv = auth->GenerateCredentialsAsync(mAuthChannel, ++ this, ++ challenge, ++ proxyAuth, ++ ident.Domain(), ++ ident.User(), ++ ident.Password(), ++ ss, ++ *continuationState, ++ getter_AddRefs(mGenerateCredentialsCancelable)); ++ if (NS_SUCCEEDED(rv)) { ++ // Calling generate credentials async, results will be dispatched to the ++ // main thread by calling OnCredsGenerated method ++ return NS_ERROR_IN_PROGRESS; ++ } ++ + uint32_t generateFlags; + rv = auth->GenerateCredentials(mAuthChannel, + challenge, +@@ -393,6 +414,29 @@ nsHttpChannelAuthProvider::GenCredsAndSe + LOG(("generated creds: %s\n", *result)); + #endif + ++ return UpdateCache(auth, scheme, host, port, directory, realm, ++ challenge, ident, *result, generateFlags, sessionState); ++} ++ ++nsresult ++nsHttpChannelAuthProvider::UpdateCache(nsIHttpAuthenticator *auth, ++ const char *scheme, ++ const char *host, ++ int32_t port, ++ const char *directory, ++ const char *realm, ++ const char *challenge, ++ const nsHttpAuthIdentity &ident, ++ const char *creds, ++ uint32_t generateFlags, ++ nsISupports *sessionState) ++{ ++ nsresult rv; ++ ++ uint32_t authFlags; ++ rv = auth->GetAuthFlags(&authFlags); ++ if (NS_FAILED(rv)) return rv; ++ + // find out if this authenticator allows reuse of credentials and/or + // challenge. + bool saveCreds = +@@ -410,6 +454,7 @@ nsHttpChannelAuthProvider::GenCredsAndSe + nsAutoCString suffix; + GetOriginAttributesSuffix(chan, suffix); + ++ + // create a cache entry. we do this even though we don't yet know that + // these credentials are valid b/c we need to avoid prompting the user + // more than once in case the credentials are valid. +@@ -417,12 +462,13 @@ nsHttpChannelAuthProvider::GenCredsAndSe + // if the credentials are not reusable, then we don't bother sticking + // them in the auth cache. + rv = authCache->SetAuthEntry(scheme, host, port, directory, realm, +- saveCreds ? *result : nullptr, ++ saveCreds ? creds : nullptr, + saveChallenge ? challenge : nullptr, + suffix, + saveIdentity ? &ident : nullptr, + sessionState); + return rv; ++ + } + + nsresult +@@ -1224,6 +1270,66 @@ NS_IMETHODIMP nsHttpChannelAuthProvider: + } + + nsresult ++nsHttpChannelAuthProvider::OnCredsGenerated(const char *aGeneratedCreds, ++ uint32_t aFlags, ++ nsresult aResult, ++ nsISupports* aSessionState, ++ nsISupports* aContinuationState) ++{ ++ nsresult rv; ++ ++ MOZ_ASSERT(NS_IsMainThread()); ++ ++ // When channel is closed, do not proceed ++ if (!mAuthChannel) { ++ return NS_OK; ++ } ++ ++ mGenerateCredentialsCancelable = nullptr; ++ ++ if (NS_FAILED(aResult)) { ++ return OnAuthCancelled(nullptr, true); ++ } ++ ++ // We want to update m(Proxy)AuthContinuationState in case it was changed by ++ // nsHttpNegotiateAuth::GenerateCredentials ++ nsCOMPtr contState(aContinuationState); ++ if (mProxyAuth) { ++ contState.swap(mProxyAuthContinuationState); ++ NS_IF_ADDREF(mProxyAuthContinuationState); ++ } else { ++ contState.swap(mAuthContinuationState); ++ NS_IF_ADDREF(mAuthContinuationState); ++ } ++ ++ nsCOMPtr auth; ++ nsAutoCString unused; ++ rv = GetAuthenticator(mCurrentChallenge.get(), unused, getter_AddRefs(auth)); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ const char *host; ++ int32_t port; ++ nsHttpAuthIdentity *ident; ++ nsAutoCString directory, scheme; ++ nsISupports **unusedContinuationState; ++ ++ // Get realm from challenge ++ nsAutoCString realm; ++ ParseRealm(mCurrentChallenge.get(), realm); ++ ++ rv = GetAuthorizationMembers(mProxyAuth, scheme, host, port, ++ directory, ident, unusedContinuationState); ++ if (NS_FAILED(rv)) return rv; ++ ++ UpdateCache(auth, scheme.get(), host, port, directory.get(), realm.get(), ++ mCurrentChallenge.get(), *ident, aGeneratedCreds, aFlags, aSessionState); ++ mCurrentChallenge.Truncate(); ++ ++ ContinueOnAuthAvailable(nsDependentCString(aGeneratedCreds)); ++ return NS_OK; ++} ++ ++nsresult + nsHttpChannelAuthProvider::ContinueOnAuthAvailable(const nsCSubstring& creds) + { + nsresult rv; +@@ -1457,7 +1563,7 @@ nsHttpChannelAuthProvider::GetCurrentPat + } + + NS_IMPL_ISUPPORTS(nsHttpChannelAuthProvider, nsICancelable, +- nsIHttpChannelAuthProvider, nsIAuthPromptCallback) ++ nsIHttpChannelAuthProvider, nsIAuthPromptCallback, nsIHttpAuthenticatorCallback) + + } // namespace net + } // namespace mozilla +diff -up firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h +--- firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200 ++++ firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h 2016-05-26 10:51:14.817550760 +0200 +@@ -9,11 +9,13 @@ + + #include "nsIHttpChannelAuthProvider.h" + #include "nsIAuthPromptCallback.h" ++#include "nsIHttpAuthenticatorCallback.h" + #include "nsString.h" + #include "nsCOMPtr.h" + #include "nsHttpAuthCache.h" + #include "nsProxyInfo.h" + #include "nsCRT.h" ++#include "nsICancelableRunnable.h" + + class nsIHttpAuthenticableChannel; + class nsIHttpAuthenticator; +@@ -25,12 +27,14 @@ class nsHttpHandler; + + class nsHttpChannelAuthProvider : public nsIHttpChannelAuthProvider + , public nsIAuthPromptCallback ++ , public nsIHttpAuthenticatorCallback + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSICANCELABLE + NS_DECL_NSIHTTPCHANNELAUTHPROVIDER + NS_DECL_NSIAUTHPROMPTCALLBACK ++ NS_DECL_NSIHTTPAUTHENTICATORCALLBACK + + nsHttpChannelAuthProvider(); + static void InitializePrefs(); +@@ -117,6 +121,19 @@ private: + // For more details look at the bug 647010. + bool BlockPrompt(); + ++ // Store credentials to the cache when appropriate aFlags are set. ++ nsresult UpdateCache(nsIHttpAuthenticator *aAuth, ++ const char *aScheme, ++ const char *aHost, ++ int32_t aPort, ++ const char *aDirectory, ++ const char *aRealm, ++ const char *aChallenge, ++ const nsHttpAuthIdentity &aIdent, ++ const char *aCreds, ++ uint32_t aGenerateFlags, ++ nsISupports *aSessionState); ++ + private: + nsIHttpAuthenticableChannel *mAuthChannel; // weak ref + +@@ -160,6 +177,7 @@ private: + // authentication credentials dialogs for sub-resources and cross-origin + // sub-resources. + static uint32_t sAuthAllowPref; ++ nsCOMPtr mGenerateCredentialsCancelable; + }; + + } // namespace net +diff -up firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp +--- firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200 ++++ firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp 2016-05-26 10:51:14.817550760 +0200 +@@ -158,6 +158,22 @@ nsHttpDigestAuth::ChallengeReceived(nsIH + return NS_OK; + } + ++ ++NS_IMETHODIMP ++nsHttpDigestAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, ++ nsIHttpAuthenticatorCallback* aCallback, ++ const char *challenge, ++ bool isProxyAuth, ++ const char16_t *domain, ++ const char16_t *username, ++ const char16_t *password, ++ nsISupports *sessionState, ++ nsISupports *continuationState, ++ nsICancelable **aCancellable) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} ++ + NS_IMETHODIMP + nsHttpDigestAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel, + const char *challenge, +diff -up firefox-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp +--- firefox-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200 ++++ firefox-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp 2016-05-26 10:51:14.817550760 +0200 +@@ -323,6 +323,21 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHtt + } + + NS_IMETHODIMP ++nsHttpNTLMAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, ++ nsIHttpAuthenticatorCallback* aCallback, ++ const char *challenge, ++ bool isProxyAuth, ++ const char16_t *domain, ++ const char16_t *username, ++ const char16_t *password, ++ nsISupports *sessionState, ++ nsISupports *continuationState, ++ nsICancelable **aCancellable) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} ++ ++NS_IMETHODIMP + nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel, + const char *challenge, + bool isProxyAuth, +diff -up firefox-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl +--- firefox-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200 ++++ firefox-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl 2016-05-26 10:51:14.817550760 +0200 +@@ -6,6 +6,8 @@ + #include "nsISupports.idl" + + interface nsIHttpAuthenticableChannel; ++interface nsIHttpAuthenticatorCallback; ++interface nsICancelable; + + /** + * nsIHttpAuthenticator +@@ -18,7 +20,7 @@ interface nsIHttpAuthenticableChannel; + * where is the lower-cased value of the authentication scheme + * found in the server challenge per the rules of RFC 2617. + */ +-[scriptable, uuid(16784db0-fcb1-4352-b0c9-6a3a67e3cf79)] ++[scriptable, uuid(fef7db8a-a4e2-49d1-9685-19ed7e309b7d)] + interface nsIHttpAuthenticator : nsISupports + { + /** +@@ -54,6 +56,54 @@ interface nsIHttpAuthenticator : nsISupp + + /** + * Called to generate the authentication credentials for a particular ++ * server/proxy challenge asynchronously. Credentials will be sent back ++ * to the server via an Authorization/Proxy-Authorization header. ++ * ++ * @param aChannel ++ * the http channel requesting credentials ++ * @param aCallback ++ * callback function to be called when credentials are available ++ * @param aChallenge ++ * the challenge from the WWW-Authenticate/Proxy-Authenticate ++ * server response header. (possibly from the auth cache.) ++ * @param aProxyAuth ++ * flag indicating whether or not aChallenge is from a proxy. ++ * @param aDomain ++ * string containing the domain name (if appropriate) ++ * @param aUser ++ * string containing the user name ++ * @param aPassword ++ * string containing the password ++ * @param aSessionState ++ * state stored along side the user's identity in the auth cache ++ * for the lifetime of the browser session. if a new auth cache ++ * entry is created for this challenge, then this parameter will ++ * be null. on return, the result will be stored in the new auth ++ * cache entry. this parameter is non-null when an auth cache entry ++ * is being reused. currently modification of session state is not ++ * communicated to caller, thus caching credentials obtained by ++ * asynchronous way is not supported. ++ * @param aContinuationState ++ * state held by the channel between consecutive calls to ++ * generateCredentials, assuming multiple calls are required ++ * to authenticate. this state is held for at most the lifetime of ++ * the channel. ++ * @pram aCancel ++ * returns cancellable runnable object which caller can use to cancel ++ * calling aCallback when finished. ++ */ ++ void generateCredentialsAsync(in nsIHttpAuthenticableChannel aChannel, ++ in nsIHttpAuthenticatorCallback aCallback, ++ in string aChallenge, ++ in boolean aProxyAuth, ++ in wstring aDomain, ++ in wstring aUser, ++ in wstring aPassword, ++ in nsISupports aSessionState, ++ in nsISupports aContinuationState, ++ out nsICancelable aCancel); ++ /** ++ * Called to generate the authentication credentials for a particular + * server/proxy challenge. This is the value that will be sent back + * to the server via an Authorization/Proxy-Authorization header. + * -- cgit