[Enterprise Signals] Get Mac Firewall Setting from socketfilterfw on MacOS 15+ only
The previous method is no longer supported on the upcoming new Sequoia OS, but we still need them to keep supporting older versions of MacOS.
This is a reland of crrev.com/c/5839553 and crrev.com/c/5845392, but limited the change to be MacOS v15+ only.
Fixed: 362191723
Change-Id: Ifc7e3f86f04bf2ae3da17c9460d95cbf42740e34
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5916765
Reviewed-by: Dominique Fauteux-Chapleau <domfc@chromium.org>
Commit-Queue: Zonghan Xu <xzonghan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1365773}
diff --git a/chrome/browser/enterprise/signals/context_info_fetcher.cc b/chrome/browser/enterprise/signals/context_info_fetcher.cc
index dc58a6ad..0f0d89fd 100644
--- a/chrome/browser/enterprise/signals/context_info_fetcher.cc
+++ b/chrome/browser/enterprise/signals/context_info_fetcher.cc
@@ -42,6 +42,9 @@
#if BUILDFLAG(IS_MAC)
#include <CoreFoundation/CoreFoundation.h>
+
+#include "base/mac/mac_util.h"
+#include "base/process/launch.h"
#endif
#if BUILDFLAG(IS_WIN)
@@ -137,34 +140,63 @@
#if BUILDFLAG(IS_MAC)
SettingValue GetMacOSFirewall() {
- // There is no official Apple documentation on how to obtain the enabled
- // status of the firewall (System Preferences> Security & Privacy> Firewall).
- // Reading globalstate from com.apple.alf is the closest way to get such an
- // API in Chrome without delegating to potentially unstable commands.
- // Values of "globalstate":
- // 0 = de-activated
- // 1 = on for specific services
- // 2 = on for essential services
- // You can get 2 by, e.g., enabling the "Block all incoming connections"
- // firewall functionality.
+ if (base::mac::MacOSMajorVersion() < 15) {
+ // There is no official Apple documentation on how to obtain the enabled
+ // status of the firewall (System Preferences> Security & Privacy> Firewall)
+ // prior to MacOS versions 15. Reading globalstate from com.apple.alf is the
+ // closest way to get such an API in Chrome without delegating to
+ // potentially unstable commands. Values of "globalstate":
+ // 0 = de-activated
+ // 1 = on for specific services
+ // 2 = on for essential services
+ // You can get 2 by, e.g., enabling the "Block all incoming connections"
+ // firewall functionality.
+ Boolean key_exists_with_valid_format = false;
+ CFIndex globalstate = CFPreferencesGetAppIntegerValue(
+ CFSTR("globalstate"), CFSTR("com.apple.alf"),
+ &key_exists_with_valid_format);
- Boolean key_exists_with_valid_format = false;
- CFIndex globalstate = CFPreferencesGetAppIntegerValue(
- CFSTR("globalstate"), CFSTR("com.apple.alf"),
- &key_exists_with_valid_format);
-
- if (!key_exists_with_valid_format)
- return SettingValue::UNKNOWN;
-
- switch (globalstate) {
- case 0:
- return SettingValue::DISABLED;
- case 1:
- case 2:
- return SettingValue::ENABLED;
- default:
+ if (!key_exists_with_valid_format) {
return SettingValue::UNKNOWN;
+ }
+
+ switch (globalstate) {
+ case 0:
+ return SettingValue::DISABLED;
+ case 1:
+ case 2:
+ return SettingValue::ENABLED;
+ default:
+ return SettingValue::UNKNOWN;
+ }
}
+
+ // Based on this recommendation from Apple:
+ // https://developer.apple.com/documentation/macos-release-notes/macos-15-release-notes/#Application-Firewall
+ base::FilePath fw_util("/usr/libexec/ApplicationFirewall/socketfilterfw");
+ if (!base::PathExists(fw_util)) {
+ return SettingValue::UNKNOWN;
+ }
+
+ base::CommandLine command(fw_util);
+ command.AppendSwitch("getglobalstate");
+ std::string output;
+ if (!base::GetAppOutput(command, &output)) {
+ return SettingValue::UNKNOWN;
+ }
+
+ // State 1 is when the Firewall is simply enabled.
+ // State 2 is when the Firewall is enabled and all incoming connections are
+ // blocked.
+ if (output.find("(State = 1)") != std::string::npos ||
+ output.find("(State = 2)") != std::string::npos) {
+ return SettingValue::ENABLED;
+ }
+ if (output.find("(State = 0)") != std::string::npos) {
+ return SettingValue::DISABLED;
+ }
+
+ return SettingValue::UNKNOWN;
}
#endif