зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1178518 - Verify signed packages. r=valentin
This commit is contained in:
Родитель
ae5a452f5b
Коммит
077ea1aeb2
|
@ -225,15 +225,12 @@ CreateSharedStringStream(const char* aData, uint32_t aCount)
|
|||
static bool
|
||||
GetOriginalResponseHeader(nsIRequest* aRequest, nsACString& aHeader)
|
||||
{
|
||||
// TODO: The flattened http header might be different from the original.
|
||||
// See Bug 1198669 for further information.
|
||||
nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
|
||||
if (!multiPartChannel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIResponseHeadProvider> headerProvider(do_QueryInterface(aRequest));
|
||||
nsHttpResponseHead *responseHead = headerProvider->GetResponseHead();
|
||||
NS_ENSURE_TRUE(responseHead, false);
|
||||
|
||||
responseHead->Flatten(aHeader, true);
|
||||
aHeader.Append("\r\n");
|
||||
multiPartChannel->GetOriginalResponseHeader(aHeader);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "nsITimer.h"
|
||||
#include "nsIPackagedAppVerifier.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIPackagedAppUtils.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
static const short kResourceHashType = nsICryptoHash::SHA256;
|
||||
|
||||
|
@ -26,7 +28,7 @@ namespace net {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS(PackagedAppVerifier, nsIPackagedAppVerifier)
|
||||
NS_IMPL_ISUPPORTS(PackagedAppVerifier, nsIPackagedAppVerifier, nsIVerificationCallback)
|
||||
|
||||
NS_IMPL_ISUPPORTS(PackagedAppVerifier::ResourceCacheInfo, nsISupports)
|
||||
|
||||
|
@ -76,6 +78,14 @@ NS_IMETHODIMP PackagedAppVerifier::Init(nsIPackagedAppVerifierListener* aListene
|
|||
mSignature = aSignature;
|
||||
mIsPackageSigned = false;
|
||||
mPackageCacheEntry = aPackageCacheEntry;
|
||||
mIsFirstResource = true;
|
||||
|
||||
nsresult rv;
|
||||
mPackagedAppUtils = do_CreateInstance(NS_PACKAGEDAPPUTILS_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("create packaged app utils failed"));
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -90,6 +100,11 @@ NS_IMETHODIMP
|
|||
PackagedAppVerifier::OnStartRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
if (mIsFirstResource) {
|
||||
// The first resource must be the manifest, hashes not needed
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mHasher) {
|
||||
mHasher = do_CreateInstance("@mozilla.org/security/hash;1");
|
||||
}
|
||||
|
@ -103,6 +118,22 @@ PackagedAppVerifier::OnStartRequest(nsIRequest *aRequest,
|
|||
return mHasher->Init(kResourceHashType);
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
PackagedAppVerifier::WriteManifest(nsIInputStream* aStream,
|
||||
void* aManifest,
|
||||
const char* aFromRawSegment,
|
||||
uint32_t aToOffset,
|
||||
uint32_t aCount,
|
||||
uint32_t* aWriteCount)
|
||||
{
|
||||
LOG(("WriteManifest: length %u", aCount));
|
||||
LOG(("%s", aFromRawSegment));
|
||||
nsCString* manifest = static_cast<nsCString*>(aManifest);
|
||||
manifest->AppendASCII(aFromRawSegment, aCount);
|
||||
*aWriteCount = aCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// @param aRequest nullptr.
|
||||
// @param aContext nullptr.
|
||||
// @param aInputStream as-is.
|
||||
|
@ -115,6 +146,16 @@ PackagedAppVerifier::OnDataAvailable(nsIRequest *aRequest,
|
|||
uint64_t aOffset,
|
||||
uint32_t aCount)
|
||||
{
|
||||
if (mIsFirstResource) {
|
||||
// The first resource must be the manifest, hash value not needed.
|
||||
// Instead, we read from the input stream and append to mManifest.
|
||||
uint32_t count;
|
||||
LOG(("ReadSegments: size = %u", aCount));
|
||||
nsresult rv = aInputStream->ReadSegments(WriteManifest, &mManifest, aCount, &count);
|
||||
MOZ_ASSERT(count == aCount, "Bytes read by ReadSegments don't match");
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mHashingResourceURI.IsEmpty(), "MUST call BeginResourceHash first.");
|
||||
NS_ENSURE_TRUE(mHasher, NS_ERROR_FAILURE);
|
||||
return mHasher->UpdateFromStream(aInputStream, aCount);
|
||||
|
@ -130,17 +171,22 @@ PackagedAppVerifier::OnStopRequest(nsIRequest* aRequest,
|
|||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "mHashingResourceURI is not thread safe.");
|
||||
|
||||
NS_ENSURE_TRUE(mHasher, NS_ERROR_FAILURE);
|
||||
if (mIsFirstResource) {
|
||||
// The first resource must be the manifest, hash value not needed
|
||||
mIsFirstResource = false;
|
||||
} else {
|
||||
NS_ENSURE_TRUE(mHasher, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoCString hash;
|
||||
nsresult rv = mHasher->Finish(true, hash);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString hash;
|
||||
nsresult rv = mHasher->Finish(true, hash);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOG(("Hash of %s is %s", mHashingResourceURI.get(), hash.get()));
|
||||
LOG(("Hash of %s is %s", mHashingResourceURI.get(), hash.get()));
|
||||
|
||||
// Store the computated hash associated with the resource URI.
|
||||
mResourceHashStore.Put(mHashingResourceURI, new nsCString(hash));
|
||||
mHashingResourceURI = EmptyCString();
|
||||
// Store the computated hash associated with the resource URI.
|
||||
mResourceHashStore.Put(mHashingResourceURI, new nsCString(hash));
|
||||
mHashingResourceURI = EmptyCString();
|
||||
}
|
||||
|
||||
// Get a internal copy and take over the life cycle handling
|
||||
// since the linked list we use only supports pointer-based element.
|
||||
|
@ -186,9 +232,10 @@ PackagedAppVerifier::ProcessResourceCache(const ResourceCacheInfo* aInfo)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP
|
||||
PackagedAppVerifier::FireVerifiedEvent(bool aForManifest, bool aSuccess)
|
||||
{
|
||||
LOG(("FireVerifiedEvent aForManifest=%d aSuccess=%d", aForManifest, aSuccess));
|
||||
nsCOMPtr<nsIRunnable> r;
|
||||
|
||||
if (aForManifest) {
|
||||
|
@ -202,6 +249,8 @@ PackagedAppVerifier::FireVerifiedEvent(bool aForManifest, bool aSuccess)
|
|||
}
|
||||
|
||||
NS_DispatchToMainThread(r);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -231,9 +280,12 @@ PackagedAppVerifier::VerifyManifest(const ResourceCacheInfo* aInfo)
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Implement manifest verification.
|
||||
LOG(("Manifest verification not implemented yet. See Bug 1178518."));
|
||||
FireVerifiedEvent(true, false);
|
||||
LOG(("Signature: length = %u\n%s", mSignature.Length(), mSignature.get()));
|
||||
LOG(("Manifest: length = %u\n%s", mManifest.Length(), mManifest.get()));
|
||||
nsresult rv = mPackagedAppUtils->VerifyManifest(mSignature, mManifest, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("VerifyManifest FAILED rv = %u", (unsigned)rv));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -269,9 +321,20 @@ PackagedAppVerifier::VerifyResource(const ResourceCacheInfo* aInfo)
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Implement resource integrity check.
|
||||
LOG(("Resource integrity check not implemented yet. See Bug 1178518."));
|
||||
FireVerifiedEvent(false, false);
|
||||
nsAutoCString path;
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(aInfo->mURI));
|
||||
if (url) {
|
||||
url->GetFilePath(path);
|
||||
}
|
||||
int32_t pos = path.Find("!//");
|
||||
if (pos == kNotFound) {
|
||||
FireVerifiedEvent(false, false);
|
||||
return;
|
||||
}
|
||||
// Only keep the part after "!//"
|
||||
path.Cut(0, pos + 3);
|
||||
|
||||
mPackagedAppUtils->CheckIntegrity(path, *resourceHash, this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -14,18 +14,21 @@
|
|||
#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 {
|
||||
|
@ -120,6 +123,14 @@ private:
|
|||
//
|
||||
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);
|
||||
|
@ -127,9 +138,6 @@ private:
|
|||
void OnManifestVerified(bool aSuccess);
|
||||
void OnResourceVerified(bool aSuccess);
|
||||
|
||||
// Fire a async event to notify the verification result.
|
||||
void FireVerifiedEvent(bool aForManifest, bool aSuccess);
|
||||
|
||||
// To notify that either manifest or resource check is done.
|
||||
nsCOMPtr<nsIPackagedAppVerifierListener> mListener;
|
||||
|
||||
|
@ -142,6 +150,12 @@ private:
|
|||
// 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;
|
||||
|
||||
|
@ -159,6 +173,9 @@ private:
|
|||
// |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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче