fune/browser/components/attribution/nsMacAttribution.cpp
Nick Alexander 4c713eeeaf Bug 1525076 - Part 1: Fix macOS native getReferrerUrl by invoking system sqlite binary (from JS). r=mixedpuppy
The issue this is addresses is that
[`CFURLCopyResourcePropertyForKey`](https://searchfox.org/mozilla-central/rev/ea7f70dac1c5fd18400f6d2a92679777d4b21492/xpcom/io/CocoaFileUtils.mm#212)
does not return quarantine data when launched as a GUI App.  What
happens is that launching via the GUI requires the user to override
GateKeeper by going to Security & Privacy > Open Anyway.  Doing that
updates the GateKeeper flags, and then the macOS API denies access:
once the GK flags reach some state, quarantine information is not
returned.  This is not documented (as far as I can see) but moons ago,
[somebody else on the internet witnessed the same
thing](https://cocoa-dev.apple.narkive.com/kkYeAC8o/is-it-possible-to-read-your-own-quarantine-info-after-launch).

To work around, we run the system SQLite binary, to fish the relevant
information out of the per-user quarantine database.  (SQLite is
installed by default on all relevant macOS versions.)

The most significant security concern I see is whether we can trust
this binary (in /usr/bin/sqlite3). Some discussion within the
Install/Update team suggested that an attacker who could corrupt or
modify that binary already had write access to the disk, which is an
attack vector equal to a totally compromised Firefox. If we determine
that we can't use the system SQLite binary, then we could use
Firefox's compiled copy of SQLite, but we might see versioning
issues. The system SQLite binary feels more robust.

This is implemented as a JS component for convenience, mostly: there
is no API for capturing output from `nsIProcess`.  It would be
possible to maintain the existing XPCOM contract by renaming the
existing contract and adding a contract with a JS implementation that
passes through to the renamed implementation, but it doesn't seem
worth the effort.

In the next commits, we will generalize the existing caching mechanism
form Windows to also apply to macOS. This is mostly a performance
optimization, so that we sniff a single well-known location rather
than launching a process at each startup, although there is a
correctness argument here as well, since the quarantine database is
dynamic and the attribution URL could expire.

Differential Revision: https://phabricator.services.mozilla.com/D92693
2020-10-11 18:18:36 +00:00

51 lines
1.7 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsMacAttribution.h"
#include <CoreFoundation/CoreFoundation.h>
#include <ApplicationServices/ApplicationServices.h>
#include "../../../xpcom/io/CocoaFileUtils.h"
#include "nsCocoaFeatures.h"
#include "nsString.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS(nsMacAttributionService, nsIMacAttributionService)
NS_IMETHODIMP
nsMacAttributionService::SetReferrerUrl(const nsACString& aFilePath,
const nsACString& aReferrerUrl,
const bool aCreate) {
const nsCString& flat = PromiseFlatCString(aFilePath);
CFStringRef filePath = ::CFStringCreateWithCString(
kCFAllocatorDefault, flat.get(), kCFStringEncodingUTF8);
if (!filePath) {
return NS_ERROR_UNEXPECTED;
}
const nsCString& flatReferrer = PromiseFlatCString(aReferrerUrl);
CFStringRef referrer = ::CFStringCreateWithCString(
kCFAllocatorDefault, flatReferrer.get(), kCFStringEncodingUTF8);
if (!referrer) {
::CFRelease(filePath);
return NS_ERROR_UNEXPECTED;
}
CFURLRef referrerURL =
::CFURLCreateWithString(kCFAllocatorDefault, referrer, nullptr);
CocoaFileUtils::AddQuarantineMetadataToFile(filePath, NULL, referrerURL, true,
aCreate);
::CFRelease(filePath);
::CFRelease(referrer);
if (referrerURL) {
::CFRelease(referrerURL);
}
return NS_OK;
}