Bug 1844908 - Remove pre-Win10-specific codepath from security/manager/. r=keeler

Differential Revision: https://phabricator.services.mozilla.com/D184298
This commit is contained in:
Masatoshi Kimura 2023-07-25 14:41:03 +00:00
Родитель 12a9d6878f
Коммит c9bcb80226
3 изменённых файлов: 3 добавлений и 279 удалений

Просмотреть файл

@ -13924,17 +13924,6 @@
value: false
mirror: once
# On Windows 8.1, if the following preference is 2, we will attempt to detect
# whether the Family Safety TLS interception feature has been enabled.
# If so, we will behave as if the enterprise roots feature has been enabled
# (i.e. import and trust third party root certificates from the OS).
# With any other value of the pref or on any other platform, this does nothing.
# This preference takes precedence over "security.enterprise_roots.enabled".
- name: security.family_safety.mode
type: RelaxedAtomicUint32
value: 2
mirror: always
# Whether or not to import and trust third party root certificates from the OS.
- name: security.enterprise_roots.enabled
type: RelaxedAtomicBool

Просмотреть файл

@ -60,7 +60,6 @@
#include "nsIWindowWatcher.h"
#include "nsIXULRuntime.h"
#include "nsLiteralString.h"
#include "nsNSSCertificateDB.h"
#include "nsNSSHelper.h"
#include "nsNetCID.h"
#include "nsPK11TokenDB.h"
@ -84,14 +83,7 @@
#endif
#ifdef XP_WIN
# include "mozilla/WindowsVersion.h"
# include "nsILocalFileWin.h"
# include "windows.h" // this needs to be before the following includes
# include "lmcons.h"
# include "sddl.h"
# include "wincrypt.h"
# include "nsIWindowsRegKey.h"
#endif
using namespace mozilla;
@ -310,245 +302,6 @@ nsNSSComponent::~nsNSSComponent() {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor finished\n"));
}
#ifdef XP_WIN
static bool GetUserSid(nsAString& sidString) {
// UNLEN is the maximum user name length (see Lmcons.h). +1 for the null
// terminator.
WCHAR lpAccountName[UNLEN + 1];
DWORD lcAccountName = sizeof(lpAccountName) / sizeof(lpAccountName[0]);
BOOL success = GetUserName(lpAccountName, &lcAccountName);
if (!success) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("GetUserName failed"));
return false;
}
char sid_buffer[SECURITY_MAX_SID_SIZE];
SID* sid = BitwiseCast<SID*, char*>(sid_buffer);
DWORD cbSid = ArrayLength(sid_buffer);
SID_NAME_USE eUse;
// There doesn't appear to be a defined maximum length for the domain name
// here. To deal with this, we start with a reasonable buffer length and
// see if that works. If it fails and the error indicates insufficient length,
// we use the indicated required length and try again.
DWORD cchReferencedDomainName = 128;
auto ReferencedDomainName(MakeUnique<WCHAR[]>(cchReferencedDomainName));
success = LookupAccountName(nullptr, lpAccountName, sid, &cbSid,
ReferencedDomainName.get(),
&cchReferencedDomainName, &eUse);
if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("LookupAccountName failed"));
return false;
}
if (!success) {
ReferencedDomainName = MakeUnique<WCHAR[]>(cchReferencedDomainName);
success = LookupAccountName(nullptr, lpAccountName, sid, &cbSid,
ReferencedDomainName.get(),
&cchReferencedDomainName, &eUse);
}
if (!success) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("LookupAccountName failed"));
return false;
}
LPTSTR StringSid;
success = ConvertSidToStringSid(sid, &StringSid);
if (!success) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ConvertSidToStringSid failed"));
return false;
}
sidString.Assign(StringSid);
LocalFree(StringSid);
return true;
}
// This is a specialized helper function to read the value of a registry key
// that might not be present. If it is present, returns (via the output
// parameter) its value. Otherwise, returns the given default value.
// This function handles one level of nesting. That is, if the desired value
// is actually in a direct child of the given registry key (where the child
// and/or the value being sought may not actually be present), this function
// will handle that. In the normal case, though, optionalChildName will be
// null.
static nsresult ReadRegKeyValueWithDefault(nsCOMPtr<nsIWindowsRegKey> regKey,
uint32_t flags,
const wchar_t* optionalChildName,
const wchar_t* valueName,
uint32_t defaultValue,
uint32_t& valueOut) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ReadRegKeyValueWithDefault"));
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("attempting to read '%S%s%S' with default '%u'",
optionalChildName ? optionalChildName : L"",
optionalChildName ? "\\" : "", valueName, defaultValue));
if (optionalChildName) {
nsDependentString childNameString(optionalChildName);
bool hasChild;
nsresult rv = regKey->HasChild(childNameString, &hasChild);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("failed to determine if child key is present"));
return rv;
}
if (!hasChild) {
valueOut = defaultValue;
return NS_OK;
}
nsCOMPtr<nsIWindowsRegKey> childRegKey;
rv = regKey->OpenChild(childNameString, flags, getter_AddRefs(childRegKey));
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open child key"));
return rv;
}
return ReadRegKeyValueWithDefault(childRegKey, flags, nullptr, valueName,
defaultValue, valueOut);
}
nsDependentString valueNameString(valueName);
bool hasValue;
nsresult rv = regKey->HasValue(valueNameString, &hasValue);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("failed to determine if value is present"));
return rv;
}
if (!hasValue) {
valueOut = defaultValue;
return NS_OK;
}
rv = regKey->ReadIntValue(valueNameString, &valueOut);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to read value"));
return rv;
}
return NS_OK;
}
static nsresult AccountHasFamilySafetyEnabled(bool& enabled) {
enabled = false;
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("AccountHasFamilySafetyEnabled?"));
nsCOMPtr<nsIWindowsRegKey> parentalControlsKey(
do_CreateInstance("@mozilla.org/windows-registry-key;1"));
if (!parentalControlsKey) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't create nsIWindowsRegKey"));
return NS_ERROR_FAILURE;
}
uint32_t flags = nsIWindowsRegKey::ACCESS_READ | nsIWindowsRegKey::WOW64_64;
constexpr auto familySafetyPath =
u"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Parental Controls"_ns;
nsresult rv = parentalControlsKey->Open(
nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, familySafetyPath, flags);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open parentalControlsKey"));
return rv;
}
constexpr auto usersString = u"Users"_ns;
bool hasUsers;
rv = parentalControlsKey->HasChild(usersString, &hasUsers);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HasChild(Users) failed"));
return rv;
}
if (!hasUsers) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("Users subkey not present - Parental Controls not enabled"));
return NS_OK;
}
nsCOMPtr<nsIWindowsRegKey> usersKey;
rv = parentalControlsKey->OpenChild(usersString, flags,
getter_AddRefs(usersKey));
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to open Users subkey"));
return rv;
}
nsAutoString sid;
if (!GetUserSid(sid)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get sid"));
return NS_ERROR_FAILURE;
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("our sid is '%S'", static_cast<const wchar_t*>(sid.get())));
bool hasSid;
rv = usersKey->HasChild(sid, &hasSid);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HasChild(sid) failed"));
return rv;
}
if (!hasSid) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("sid not present in Family Safety Users"));
return NS_OK;
}
nsCOMPtr<nsIWindowsRegKey> sidKey;
rv = usersKey->OpenChild(sid, flags, getter_AddRefs(sidKey));
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open sid key"));
return rv;
}
// There are three keys we're interested in: "Parental Controls On",
// "Logging Required", and "Web\\Filter On". These keys will have value 0
// or 1, indicating a particular feature is disabled or enabled,
// respectively. So, if "Parental Controls On" is not 1, Family Safety is
// disabled and we don't care about anything else. If both "Logging
// Required" and "Web\\Filter On" are 0, the proxy will not be running,
// so for our purposes we can consider Family Safety disabled in that
// case.
// By default, "Logging Required" is 1 and "Web\\Filter On" is 0,
// reflecting the initial settings when Family Safety is enabled for an
// account for the first time, However, these sub-keys are not created
// unless they are switched away from the default value.
uint32_t parentalControlsOn;
rv = sidKey->ReadIntValue(u"Parental Controls On"_ns, &parentalControlsOn);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("couldn't read Parental Controls On"));
return rv;
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("Parental Controls On: %u", parentalControlsOn));
if (parentalControlsOn != 1) {
return NS_OK;
}
uint32_t loggingRequired;
rv = ReadRegKeyValueWithDefault(sidKey, flags, nullptr, L"Logging Required",
1, loggingRequired);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("failed to read value of Logging Required"));
return rv;
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("Logging Required: %u", loggingRequired));
uint32_t webFilterOn;
rv = ReadRegKeyValueWithDefault(sidKey, flags, L"Web", L"Filter On", 0,
webFilterOn);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("failed to read value of Web\\Filter On"));
return rv;
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Web\\Filter On: %u", webFilterOn));
enabled = loggingRequired == 1 || webFilterOn == 1;
return NS_OK;
}
#endif // XP_WIN
bool nsNSSComponent::ShouldEnableEnterpriseRootsForFamilySafety(
uint32_t familySafetyMode) {
#ifdef XP_WIN
if (!(IsWin8Point1OrLater() && !IsWin10OrLater())) {
return false;
}
if (familySafetyMode != 2) {
return false;
}
bool familySafetyEnabled;
nsresult rv = AccountHasFamilySafetyEnabled(familySafetyEnabled);
if (NS_FAILED(rv)) {
return false;
}
return familySafetyEnabled;
#else
return false;
#endif // XP_WIN
}
void nsNSSComponent::UnloadEnterpriseRoots() {
MOZ_ASSERT(NS_IsMainThread());
if (!NS_IsMainThread()) {
@ -591,12 +344,6 @@ void nsNSSComponent::MaybeImportEnterpriseRoots() {
return;
}
bool importEnterpriseRoots = StaticPrefs::security_enterprise_roots_enabled();
uint32_t familySafetyMode = StaticPrefs::security_family_safety_mode();
// If we've been configured to detect the Family Safety TLS interception
// feature, see if it's enabled. If so, we want to import enterprise roots.
if (ShouldEnableEnterpriseRootsForFamilySafety(familySafetyMode)) {
importEnterpriseRoots = true;
}
if (importEnterpriseRoots) {
RefPtr<BackgroundImportEnterpriseCertsTask> task =
new BackgroundImportEnterpriseCertsTask(this);
@ -685,13 +432,12 @@ nsNSSComponent::AddEnterpriseIntermediate(
class LoadLoadableCertsTask final : public Runnable {
public:
LoadLoadableCertsTask(nsNSSComponent* nssComponent,
bool importEnterpriseRoots, uint32_t familySafetyMode,
bool importEnterpriseRoots,
Vector<nsCString>&& possibleLoadableRootsLocations,
Maybe<nsCString>&& osClientCertsModuleLocation)
: Runnable("LoadLoadableCertsTask"),
mNSSComponent(nssComponent),
mImportEnterpriseRoots(importEnterpriseRoots),
mFamilySafetyMode(familySafetyMode),
mPossibleLoadableRootsLocations(
std::move(possibleLoadableRootsLocations)),
mOSClientCertsModuleLocation(std::move(osClientCertsModuleLocation)) {
@ -707,7 +453,6 @@ class LoadLoadableCertsTask final : public Runnable {
nsresult LoadLoadableRoots();
RefPtr<nsNSSComponent> mNSSComponent;
bool mImportEnterpriseRoots;
uint32_t mFamilySafetyMode;
Vector<nsCString> mPossibleLoadableRootsLocations; // encoded in UTF-8
Maybe<nsCString> mOSClientCertsModuleLocation; // encoded in UTF-8
};
@ -748,12 +493,6 @@ LoadLoadableCertsTask::Run() {
}
}
// If we've been configured to detect the Family Safety TLS interception
// feature, see if it's enabled. If so, we want to import enterprise roots.
if (mNSSComponent->ShouldEnableEnterpriseRootsForFamilySafety(
mFamilySafetyMode)) {
mImportEnterpriseRoots = true;
}
if (mImportEnterpriseRoots) {
mNSSComponent->ImportEnterpriseRoots();
mNSSComponent->UpdateCertVerifierWithEnterpriseRoots();
@ -1899,7 +1638,6 @@ nsresult nsNSSComponent::InitializeNSS() {
bool importEnterpriseRoots =
StaticPrefs::security_enterprise_roots_enabled();
uint32_t familySafetyMode = StaticPrefs::security_family_safety_mode();
Vector<nsCString> possibleLoadableRootsLocations;
rv = ListPossibleLoadableRootsLocations(possibleLoadableRootsLocations);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
@ -1917,7 +1655,7 @@ nsresult nsNSSComponent::InitializeNSS() {
}
}
RefPtr<LoadLoadableCertsTask> loadLoadableCertsTask(
new LoadLoadableCertsTask(this, importEnterpriseRoots, familySafetyMode,
new LoadLoadableCertsTask(this, importEnterpriseRoots,
std::move(possibleLoadableRootsLocations),
std::move(maybeOSClientCertsModuleLocation)));
rv = loadLoadableCertsTask->Dispatch();
@ -2229,8 +1967,7 @@ nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
Preferences::GetCString("security.test.built_in_root_hash",
mTestBuiltInRootHash);
#endif // DEBUG
} else if (prefName.Equals("security.enterprise_roots.enabled") ||
prefName.Equals("security.family_safety.mode")) {
} else if (prefName.Equals("security.enterprise_roots.enabled")) {
UnloadEnterpriseRoots();
MaybeImportEnterpriseRoots();
} else if (prefName.Equals("security.osclientcerts.autoload")) {

Просмотреть файл

@ -110,8 +110,6 @@ class nsNSSComponent final : public nsINSSComponent, public nsIObserver {
nsresult CommonGetEnterpriseCerts(
nsTArray<nsTArray<uint8_t>>& enterpriseCerts, bool getRoots);
bool ShouldEnableEnterpriseRootsForFamilySafety(uint32_t familySafetyMode);
nsresult MaybeEnableIntermediatePreloadingHealer();
// mLoadableCertsLoadedMonitor protects mLoadableCertsLoaded.