gecko-dev/netwerk/protocol/http/PackagedAppVerifier.h

207 lines
6.4 KiB
C
Raw Normal View History

/* -*- 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<ResourceCacheInfo>
{
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<nsIURI> mURI;
nsCOMPtr<nsICacheEntry> 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<nsIPackagedAppVerifierListener> 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<nsICacheEntry> mPackageCacheEntry;
// The resource URI that we are computing its hash.
nsCString mHashingResourceURI;
// Used to compute resource's hash value.
nsCOMPtr<nsICryptoHash> 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<nsIPackagedAppUtils> mPackagedAppUtils;
// A list of pending resource that is downloaded but not verified yet.
mozilla::LinkedList<ResourceCacheInfo> mPendingResourceCacheInfoList;
// A place to store the computed hashes of each resource.
nsClassHashtable<nsCStringHashKey, nsCString> mResourceHashStore;
nsCString mPackageIdentifer;
}; // class PackagedAppVerifier
} // namespace net
} // namespace mozilla
#endif // mozilla_net_PackagedAppVerifier_h