nsresult CompareNetwork::Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, nsILoadGroup* aLoadGroup) { MOZ_ASSERT(aPrincipal); AssertIsOnMainThread(); nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, nullptr); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsILoadGroup> loadGroup; rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), aPrincipal); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsLoadFlags flags = nsIChannel::LOAD_BYPASS_SERVICE_WORKER; RefPtr<ServiceWorkerRegistrationInfo> registration = mManager->GetRegistration(); if (registration->IsLastUpdateCheckTimeOverOneDay()) { flags |= nsIRequest::LOAD_BYPASS_CACHE; } // Note that because there is no "serviceworker" RequestContext type, we can // use the TYPE_INTERNAL_SCRIPT content policy types when loading a service // worker. rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED, nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER, loadGroup, nullptr, // aCallbacks flags); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel); if (httpChannel) { // Spec says no redirects allowed for SW scripts. httpChannel->SetRedirectionLimit(0); httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Service-Worker"), NS_LITERAL_CSTRING("script"), /* merge */ false); } nsCOMPtr<nsIStreamLoader> loader; rv = NS_NewStreamLoader(getter_AddRefs(loader), this, this); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } rv = mChannel->AsyncOpen2(loader); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_OK; }
nsresult PendingLookup::SendRemoteQueryInternal() { // If we aren't supposed to do remote lookups, bail. if (!Preferences::GetBool(PREF_SB_DOWNLOADS_REMOTE_ENABLED, false)) { LOG(("Remote lookups are disabled [this = %p]", this)); return NS_ERROR_NOT_AVAILABLE; } // If the remote lookup URL is empty or absent, bail. nsCString serviceUrl; NS_ENSURE_SUCCESS(Preferences::GetCString(PREF_SB_APP_REP_URL, &serviceUrl), NS_ERROR_NOT_AVAILABLE); if (serviceUrl.IsEmpty()) { LOG(("Remote lookup URL is empty [this = %p]", this)); return NS_ERROR_NOT_AVAILABLE; } // If the blocklist or allowlist is empty (so we couldn't do local lookups), // bail { nsAutoCString table; NS_ENSURE_SUCCESS(Preferences::GetCString(PREF_DOWNLOAD_BLOCK_TABLE, &table), NS_ERROR_NOT_AVAILABLE); if (table.IsEmpty()) { LOG(("Blocklist is empty [this = %p]", this)); return NS_ERROR_NOT_AVAILABLE; } } #ifdef XP_WIN // The allowlist is only needed to do signature verification on Windows { nsAutoCString table; NS_ENSURE_SUCCESS(Preferences::GetCString(PREF_DOWNLOAD_ALLOW_TABLE, &table), NS_ERROR_NOT_AVAILABLE); if (table.IsEmpty()) { LOG(("Allowlist is empty [this = %p]", this)); return NS_ERROR_NOT_AVAILABLE; } } #endif LOG(("Sending remote query for application reputation [this = %p]", this)); // We did not find a local result, so fire off the query to the // application reputation service. nsCOMPtr<nsIURI> uri; nsresult rv; rv = mQuery->GetSourceURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); nsCString spec; rv = GetStrippedSpec(uri, spec); NS_ENSURE_SUCCESS(rv, rv); mRequest.set_url(spec.get()); uint32_t fileSize; rv = mQuery->GetFileSize(&fileSize); NS_ENSURE_SUCCESS(rv, rv); mRequest.set_length(fileSize); // We have no way of knowing whether or not a user initiated the // download. Set it to true to lessen the chance of false positives. mRequest.set_user_initiated(true); nsCString locale; NS_ENSURE_SUCCESS(Preferences::GetCString(PREF_GENERAL_LOCALE, &locale), NS_ERROR_NOT_AVAILABLE); mRequest.set_locale(locale.get()); nsCString sha256Hash; rv = mQuery->GetSha256Hash(sha256Hash); NS_ENSURE_SUCCESS(rv, rv); mRequest.mutable_digests()->set_sha256(sha256Hash.Data()); nsString fileName; rv = mQuery->GetSuggestedFileName(fileName); NS_ENSURE_SUCCESS(rv, rv); mRequest.set_file_basename(NS_ConvertUTF16toUTF8(fileName).get()); mRequest.set_download_type(GetDownloadType(fileName)); if (mRequest.signature().trusted()) { LOG(("Got signed binary for remote application reputation check " "[this = %p]", this)); } else { LOG(("Got unsigned binary for remote application reputation check " "[this = %p]", this)); } // Serialize the protocol buffer to a string. This can only fail if we are // out of memory, or if the protocol buffer req is missing required fields // (only the URL for now). std::string serialized; if (!mRequest.SerializeToString(&serialized)) { return NS_ERROR_UNEXPECTED; } LOG(("Serialized protocol buffer [this = %p]: (length=%d) %s", this, serialized.length(), serialized.c_str())); // Set the input stream to the serialized protocol buffer nsCOMPtr<nsIStringInputStream> sstream = do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv); NS_ENSURE_SUCCESS(rv, rv); rv = sstream->SetData(serialized.c_str(), serialized.length()); NS_ENSURE_SUCCESS(rv, rv); // Set up the channel to transmit the request to the service. nsCOMPtr<nsIIOService> ios = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); rv = ios->NewChannel2(serviceUrl, nullptr, nullptr, nullptr, // aLoadingNode nsContentUtils::GetSystemPrincipal(), nullptr, // aTriggeringPrincipal nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nsIContentPolicy::TYPE_OTHER, getter_AddRefs(mChannel)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo(); if (loadInfo) { loadInfo->SetOriginAttributes( mozilla::NeckoOriginAttributes(NECKO_SAFEBROWSING_APP_ID, false)); } nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel, &rv)); NS_ENSURE_SUCCESS(rv, rv); mozilla::Unused << httpChannel; // Upload the protobuf to the application reputation service. nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(mChannel, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = uploadChannel->ExplicitSetUploadStream(sstream, NS_LITERAL_CSTRING("application/octet-stream"), serialized.size(), NS_LITERAL_CSTRING("POST"), false); NS_ENSURE_SUCCESS(rv, rv); // Set the Safebrowsing cookie jar, so that the regular Google cookie is not // sent with this request. See bug 897516. DocShellOriginAttributes attrs; attrs.mAppId = NECKO_SAFEBROWSING_APP_ID; nsCOMPtr<nsIInterfaceRequestor> loadContext = new mozilla::LoadContext(attrs); rv = mChannel->SetNotificationCallbacks(loadContext); NS_ENSURE_SUCCESS(rv, rv); uint32_t timeoutMs = Preferences::GetUint(PREF_SB_DOWNLOADS_REMOTE_TIMEOUT, 10000); mTimeoutTimer = do_CreateInstance(NS_TIMER_CONTRACTID); mTimeoutTimer->InitWithCallback(this, timeoutMs, nsITimer::TYPE_ONE_SHOT); rv = mChannel->AsyncOpen2(this); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }