2017-10-27 01:08:41 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2016-02-09 18:43:00 +03:00
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
#ifndef mozilla_dom_U2F_h
|
|
|
|
#define mozilla_dom_U2F_h
|
|
|
|
|
|
|
|
#include "js/TypeDecls.h"
|
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#include "mozilla/dom/BindingDeclarations.h"
|
|
|
|
#include "mozilla/dom/Nullable.h"
|
2016-10-13 06:56:56 +03:00
|
|
|
#include "mozilla/dom/U2FBinding.h"
|
2017-12-05 21:05:06 +03:00
|
|
|
#include "mozilla/dom/WebAuthnManagerBase.h"
|
2016-02-09 18:43:00 +03:00
|
|
|
#include "mozilla/ErrorResult.h"
|
2019-01-19 02:21:46 +03:00
|
|
|
#include "mozilla/Maybe.h"
|
2016-10-13 06:56:56 +03:00
|
|
|
#include "mozilla/MozPromise.h"
|
|
|
|
#include "nsProxyRelease.h"
|
2016-02-09 18:43:00 +03:00
|
|
|
#include "nsWrapperCache.h"
|
2017-01-09 23:22:49 +03:00
|
|
|
#include "U2FAuthenticator.h"
|
2016-11-22 09:19:06 +03:00
|
|
|
|
2017-06-10 07:24:46 +03:00
|
|
|
namespace mozilla {
|
2016-02-09 18:43:00 +03:00
|
|
|
namespace dom {
|
|
|
|
|
2018-02-12 23:46:11 +03:00
|
|
|
class WebAuthnMakeCredentialResult;
|
|
|
|
class WebAuthnGetAssertionResult;
|
|
|
|
|
2016-02-09 18:43:00 +03:00
|
|
|
class U2FRegisterCallback;
|
|
|
|
class U2FSignCallback;
|
|
|
|
|
2016-10-13 06:56:56 +03:00
|
|
|
// Defined in U2FBinding.h by the U2F.webidl; their use requires a JSContext.
|
|
|
|
struct RegisterRequest;
|
|
|
|
struct RegisteredKey;
|
|
|
|
|
2017-11-28 12:21:07 +03:00
|
|
|
class U2FTransaction {
|
2017-12-08 18:55:52 +03:00
|
|
|
typedef Variant<nsMainThreadPtrHandle<U2FRegisterCallback>,
|
|
|
|
nsMainThreadPtrHandle<U2FSignCallback>>
|
|
|
|
U2FCallback;
|
|
|
|
|
2017-11-28 12:21:07 +03:00
|
|
|
public:
|
2018-05-30 17:06:09 +03:00
|
|
|
explicit U2FTransaction(const U2FCallback&& aCallback)
|
2018-05-30 22:15:35 +03:00
|
|
|
: mCallback(std::move(aCallback)), mId(NextId()) {
|
2017-11-28 12:21:07 +03:00
|
|
|
MOZ_ASSERT(mId > 0);
|
|
|
|
}
|
|
|
|
|
2017-12-08 18:55:52 +03:00
|
|
|
bool HasRegisterCallback() {
|
|
|
|
return mCallback.is<nsMainThreadPtrHandle<U2FRegisterCallback>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto& GetRegisterCallback() {
|
|
|
|
return mCallback.as<nsMainThreadPtrHandle<U2FRegisterCallback>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool HasSignCallback() {
|
|
|
|
return mCallback.is<nsMainThreadPtrHandle<U2FSignCallback>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto& GetSignCallback() {
|
|
|
|
return mCallback.as<nsMainThreadPtrHandle<U2FSignCallback>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
// The callback passed to the API.
|
|
|
|
U2FCallback mCallback;
|
|
|
|
|
2017-11-28 12:21:07 +03:00
|
|
|
// Unique transaction id.
|
|
|
|
uint64_t mId;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Generates a unique id for new transactions. This doesn't have to be unique
|
|
|
|
// forever, it's sufficient to differentiate between temporally close
|
|
|
|
// transactions, where messages can intersect. Can overflow.
|
|
|
|
static uint64_t NextId() {
|
|
|
|
static uint64_t id = 0;
|
|
|
|
return ++id;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-12-06 20:41:58 +03:00
|
|
|
class U2F final : public WebAuthnManagerBase, public nsWrapperCache {
|
2016-02-09 18:43:00 +03:00
|
|
|
public:
|
2019-01-19 02:21:46 +03:00
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(U2F,
|
|
|
|
WebAuthnManagerBase)
|
2016-02-09 18:43:00 +03:00
|
|
|
|
2017-12-06 20:41:58 +03:00
|
|
|
explicit U2F(nsPIDOMWindowInner* aParent) : WebAuthnManagerBase(aParent) {}
|
2016-02-09 18:43:00 +03:00
|
|
|
|
|
|
|
nsPIDOMWindowInner* GetParentObject() const { return mParent; }
|
|
|
|
|
Bug 1245527 - Rewrite U2F.cpp to use U2FTokenManager. r=keeler, r=ttaubert
- This patch reworks the U2F module to asynchronously call U2FManager,
which in turn handles constructing and managing the U2FTokenManager
via IPC.
- Add U2FTransaction{Parent,Child} implementations to mirror similar ones for
WebAuthn
- Rewrite all tests to compensate for U2F executing asynchronously now.
- Used async tasks, used the manifest parameters for scheme, and generally
made these cleaner.
- The mochitest "pref =" functionality from Bug 1328830 doesn't support Android
yet, causing breakage on Android. Rework the tests to go back to the old way
of using iframes to test U2F.
NOTE TO REVIEWERS:
Since this is huge, I recommend the following:
keeler - please review U2F.cpp/h, the tests, and the security-prefs.js. Most
of the U2F logic is still in U2F.cpp like before, but there's been
some reworking of how it is called.
ttaubert - please review U2FManager, the Transaction classes, build changes,
and the changes to nsGlobalWindow. All of these should be very
similar to the WebAuthn code it's patterned off.
MozReview-Commit-ID: C1ZN2ch66Rm
--HG--
extra : rebase_source : 5a2c52b0340c13f471af5040b998eb7e661b1981
2017-09-11 22:56:59 +03:00
|
|
|
void Init(ErrorResult& aRv);
|
2016-02-09 18:43:00 +03:00
|
|
|
|
|
|
|
virtual JSObject* WrapObject(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) override;
|
|
|
|
|
|
|
|
void Register(const nsAString& aAppId,
|
|
|
|
const Sequence<RegisterRequest>& aRegisterRequests,
|
|
|
|
const Sequence<RegisteredKey>& aRegisteredKeys,
|
|
|
|
U2FRegisterCallback& aCallback,
|
|
|
|
const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
|
|
|
|
ErrorResult& aRv);
|
|
|
|
|
|
|
|
void Sign(const nsAString& aAppId, const nsAString& aChallenge,
|
|
|
|
const Sequence<RegisteredKey>& aRegisteredKeys,
|
|
|
|
U2FSignCallback& aCallback,
|
|
|
|
const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
|
|
|
|
ErrorResult& aRv);
|
|
|
|
|
2017-12-05 21:05:06 +03:00
|
|
|
// WebAuthnManagerBase
|
|
|
|
|
|
|
|
void FinishMakeCredential(
|
|
|
|
const uint64_t& aTransactionId,
|
2018-02-12 23:08:54 +03:00
|
|
|
const WebAuthnMakeCredentialResult& aResult) override;
|
2017-11-28 12:21:07 +03:00
|
|
|
|
2017-12-05 21:05:06 +03:00
|
|
|
void FinishGetAssertion(const uint64_t& aTransactionId,
|
2018-02-12 23:08:54 +03:00
|
|
|
const WebAuthnGetAssertionResult& aResult) override;
|
2017-11-28 12:21:07 +03:00
|
|
|
|
2017-12-05 21:05:06 +03:00
|
|
|
void RequestAborted(const uint64_t& aTransactionId,
|
|
|
|
const nsresult& aError) override;
|
2017-11-28 12:21:07 +03:00
|
|
|
|
2017-12-06 20:41:58 +03:00
|
|
|
protected:
|
|
|
|
// Cancels the current transaction (by sending a Cancel message to the
|
|
|
|
// parent) and rejects it by calling RejectTransaction().
|
|
|
|
void CancelTransaction(const nsresult& aError) override;
|
2017-11-28 12:21:07 +03:00
|
|
|
|
|
|
|
private:
|
|
|
|
~U2F();
|
|
|
|
|
2017-12-08 18:55:52 +03:00
|
|
|
template <typename T, typename C>
|
|
|
|
void ExecuteCallback(T& aResp, nsMainThreadPtrHandle<C>& aCb);
|
|
|
|
|
2017-11-28 12:21:07 +03:00
|
|
|
// Clears all information we have about the current transaction.
|
|
|
|
void ClearTransaction();
|
2017-12-08 18:55:52 +03:00
|
|
|
// Rejects the current transaction and clears it.
|
2017-11-28 12:21:07 +03:00
|
|
|
void RejectTransaction(const nsresult& aError);
|
2017-09-19 17:55:38 +03:00
|
|
|
|
2017-09-09 10:09:21 +03:00
|
|
|
nsString mOrigin;
|
2017-11-28 12:21:07 +03:00
|
|
|
|
|
|
|
// The current transaction, if any.
|
|
|
|
Maybe<U2FTransaction> mTransaction;
|
2016-02-09 18:43:00 +03:00
|
|
|
};
|
|
|
|
|
2019-01-19 02:21:46 +03:00
|
|
|
inline void ImplCycleCollectionTraverse(
|
|
|
|
nsCycleCollectionTraversalCallback& aCallback, U2FTransaction& aTransaction,
|
|
|
|
const char* aName, uint32_t aFlags = 0) {
|
|
|
|
if (aTransaction.HasRegisterCallback()) {
|
|
|
|
CycleCollectionNoteChild(
|
|
|
|
aCallback, aTransaction.GetRegisterCallback().get(), aName, aFlags);
|
|
|
|
} else {
|
|
|
|
CycleCollectionNoteChild(aCallback, aTransaction.GetSignCallback().get(),
|
|
|
|
aName, aFlags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void ImplCycleCollectionUnlink(U2FTransaction& aTransaction) {
|
|
|
|
if (aTransaction.HasRegisterCallback()) {
|
|
|
|
aTransaction.GetRegisterCallback() = nullptr;
|
|
|
|
} else {
|
|
|
|
aTransaction.GetSignCallback() = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-09 18:43:00 +03:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_dom_U2F_h
|