728 lines
30 KiB
Diff
728 lines
30 KiB
Diff
|
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<nsIHttpAuthenticatorCallback> 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<nsIHttpAuthenticatorCallback> mCallback;
|
||
|
+ char *mCreds; // This class owns it, freed in destructor
|
||
|
+ uint32_t mFlags;
|
||
|
+ nsresult mResult;
|
||
|
+ bool mCancelled;
|
||
|
+ nsCOMPtr<nsISupports> mSessionState;
|
||
|
+ nsCOMPtr<nsISupports> 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<nsIHttpAuthenticator> 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<nsIHttpAuthenticableChannel> mAuthChannel;
|
||
|
+ nsCString mChallenge;
|
||
|
+ bool mIsProxyAuth;
|
||
|
+ nsString mDomain;
|
||
|
+ nsString mUsername;
|
||
|
+ nsString mPassword;
|
||
|
+ nsCOMPtr<nsISupports> mSessionState;
|
||
|
+ nsCOMPtr<nsISupports> mContinuationState;
|
||
|
+ RefPtr<GetNextTokenCompleteEvent> 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<GetNextTokenCompleteEvent> cancelEvent =
|
||
|
+ new GetNextTokenCompleteEvent(aCallback);
|
||
|
+
|
||
|
+
|
||
|
+ nsCOMPtr<nsIRunnable> 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<mozilla::LazyIdleThread> 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<nsISupports> contState(aContinuationState);
|
||
|
+ if (mProxyAuth) {
|
||
|
+ contState.swap(mProxyAuthContinuationState);
|
||
|
+ NS_IF_ADDREF(mProxyAuthContinuationState);
|
||
|
+ } else {
|
||
|
+ contState.swap(mAuthContinuationState);
|
||
|
+ NS_IF_ADDREF(mAuthContinuationState);
|
||
|
+ }
|
||
|
+
|
||
|
+ nsCOMPtr<nsIHttpAuthenticator> 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<nsICancelable> 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 <auth-scheme> 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.
|
||
|
*
|