--- a/toolkit/components/downloads/ApplicationReputation.cpp
+++ b/toolkit/components/downloads/ApplicationReputation.cpp
@@ -160,24 +160,26 @@ private:
// Returns true if the file is likely to be binary.
bool IsBinaryFile();
// Returns the type of download binary for the file.
ClientDownloadRequest::DownloadType GetDownloadType(const nsAString& aFilename);
// Clean up and call the callback. PendingLookup must not be used after this
// function is called.
- nsresult OnComplete(bool shouldBlock, nsresult rv);
+ nsresult OnComplete(bool shouldBlock, nsresult rv,
+ uint32_t verdict = nsIApplicationReputationService::VERDICT_NONE);
// Wrapper function for nsIStreamListener.onStopRequest to make it easy to
// guarantee calling the callback
nsresult OnStopRequestInternal(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aResult,
- bool* aShouldBlock);
+ bool* aShouldBlock,
+ uint32_t* aVerdict);
// Strip url parameters, fragments, and user@pass fields from the URI spec
// using nsIURL. If aURI is not an nsIURL, returns the original nsIURI.spec.
nsresult GetStrippedSpec(nsIURI* aUri, nsACString& spec);
// Escape '/' and '%' in certificate attribute values.
nsCString EscapeCertificateAttribute(const nsACString& aAttribute);
@@ -339,17 +341,18 @@ PendingDBLookup::HandleEvent(const nsACS
// 2) PendingLookup::LookupNext if the URL does not match the blocklist.
// Blocklisting trumps allowlisting.
nsAutoCString blockList;
Preferences::GetCString(PREF_DOWNLOAD_BLOCK_TABLE, &blockList);
if (!mAllowlistOnly && FindInReadable(blockList, tables)) {
mPendingLookup->mBlocklistCount++;
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_LOCAL, BLOCK_LIST);
LOG(("Found principal %s on blocklist [this = %p]", mSpec.get(), this));
- return mPendingLookup->OnComplete(true, NS_OK);
+ return mPendingLookup->OnComplete(true, NS_OK,
+ nsIApplicationReputationService::VERDICT_MALWARE);
}
nsAutoCString allowList;
Preferences::GetCString(PREF_DOWNLOAD_ALLOW_TABLE, &allowList);
if (FindInReadable(allowList, tables)) {
mPendingLookup->mAllowlistCount++;
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_LOCAL, ALLOW_LIST);
LOG(("Found principal %s on allowlist [this = %p]", mSpec.get(), this));
@@ -442,30 +445,32 @@ PendingLookup::GetDownloadType(const nsA
nsresult
PendingLookup::LookupNext()
{
// We must call LookupNext or SendRemoteQuery upon return.
// Look up all of the URLs that could allow or block this download.
// Blocklist first.
if (mBlocklistCount > 0) {
- return OnComplete(true, NS_OK);
+ return OnComplete(true, NS_OK,
+ nsIApplicationReputationService::VERDICT_MALWARE);
}
int index = mAnylistSpecs.Length() - 1;
nsCString spec;
if (index >= 0) {
// Check the source URI, referrer and redirect chain.
spec = mAnylistSpecs[index];
mAnylistSpecs.RemoveElementAt(index);
RefPtr<PendingDBLookup> lookup(new PendingDBLookup(this));
return lookup->LookupSpec(spec, false);
}
// If any of mAnylistSpecs matched the blocklist, go ahead and block.
if (mBlocklistCount > 0) {
- return OnComplete(true, NS_OK);
+ return OnComplete(true, NS_OK,
+ nsIApplicationReputationService::VERDICT_MALWARE);
}
// If any of mAnylistSpecs matched the allowlist, go ahead and pass.
if (mAllowlistCount > 0) {
return OnComplete(false, NS_OK);
}
// Only binary signatures remain.
index = mAllowlistSpecs.Length() - 1;
if (index >= 0) {
@@ -754,17 +759,17 @@ PendingLookup::DoLookupInternal()
rv = GenerateWhitelistStrings();
NS_ENSURE_SUCCESS(rv, rv);
// Start the call chain.
return LookupNext();
}
nsresult
-PendingLookup::OnComplete(bool shouldBlock, nsresult rv)
+PendingLookup::OnComplete(bool shouldBlock, nsresult rv, uint32_t verdict)
{
if (NS_FAILED(rv)) {
nsAutoCString errorName;
mozilla::GetErrorName(rv, errorName);
LOG(("Failed sending remote query for application reputation "
"[rv = %s, this = %p]", errorName.get(), this));
}
@@ -777,17 +782,17 @@ PendingLookup::OnComplete(bool shouldBlo
shouldBlock);
double t = (TimeStamp::Now() - mStartTime).ToMilliseconds();
if (shouldBlock) {
LOG(("Application Reputation check failed, blocking bad binary in %f ms "
"[this = %p]", t, this));
} else {
LOG(("Application Reputation check passed in %f ms [this = %p]", t, this));
}
- nsresult res = mCallback->OnComplete(shouldBlock, rv);
+ nsresult res = mCallback->OnComplete(shouldBlock, rv, verdict);
return res;
}
nsresult
PendingLookup::ParseCertificates(nsIArray* aSigArray)
{
// If we haven't been set for any reason, bail.
NS_ENSURE_ARG_POINTER(aSigArray);
@@ -1050,34 +1055,37 @@ PendingLookup::OnStartRequest(nsIRequest
NS_IMETHODIMP
PendingLookup::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aResult) {
NS_ENSURE_STATE(mCallback);
bool shouldBlock = false;
+ uint32_t verdict = nsIApplicationReputationService::VERDICT_NONE;
nsresult rv = OnStopRequestInternal(aRequest, aContext, aResult,
- &shouldBlock);
- OnComplete(shouldBlock, rv);
+ &shouldBlock, &verdict);
+ OnComplete(shouldBlock, rv, verdict);
return rv;
}
nsresult
PendingLookup::OnStopRequestInternal(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aResult,
- bool* aShouldBlock) {
+ bool* aShouldBlock,
+ uint32_t* aVerdict) {
if (NS_FAILED(aResult)) {
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
SERVER_RESPONSE_FAILED);
return aResult;
}
*aShouldBlock = false;
+ *aVerdict = nsIApplicationReputationService::VERDICT_NONE;
nsresult rv;
nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aRequest, &rv);
if (NS_FAILED(rv)) {
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
SERVER_RESPONSE_FAILED);
return rv;
}
@@ -1107,31 +1115,39 @@ PendingLookup::OnStopRequestInternal(nsI
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER,
SERVER_RESPONSE_VALID);
// Clamp responses 0-7, we only know about 0-4 for now.
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER_VERDICT,
std::min<uint32_t>(response.verdict(), 7));
switch(response.verdict()) {
case safe_browsing::ClientDownloadResponse::DANGEROUS:
*aShouldBlock = Preferences::GetBool(PREF_BLOCK_DANGEROUS, true);
+ *aVerdict = nsIApplicationReputationService::VERDICT_MALWARE;
break;
case safe_browsing::ClientDownloadResponse::DANGEROUS_HOST:
*aShouldBlock = Preferences::GetBool(PREF_BLOCK_DANGEROUS_HOST, true);
+ *aVerdict = nsIApplicationReputationService::VERDICT_MALWARE;
break;
case safe_browsing::ClientDownloadResponse::POTENTIALLY_UNWANTED:
*aShouldBlock = Preferences::GetBool(PREF_BLOCK_POTENTIALLY_UNWANTED, false);
+ *aVerdict = nsIApplicationReputationService::VERDICT_POTENTIALLY_UNWANTED;
break;
case safe_browsing::ClientDownloadResponse::UNCOMMON:
*aShouldBlock = Preferences::GetBool(PREF_BLOCK_UNCOMMON, false);
+ *aVerdict = nsIApplicationReputationService::VERDICT_UNCOMMON;
break;
default:
// Treat everything else as safe
break;
}
+ if (!*aShouldBlock) {
+ *aVerdict = nsIApplicationReputationService::VERDICT_NONE;
+ }
+
return NS_OK;
}
NS_IMPL_ISUPPORTS(ApplicationReputationService,
nsIApplicationReputationService)
ApplicationReputationService*
ApplicationReputationService::gApplicationReputationService = nullptr;
@@ -1170,17 +1186,18 @@ ApplicationReputationService::QueryReput
NS_ENSURE_ARG_POINTER(aQuery);
NS_ENSURE_ARG_POINTER(aCallback);
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_COUNT, true);
nsresult rv = QueryReputationInternal(aQuery, aCallback);
if (NS_FAILED(rv)) {
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SHOULD_BLOCK,
false);
- aCallback->OnComplete(false, rv);
+ aCallback->OnComplete(false, rv,
+ nsIApplicationReputationService::VERDICT_NONE);
}
return NS_OK;
}
nsresult ApplicationReputationService::QueryReputationInternal(
nsIApplicationReputationQuery* aQuery,
nsIApplicationReputationCallback* aCallback) {
nsresult rv;