/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=8 et tw=80 : */ /* 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_net_PackagedAppVerifier_h #define mozilla_net_PackagedAppVerifier_h #include "nsICacheEntry.h" #include "nsIURI.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" #include "nsICryptoHash.h" #include "nsIPackagedAppVerifier.h" #include "mozilla/LinkedList.h" #include "nsIPackagedAppUtils.h" namespace mozilla { namespace net { class PackagedAppVerifier final : public nsIPackagedAppVerifier , public nsIVerificationCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSIPACKAGEDAPPVERIFIER NS_DECL_NSIVERIFICATIONCALLBACK public: enum EState { // The initial state. STATE_UNKNOWN, // When we are notified to process the first resource, we will start to // verify the manifest and go to this state no matter the package has // signature or not. STATE_MANIFEST_VERIFYING, // Either the package has no signature or the manifest is verified // successfully will we be in this state. STATE_MANIFEST_VERIFIED_OK, // iff the package has signature but the manifest is not well signed. STATE_MANIFEST_VERIFIED_FAILED, // The manifest is well signed but the resource integrity check failed. STATE_RESOURCE_VERIFIED_FAILED, }; // The only reason to inherit from nsISupports is it needs to be // passed as the context to PackagedAppVerifier::OnStopRequest. class ResourceCacheInfo : public nsISupports , public mozilla::LinkedListElement { public: NS_DECL_ISUPPORTS ResourceCacheInfo(nsIURI* aURI, nsICacheEntry* aCacheEntry, nsresult aStatusCode, bool aIsLastPart) : mURI(aURI) , mCacheEntry(aCacheEntry) , mStatusCode(aStatusCode) , mIsLastPart(aIsLastPart) { } ResourceCacheInfo(const ResourceCacheInfo& aCopyFrom) : mURI(aCopyFrom.mURI) , mCacheEntry(aCopyFrom.mCacheEntry) , mStatusCode(aCopyFrom.mStatusCode) , mIsLastPart(aCopyFrom.mIsLastPart) { } // A ResourceCacheInfo must have a URI. If mURI is null, this // resource is broken. nsCOMPtr mURI; nsCOMPtr mCacheEntry; nsresult mStatusCode; bool mIsLastPart; private: virtual ~ResourceCacheInfo() { } }; public: PackagedAppVerifier(); PackagedAppVerifier(nsIPackagedAppVerifierListener* aListener, const nsACString& aPackageOrigin, const nsACString& aSignature, nsICacheEntry* aPackageCacheEntry); // A internal used function to let the verifier know there's a broken // last part. void SetHasBrokenLastPart(nsresult aStatusCode); // Used to explicitly clear the listener to avoid circula reference. void ClearListener() { mListener = nullptr; } bool GetIsPackageSigned() const { return mIsPackageSigned; } const nsACString& GetPackageIdentifier() const { return mPackageIdentifer; } bool WouldVerify() const; static const char* kSignedPakIdMetadataKey; private: virtual ~PackagedAppVerifier(); // Called when a resource is already fully written in the cache. This resource // will be processed and is guaranteed to be called back in either: // // 1) PackagedAppVerifierListener::OnManifestVerified: // ------------------------------------------------------------------------ // If the resource is the first one in the package, it will be called // back in OnManifestVerified no matter this package has a signature or not. // // 2) PackagedAppVerifierListener::OnResourceVerified. // ------------------------------------------------------------------------ // Otherwise, the resource will be called back here. // void ProcessResourceCache(const ResourceCacheInfo* aInfo); // Callback for nsIInputStream::ReadSegment() to read manifest static NS_METHOD WriteManifest(nsIInputStream* aStream, void* aManifest, const char* aFromRawSegment, uint32_t aToOffset, uint32_t aCount, uint32_t* aWriteCount); // This two functions would call the actual verifier. void VerifyManifest(const ResourceCacheInfo* aInfo); void VerifyResource(const ResourceCacheInfo* aInfo); void OnManifestVerified(bool aSuccess); void OnResourceVerified(bool aSuccess); // To notify that either manifest or resource check is done. nsCOMPtr mListener; // The internal verification state. EState mState; // Initialized as a normal origin. Will be updated once we verified the manifest. nsCString mPackageOrigin; // The signature of the package. nsCString mSignature; // The app manfiest of the package nsCString mManifest; // Whether we're processing the first resource, which is the manfiest bool mIsFirstResource; // Whether this package app is signed. bool mIsPackageSigned; // Whether we should bypass verification. bool mBypassVerification; // The package cache entry (e.g. http://foo.com/app.pak) used to store // any necessarry signed package information. nsCOMPtr mPackageCacheEntry; // The resource URI that we are computing its hash. nsCString mHashingResourceURI; // Used to compute resource's hash value. nsCOMPtr mHasher; // The last computed hash value for a resource. It will be set on every // |EndResourceHash| call. nsCString mLastComputedResourceHash; // This will help to verify manifests and resource integrity nsCOMPtr mPackagedAppUtils; // A list of pending resource that is downloaded but not verified yet. mozilla::LinkedList mPendingResourceCacheInfoList; // A place to store the computed hashes of each resource. nsClassHashtable mResourceHashStore; nsCString mPackageIdentifer; }; // class PackagedAppVerifier } // namespace net } // namespace mozilla #endif // mozilla_net_PackagedAppVerifier_h