From 08144b54a729a0be7f4d9f860d92d1c63ad4e7d5 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Wed, 24 Jan 2018 21:07:48 -0500 Subject: [PATCH 01/25] docs: updated configuration details (#232) * docs: updated configuration details * config: add example mobileconfig --- .../com.google.santa.example.mobileconfig | 83 +++++++++++ Docs/deployment/configuration.md | 131 +++++++++++++----- Docs/details/mode.md | 25 ++-- 3 files changed, 188 insertions(+), 51 deletions(-) create mode 100644 Docs/deployment/com.google.santa.example.mobileconfig diff --git a/Docs/deployment/com.google.santa.example.mobileconfig b/Docs/deployment/com.google.santa.example.mobileconfig new file mode 100644 index 000000000..3a583873b --- /dev/null +++ b/Docs/deployment/com.google.santa.example.mobileconfig @@ -0,0 +1,83 @@ + + + + + PayloadContent + + + PayloadContent + + com.google.santa + + Forced + + + mcx_preference_settings + + BannedBlockMessage + This application has been banned + ClientMode + 1 + EnablePageZeroProtection + + EventDetailText + Open sync server + EventDetailURL + https://sync-server-hostname/blockables/%file_sha% + FileChangesRegex + ^/(?!(?:private/tmp|Library/(?:Caches|Managed Installs/Logs|(?:Managed )?Preferences))/) + MachineIDKey + MachineUUID + MachineIDPlist + /Library/Preferences/com.company.machine-mapping.plist + MachineOwnerKey + Owner + MachineOwnerPlist + /Library/Preferences/com.company.machine-mapping.plist + ModeNotificationLockdown + Entering Lockdown mode + ModeNotificationMonitor + Entering Monitor mode<br/>Please be careful! + MoreInfoURL + https://sync-server-hostname/moreinfo + SyncBaseURL + https://sync-server-hostname/api/santa/ + UnknownBlockMessage + This application has been blocked from executing. + + + + + + PayloadEnabled + + PayloadIdentifier + 0342c558-a101-4a08-a0b9-40cc00039ea5 + PayloadType + com.apple.ManagedClient.preferences + PayloadUUID + 0342c558-a101-4a08-a0b9-40cc00039ea5 + PayloadVersion + 1 + + + PayloadDescription + com.google.santa + PayloadDisplayName + com.google.santa + PayloadIdentifier + com.google.santa + PayloadOrganization + + PayloadRemovalDisallowed + + PayloadScope + System + PayloadType + Configuration + PayloadUUID + 9020fb2d-cab3-420f-9268-acca4868bdd0 + PayloadVersion + 1 + + diff --git a/Docs/deployment/configuration.md b/Docs/deployment/configuration.md index c884084be..ea71dde2a 100644 --- a/Docs/deployment/configuration.md +++ b/Docs/deployment/configuration.md @@ -1,8 +1,12 @@ +# Important + +Santa v0.9.21 has moved to using an Apple [Configuration Profile](https://developer.apple.com/library/content/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html) to manage the local configuration. The old config file (`/var/db/santa/config.plist`) is no longer used. + # Configuration -Two configuration methods can be used to control Santa: local configuration and a sync server controlled configuration. There are certain options that can only be controlled with a local configuration and others that can only be controlled with a sync server controlled configuration. Additionally, there are options that can be controlled by both. +Two configuration methods can be used to control Santa: a local configuration profile and a sync server controlled configuration. There are certain options that can only be controlled with a local configuration profile and others that can only be controlled with a sync server controlled configuration. Additionally, there are options that can be controlled by both. -## Local Configuration +## Local Configuration Profile | Key | Value Type | Description | | ----------------------------- | ---------- | ---------------------------------------- | @@ -32,7 +36,7 @@ Two configuration methods can be used to control Santa: local configuration and | MachineIDPlist | String | The path to a plist that contains the MachineOwnerKey / value pair. | | MachineIDKey | String | The key to use on MachineIDPlist. | -*protected keys: If a sync server is configured, this setting cannot be changed while santad is running as it is assumed the setting will be provided by the sync server. +*overridable by the sync server: run `santactl status` to check the current running config ##### EventDetailURL @@ -50,49 +54,108 @@ This property contains a kind of format string to be turned into the URL to send For example: `https://sync-server-hostname/%machine_id%/%file_sha%` -##### Example Config +##### Example Configuration Profile + +Here is an example of a configuration profile that could be set. It was generated with Tim Sutton's great [mcxToProfile](https://github.com/timsutton/mcxToProfile) tool. A copy is also available [here](com.google.santa.example.mobileconfig). + +A few key points to when creating your configuration profile: -Here is an example of a configuration that could be set. +* `com.google.santa` needs to be the key inside `PayloadContent` +* The `PayloadScope` needs to be `System` ```xml - BannedBlockMessage - This application has been banned - ClientMode + PayloadContent + + + PayloadContent + + com.google.santa + + Forced + + + mcx_preference_settings + + BannedBlockMessage + This application has been banned + ClientMode + 1 + EnablePageZeroProtection + + EventDetailText + Open sync server + EventDetailURL + https://sync-server-hostname/blockables/%file_sha% + FileChangesRegex + ^/(?!(?:private/tmp|Library/(?:Caches|Managed Installs/Logs|(?:Managed )?Preferences))/) + MachineIDKey + MachineUUID + MachineIDPlist + /Library/Preferences/com.company.machine-mapping.plist + MachineOwnerKey + Owner + MachineOwnerPlist + /Library/Preferences/com.company.machine-mapping.plist + ModeNotificationLockdown + Entering Lockdown mode + ModeNotificationMonitor + Entering Monitor mode<br/>Please be careful! + MoreInfoURL + https://sync-server-hostname/moreinfo + SyncBaseURL + https://sync-server-hostname/api/santa/ + UnknownBlockMessage + This application has been blocked from executing. + + + + + + PayloadEnabled + + PayloadIdentifier + 0342c558-a101-4a08-a0b9-40cc00039ea5 + PayloadType + com.apple.ManagedClient.preferences + PayloadUUID + 0342c558-a101-4a08-a0b9-40cc00039ea5 + PayloadVersion + 1 + + + PayloadDescription + com.google.santa + PayloadDisplayName + com.google.santa + PayloadIdentifier + com.google.santa + PayloadOrganization + + PayloadRemovalDisallowed + + PayloadScope + System + PayloadType + Configuration + PayloadUUID + 9020fb2d-cab3-420f-9268-acca4868bdd0 + PayloadVersion 1 - EnablePageZeroProtection - - EventDetailText - Open sync server - EventDetailURL - https://sync-server-hostname/blockables/%file_sha% - FileChangesRegex - ^/(?!(?:private/tmp|Library/(?:Caches|Managed Installs/Logs|(?:Managed )?Preferences))/) - MachineIDKey - MachineUUID - MachineIDPlist - /Library/Preferences/com.company.machine-mapping.plist - MachineOwnerKey - Owner - MachineOwnerPlist - /Library/Preferences/com.company.machine-mapping.plist - ModeNotificationLockdown - Entering Lockdown mode - ModeNotificationMonitor - Entering Monitor mode<br/>Please be careful! - MoreInfoURL - https://sync-server-hostname/moreinfo - SyncBaseURL - https://sync-server-hostname/api/santa/ - UnknownBlockMessage - This application has been blocked from executing. + ``` +Configuration profiles have a `.mobileconfig` file extension. There are many ways to install configuration profiles: + +* Double click them in Finder +* Use the `/usr/bin/profiles` tool +* Use an MDM + ## Sync server Provided Configuration | Key | Value Type | Description | diff --git a/Docs/details/mode.md b/Docs/details/mode.md index c38adf478..8ff1d253a 100644 --- a/Docs/details/mode.md +++ b/Docs/details/mode.md @@ -35,28 +35,19 @@ Running Santa in Lockdown Mode will stop all blacklisted binaries and additional ##### Changing Modes -There are two ways to change the running mode: changing the config.plist and with a sync server configuration. +There are two ways to change the running mode: changing the configuration profile and with a sync server configuration. -###### Change modes with the config.plist +###### Change modes with the configuration profile -The `ClientMode` config key is protected while santad is running and will revert any attempt to change it. +Set the `ClientMode` in your configuration profile to the integer value `1` for MONITOR or `2` for LOCKDOWN. -Change to Monitor mode: - -```sh -sudo launchctl unload /Library/LaunchDaemons/com.google.santad.plist -sudo defaults write /var/db/santa/config.plist ClientMode -int 1 -sudo launchctl load /Library/LaunchDaemons/com.google.santad.plist +```xml +ClientMode +1 ``` -Change to Lockdown mode: - -```sh -sudo launchctl unload /Library/LaunchDaemons/com.google.santad.plist -sudo defaults write /var/db/santa/config.plist ClientMode -int 2 -sudo launchctl load /Library/LaunchDaemons/com.google.santad.plist -``` +Install your new configuration profile, it will overwrite any old `com.google.santa` profiles you may have already install. See the [configuration](../deployment/configuration.md) document for more details. -######Change modes with a sync server +###### Change modes with a sync server The mode is set in the preflight sync stage. Use the key `client_mode` and a value of `MONITOR` or `LOCKDOWN`. From 7ca2028c198f28eec852f0e34b7e239ec883230a Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Fri, 26 Jan 2018 11:33:04 -0500 Subject: [PATCH 02/25] santabs: don't try to lookup nil bundle paths (#233) --- Source/santabs/SNTBundleService.m | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/santabs/SNTBundleService.m b/Source/santabs/SNTBundleService.m index 9a2fe0355..e93ded9a6 100644 --- a/Source/santabs/SNTBundleService.m +++ b/Source/santabs/SNTBundleService.m @@ -98,11 +98,20 @@ - (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event dispatch_semaphore_t sema = dispatch_semaphore_create(0); dispatch_async(self.queue, ^{ - // Use the highest bundle we can find. Save and reuse the bundle infomation when creating - // the related binary events. + // Use the highest bundle we can find. SNTFileInfo *b = [[SNTFileInfo alloc] initWithPath:event.fileBundlePath]; b.useAncestorBundle = YES; event.fileBundlePath = b.bundlePath; + + // If path to the bundle is unavailable, stop. SantaGUI will revert to + // using the offending blockable. + if (!event.fileBundlePath) { + reply(nil, nil, 0); + dispatch_semaphore_signal(sema); + return; + } + + // Reuse the bundle infomation when creating the related binary events. event.fileBundleID = b.bundleIdentifier; event.fileBundleName = b.bundleName; event.fileBundleVersion = b.bundleVersion; From 0e6eb45732f55a6610c75bdf34e86fd439eef2d5 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Fri, 26 Jan 2018 11:33:54 -0500 Subject: [PATCH 03/25] santa-driver: add an acknowledge feature to allow timeouts (#220) * santa-driver: Add an acknowledge feature to allow timeouts for lost requests * project: cocoapods 1.3.1 update * review updates --- Podfile.lock | 2 +- Santa.xcodeproj/project.pbxproj | 25 +++++++++++++---- Source/common/SNTKernelCommon.h | 4 ++- Source/santa-driver/SantaDecisionManager.cc | 19 ++++++++++--- Source/santa-driver/SantaDecisionManager.h | 6 +++++ Source/santa-driver/SantaDriverClient.cc | 13 +++++++++ Source/santa-driver/SantaDriverClient.h | 5 ++++ Source/santad/SNTDriverManager.m | 7 +++++ Source/santad/SNTExecutionController.m | 13 +++++++++ Tests/KernelTests/main.mm | 30 +++++++++++++++++++++ 10 files changed, 113 insertions(+), 11 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 5bae5391f..551627fbc 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -29,4 +29,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: acd378b3727c923d912e09812da344f7375c14fe -COCOAPODS: 1.2.1 +COCOAPODS: 1.3.1 diff --git a/Santa.xcodeproj/project.pbxproj b/Santa.xcodeproj/project.pbxproj index 94a3c56c7..f1228fade 100644 --- a/Santa.xcodeproj/project.pbxproj +++ b/Santa.xcodeproj/project.pbxproj @@ -1221,13 +1221,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-santad-santabs-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 2146C1274A8C11B3755A8A67 /* [CP] Check Pods Manifest.lock */ = { @@ -1236,13 +1239,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-santad-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 23869BA352E2C86DEFE62819 /* [CP] Copy Pods Resources */ = { @@ -1296,13 +1302,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-LogicTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; B193461D3612BCB47C16E407 /* [CP] Check Pods Manifest.lock */ = { @@ -1311,13 +1320,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Santa-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; BA20035148DDEF5808B2C7EF /* [CP] Embed Pods Frameworks */ = { @@ -1358,13 +1370,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-santactl-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; D49A3AB950AFD99741E9AF89 /* [CP] Embed Pods Frameworks */ = { diff --git a/Source/common/SNTKernelCommon.h b/Source/common/SNTKernelCommon.h index 8c7345001..a127eec7f 100644 --- a/Source/common/SNTKernelCommon.h +++ b/Source/common/SNTKernelCommon.h @@ -37,6 +37,7 @@ enum SantaDriverMethods { kSantaUserClientOpen, kSantaUserClientAllowBinary, kSantaUserClientDenyBinary, + kSantaUserClientAcknowledgeBinary, kSantaUserClientClearCache, kSantaUserClientCacheCount, kSantaUserClientCheckCache, @@ -64,7 +65,8 @@ typedef enum { ACTION_RESPOND_ALLOW = 20, ACTION_RESPOND_DENY = 21, ACTION_RESPOND_TOOLONG = 22, - + ACTION_RESPOND_ACK = 23, + // NOTIFY ACTION_NOTIFY_EXEC = 30, ACTION_NOTIFY_WRITE = 31, diff --git a/Source/santa-driver/SantaDecisionManager.cc b/Source/santa-driver/SantaDecisionManager.cc index d2908ad6a..e7e928857 100644 --- a/Source/santa-driver/SantaDecisionManager.cc +++ b/Source/santa-driver/SantaDecisionManager.cc @@ -233,10 +233,15 @@ void SantaDecisionManager::AddToCache( case ACTION_REQUEST_BINARY: decision_cache->set(identifier, val, 0); break; + case ACTION_RESPOND_ACK: + decision_cache->set(identifier, val, ((uint64_t)ACTION_REQUEST_BINARY << 56)); + break; case ACTION_RESPOND_ALLOW: case ACTION_RESPOND_DENY: - decision_cache->set( - identifier, val, ((uint64_t)ACTION_REQUEST_BINARY << 56)); + // TODO(bur): Avoid calling set() twice, finding and locking buckets is fast, but not free. + if (decision_cache->set(identifier, val, ((uint64_t)ACTION_REQUEST_BINARY << 56))) { + decision_cache->set(identifier, val, ((uint64_t)ACTION_RESPOND_ACK << 56)); + } break; default: break; @@ -316,10 +321,16 @@ santa_action_t SantaDecisionManager::GetFromDaemon( return ACTION_ERROR; } + // Check the cache every kRequestLoopSleepMilliseconds. Break this loop and send the request + // again if kRequestCacheChecks is reached. Don't break the loop if the daemon is working on the + // request, indicated with ACTION_RESPOND_ACK. + auto cache_check_count = 0; do { msleep((void *)message->vnode_id, NULL, 0, "", &ts_); return_action = GetFromCache(identifier); - } while (return_action == ACTION_REQUEST_BINARY && ClientConnected()); + } while (ClientConnected() && + ((return_action == ACTION_REQUEST_BINARY && ++cache_check_count < kRequestCacheChecks) + || (return_action == ACTION_RESPOND_ACK))); } while (!RESPONSE_VALID(return_action) && ClientConnected()); // If response is still not valid, the daemon exited @@ -354,7 +365,7 @@ santa_action_t SantaDecisionManager::FetchDecision( // If item is not in cache, break out of loop to send request to daemon. if (RESPONSE_VALID(return_action)) { return return_action; - } else if (return_action == ACTION_REQUEST_BINARY) { + } else if (return_action == ACTION_REQUEST_BINARY || return_action == ACTION_RESPOND_ACK) { // This thread will now sleep for kRequestLoopSleepMilliseconds (1s) or // until AddToCache is called, indicating a response has arrived. msleep((void *)vnode_id, NULL, 0, "", &ts_); diff --git a/Source/santa-driver/SantaDecisionManager.h b/Source/santa-driver/SantaDecisionManager.h index cd53ab9e2..4914d4a1d 100644 --- a/Source/santa-driver/SantaDecisionManager.h +++ b/Source/santa-driver/SantaDecisionManager.h @@ -144,6 +144,12 @@ class SantaDecisionManager : public OSObject { */ static const uint32_t kRequestLoopSleepMilliseconds = 1000; + /** + While waiting for a response from the daemon, this is the maximum number cache checks before + re-sending the request. + */ + static const uint32_t kRequestCacheChecks = 5; + /** The maximum number of milliseconds a cached deny message should be considered valid. diff --git a/Source/santa-driver/SantaDriverClient.cc b/Source/santa-driver/SantaDriverClient.cc index 93a3a7b7b..4ffd38303 100644 --- a/Source/santa-driver/SantaDriverClient.cc +++ b/Source/santa-driver/SantaDriverClient.cc @@ -152,6 +152,18 @@ IOReturn SantaDriverClient::deny_binary( return kIOReturnSuccess; } +IOReturn SantaDriverClient::acknowledge_binary( + OSObject *target, void *reference, IOExternalMethodArguments *arguments) { + SantaDriverClient *me = OSDynamicCast(SantaDriverClient, target); + if (!me) return kIOReturnBadArgument; + + const uint64_t vnode_id = static_cast(arguments->scalarInput[0]); + if (!vnode_id) return kIOReturnInvalid; + me->decisionManager->AddToCache(vnode_id, ACTION_RESPOND_ACK, 0); + + return kIOReturnSuccess; +} + IOReturn SantaDriverClient::clear_cache( OSObject *target, void *reference, IOExternalMethodArguments *arguments) { SantaDriverClient *me = OSDynamicCast(SantaDriverClient, target); @@ -199,6 +211,7 @@ IOReturn SantaDriverClient::externalMethod( { &SantaDriverClient::open, 0, 0, 0, 0 }, { &SantaDriverClient::allow_binary, 1, 0, 0, 0 }, { &SantaDriverClient::deny_binary, 1, 0, 0, 0 }, + { &SantaDriverClient::acknowledge_binary, 1, 0, 0, 0 }, { &SantaDriverClient::clear_cache, 1, 0, 0, 0 }, { &SantaDriverClient::cache_count, 0, 0, 2, 0 }, { &SantaDriverClient::check_cache, 1, 0, 1, 0 } diff --git a/Source/santa-driver/SantaDriverClient.h b/Source/santa-driver/SantaDriverClient.h index c16566eb9..a31dd2d6f 100644 --- a/Source/santa-driver/SantaDriverClient.h +++ b/Source/santa-driver/SantaDriverClient.h @@ -87,6 +87,11 @@ class com_google_SantaDriverClient : public IOUserClient { static IOReturn deny_binary( OSObject *target, void *reference, IOExternalMethodArguments *arguments); + /// The daemon calls this to acknowledge a binary request. This is used for large binaries that + /// may take a while to reach a decision. + static IOReturn acknowledge_binary( + OSObject *target, void *reference, IOExternalMethodArguments *arguments); + /// The daemon calls this to empty the cache. static IOReturn clear_cache( OSObject *target, void *reference, IOExternalMethodArguments *arguments); diff --git a/Source/santad/SNTDriverManager.m b/Source/santad/SNTDriverManager.m index 78d552137..b84f79555 100644 --- a/Source/santad/SNTDriverManager.m +++ b/Source/santad/SNTDriverManager.m @@ -162,6 +162,13 @@ - (kern_return_t)postToKernelAction:(santa_action_t)action forVnodeID:(uint64_t) 1, 0, 0); + case ACTION_RESPOND_ACK: + return IOConnectCallScalarMethod(_connection, + kSantaUserClientAcknowledgeBinary, + &vnodeId, + 1, + 0, + 0); default: return KERN_INVALID_ARGUMENT; } diff --git a/Source/santad/SNTExecutionController.m b/Source/santad/SNTExecutionController.m index e844a08d5..2e27d6b6a 100644 --- a/Source/santad/SNTExecutionController.m +++ b/Source/santad/SNTExecutionController.m @@ -38,6 +38,12 @@ #import "SNTStoredEvent.h" #import "SNTSyncdQueue.h" +// A binary is considered large at ~30MB. Large binaries take longer to hash and consequently +// longer to post a decision back to santa-driver. When a binary is considered large santad will +// let santa-driver know it has received its request and is working on a decision. This allows +// santa-driver to relax; it does not have to worry about resending the request due to a timeout. +static size_t kLargeBinarySize = 30 * 1024 * 1024; + @interface SNTExecutionController () @property SNTDriverManager *driverManager; @property SNTEventLog *eventLog; @@ -102,6 +108,13 @@ - (void)validateBinaryWithMessage:(santa_message_t)message { return; } + // If the binary is large let santa-driver know we received the request and we are working on it. + if (binInfo.fileSize > kLargeBinarySize) { + LOGD(@"%@ is larger than %zu. Letting santa-driver know we are working on it.", + binInfo.path, kLargeBinarySize); + [_driverManager postToKernelAction:ACTION_RESPOND_ACK forVnodeID:message.vnode_id]; + } + // Get codesigning info about the file. NSError *csError; MOLCodesignChecker *csInfo = [[MOLCodesignChecker alloc] initWithBinaryPath:binInfo.path diff --git a/Tests/KernelTests/main.mm b/Tests/KernelTests/main.mm index 67e3b60a6..729ab5c60 100644 --- a/Tests/KernelTests/main.mm +++ b/Tests/KernelTests/main.mm @@ -99,6 +99,9 @@ - (void)postToKernelAction:(santa_action_t)action forVnodeID:(uint64_t)vnodeid { IOConnectCallScalarMethod(self.connection, kSantaUserClientAllowBinary, &vnodeid, 1, 0, 0); } else if (action == ACTION_RESPOND_DENY) { IOConnectCallScalarMethod(self.connection, kSantaUserClientDenyBinary, &vnodeid, 1, 0, 0); + } else if (action == ACTION_RESPOND_ACK) { + IOConnectCallScalarMethod(self.connection, kSantaUserClientAcknowledgeBinary, + &vnodeid, 1, 0, 0); } } @@ -239,6 +242,18 @@ - (void)beginListening { } else if (strncmp("/bin/cat", vdata.path, strlen("/bin/cat")) == 0) { [self postToKernelAction:ACTION_RESPOND_ALLOW forVnodeID:vdata.vnode_id]; self.timesSeenCat++; + } else if (strncmp("/usr/bin/cal", vdata.path, strlen("/usr/bin/cal")) == 0) { + static int count = 0; + if (count++) TFAILINFO("Large binary should not re-request"); + [self postToKernelAction:ACTION_RESPOND_ACK forVnodeID:vdata.vnode_id]; + for (int i = 0; i < 15; ++i) { + printf("\033[s"); // save cursor position + printf("%i/15", i); + sleep(1); + printf("\033[u"); // restore cursor position + } + printf("\033[K\033[u"); // clear line, restore cursor position + [self postToKernelAction:ACTION_RESPOND_ALLOW forVnodeID:vdata.vnode_id]; } else if (strncmp("/bin/ln", vdata.path, strlen("/bin/ln")) == 0) { [self postToKernelAction:ACTION_RESPOND_ALLOW forVnodeID:vdata.vnode_id]; @@ -554,6 +569,20 @@ - (void)testCachePerformance { } } +- (void)testLargeBinary { + TSTART("Handles large binary"); + + @try { + NSTask *testexec = [self taskWithPath:@"/usr/bin/cal"]; + [testexec launch]; + [testexec waitUntilExit]; + } @catch (NSException *e) { + TFAILINFO("Failed to launch"); + } + + TPASS(); +} + #pragma mark - Main - (void)runTests { @@ -580,6 +609,7 @@ - (void)runTests { printf("\n-> Performance tests:\033[m\n"); [self testCachePerformance]; + [self testLargeBinary]; [self handlesLotsOfBinaries]; printf("\nAll tests passed.\n\n"); From 400c4130294d026b1aa9b36962f8d217b4d5ae37 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Fri, 2 Feb 2018 12:01:51 -0500 Subject: [PATCH 04/25] config: add option to disable mode change notifications (#235) * config: add option to disable mode change notifications * config: don't do extra work * config: handle none, default and custom * config: cleaner --- Source/SantaGUI/SNTNotificationManager.m | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/SantaGUI/SNTNotificationManager.m b/Source/SantaGUI/SNTNotificationManager.m index 15169f55d..36e394ab3 100644 --- a/Source/SantaGUI/SNTNotificationManager.m +++ b/Source/SantaGUI/SNTNotificationManager.m @@ -102,14 +102,16 @@ - (void)postClientModeNotification:(SNTClientMode)clientmode { case SNTClientModeMonitor: un.informativeText = @"Switching into Monitor mode"; customMsg = [[SNTConfigurator configurator] modeNotificationMonitor]; - customMsg = [SNTBlockMessage stringFromHTML:customMsg]; - if (customMsg.length) un.informativeText = customMsg; + if (!customMsg) break; + if (!customMsg.length) return; + un.informativeText = [SNTBlockMessage stringFromHTML:customMsg]; break; case SNTClientModeLockdown: un.informativeText = @"Switching into Lockdown mode"; customMsg = [[SNTConfigurator configurator] modeNotificationLockdown]; - customMsg = [SNTBlockMessage stringFromHTML:customMsg]; - if (customMsg.length) un.informativeText = customMsg; + if (!customMsg) break; + if (!customMsg.length) return; + un.informativeText = [SNTBlockMessage stringFromHTML:customMsg]; break; default: return; From fc87cde6681fb2d8641818b005802addb49d60dd Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Wed, 7 Feb 2018 13:59:00 -0500 Subject: [PATCH 05/25] config: use KVO (#234) * config: atomically update config * config: add an explanation for sleep usage * config: use mobileconfig in the getters * config: cleanup file watcher * config: spell * config: clear or reload sync state on sync base url change * config: Use KVO and Dependent Keys * config: remove debug log * config: review updates * config: update rule sync getter and setter names * config: get logical --- Santa.xcodeproj/project.pbxproj | 6 +- Source/SantaGUI/SNTAppDelegate.m | 8 - Source/common/SNTConfigurator.h | 46 +- Source/common/SNTConfigurator.m | 520 ++++++++++-------- Source/common/SNTXPCControlInterface.h | 5 +- Source/santactl/Commands/SNTCommandStatus.m | 46 +- .../Commands/sync/SNTCommandSyncPostflight.m | 2 +- .../Commands/sync/SNTCommandSyncPreflight.m | 10 +- Source/santad/SNTApplication.m | 152 +++-- Source/santad/SNTDaemonControlController.m | 32 +- 10 files changed, 491 insertions(+), 336 deletions(-) diff --git a/Santa.xcodeproj/project.pbxproj b/Santa.xcodeproj/project.pbxproj index f1228fade..a552df836 100644 --- a/Santa.xcodeproj/project.pbxproj +++ b/Santa.xcodeproj/project.pbxproj @@ -149,7 +149,6 @@ 0DEA5F7D1CF64EB600704398 /* SNTCommandSyncRuleDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D0A1EC2191998C900B8450F /* SNTCommandSyncRuleDownload.m */; }; 0DEFB7C01ACB28B000B92AAE /* SNTCommandSyncConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7BF1ACB28B000B92AAE /* SNTCommandSyncConstants.m */; }; 0DEFB7C41ACDD80100B92AAE /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; - 0DEFB7C51ACDD80100B92AAE /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; 0DEFB7C61ACDE5F600B92AAE /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; 0DEFB7C81ACF0BFE00B92AAE /* SNTFileWatcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C71ACF0BFE00B92AAE /* SNTFileWatcherTest.m */; }; 0DF395641AB76A7900CBC520 /* NSData+Zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DF395631AB76A7900CBC520 /* NSData+Zlib.m */; }; @@ -172,6 +171,8 @@ C76614EC1D142D3C00D150C1 /* SNTCommandCheckCache.m in Sources */ = {isa = PBXBuildFile; fileRef = C76614EB1D142D3C00D150C1 /* SNTCommandCheckCache.m */; }; C776A1071DEE160500A56616 /* SNTCommandSyncManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C776A1061DEE160500A56616 /* SNTCommandSyncManager.m */; }; C78227631E1C3C7D006EB2D6 /* santabs.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = C78227541E1C3C58006EB2D6 /* santabs.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + C7943FE92028B855008D4F76 /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; + C7943FEA2028C4F7008D4F76 /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; C795ED901D80A5BE007CFF42 /* SNTPolicyProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */; }; C795ED911D80B66B007CFF42 /* SNTPolicyProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */; }; C79A23581E23F7E80037AFA8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C79A23561E23F7E80037AFA8 /* main.m */; }; @@ -1515,6 +1516,7 @@ C76614EC1D142D3C00D150C1 /* SNTCommandCheckCache.m in Sources */, 0D416401191974F1006A356A /* SNTCommandSyncState.m in Sources */, 0DC5D871192160180078A5C0 /* SNTCommandSyncLogUpload.m in Sources */, + C7943FE92028B855008D4F76 /* SNTFileWatcher.m in Sources */, 0DB77FDA1CD14092004DF060 /* SNTBlockMessage.m in Sources */, 0D35BDA218FD71CE00921A21 /* main.m in Sources */, 0DCD6043190ACCB8006B445C /* SNTFileInfo.m in Sources */, @@ -1533,6 +1535,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C7943FEA2028C4F7008D4F76 /* SNTFileWatcher.m in Sources */, 0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */, 0D385DF1180DE51600418BC6 /* SNTAppDelegate.m in Sources */, 0D88680A1AC48A1200B86659 /* SNTSystemInfo.m in Sources */, @@ -1547,7 +1550,6 @@ 0D1B477019A53419008CADD3 /* SNTAboutWindowController.m in Sources */, 0D668E8118D1121700E29A8B /* SNTMessageWindow.m in Sources */, 0DA73CA11934F8100056D7C4 /* SNTLogging.m in Sources */, - 0DEFB7C51ACDD80100B92AAE /* SNTFileWatcher.m in Sources */, C7479F051E53704E0054C1CF /* SNTXPCBundleServiceInterface.m in Sources */, 0D20710E1A7C4A86008B0A9A /* SNTStoredEvent.m in Sources */, 0DE2CE561CA05561002B649A /* SNTAccessibleTextField.m in Sources */, diff --git a/Source/SantaGUI/SNTAppDelegate.m b/Source/SantaGUI/SNTAppDelegate.m index 4d1c6d7dd..61edadd62 100644 --- a/Source/SantaGUI/SNTAppDelegate.m +++ b/Source/SantaGUI/SNTAppDelegate.m @@ -16,7 +16,6 @@ #import "SNTAboutWindowController.h" #import "SNTConfigurator.h" -#import "SNTFileWatcher.h" #import "SNTNotificationManager.h" #import "SNTStrengthify.h" #import "SNTXPCConnection.h" @@ -24,7 +23,6 @@ @interface SNTAppDelegate () @property SNTAboutWindowController *aboutWindowController; -@property SNTFileWatcher *configFileWatcher; @property SNTNotificationManager *notificationManager; @property SNTXPCConnection *daemonListener; @property SNTXPCConnection *bundleListener; @@ -36,12 +34,6 @@ @implementation SNTAppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [self setupMenu]; - - self.configFileWatcher = [[SNTFileWatcher alloc] initWithFilePath:kMobileConfigFilePath - handler:^(unsigned long data) { - if (!(data & DISPATCH_VNODE_ATTRIB)) [[SNTConfigurator configurator] reloadConfigData]; - }]; - self.notificationManager = [[SNTNotificationManager alloc] init]; NSNotificationCenter *workspaceNotifications = [[NSWorkspace sharedWorkspace] notificationCenter]; diff --git a/Source/common/SNTConfigurator.h b/Source/common/SNTConfigurator.h index 7b12ce176..808e3b565 100644 --- a/Source/common/SNTConfigurator.h +++ b/Source/common/SNTConfigurator.h @@ -16,12 +16,10 @@ #import "SNTCommonEnums.h" -extern NSString *const kSyncStateFilePath; -extern NSString *const kMobileConfigFilePath; - /// /// Singleton that provides an interface for managing configuration values on disk /// @note This class is designed as a singleton but that is not strictly enforced. +/// @note All properties are KVO compliant. /// @interface SNTConfigurator : NSObject @@ -30,16 +28,12 @@ extern NSString *const kMobileConfigFilePath; /// /// The operating mode. /// -@property(nonatomic) SNTClientMode clientMode; +@property(readonly, nonatomic) SNTClientMode clientMode; /// -/// The regex of paths to log file changes for. Regexes are specified in ICU format. -/// -/// The regex flags IXSM can be used, though the s (dotalL) and m (multiline) flags are -/// pointless as a path only ever has a single line. -/// If the regex doesn't begin with ^ to match from the beginning of the line, it will be added. +/// Set the operating mode as received from a sync server. /// -@property(nonatomic) NSRegularExpression *fileChangesRegex; +- (void)setSyncServerClientMode:(SNTClientMode)newMode; /// /// The regex of whitelisted paths. Regexes are specified in ICU format. @@ -48,7 +42,12 @@ extern NSString *const kMobileConfigFilePath; /// pointless as a path only ever has a single line. /// If the regex doesn't begin with ^ to match from the beginning of the line, it will be added. /// -@property(nonatomic) NSRegularExpression *whitelistPathRegex; +@property(readonly, nonatomic) NSRegularExpression *whitelistPathRegex; + +/// +/// Set the regex of whitelisted paths as received from a sync server. +/// +- (void)setSyncServerWhitelistPathRegex:(NSRegularExpression *)re; /// /// The regex of blacklisted paths. Regexes are specified in ICU format. @@ -57,7 +56,21 @@ extern NSString *const kMobileConfigFilePath; /// pointless as a path only ever has a single line. /// If the regex doesn't begin with ^ to match from the beginning of the line, it will be added. /// -@property(nonatomic) NSRegularExpression *blacklistPathRegex; +@property(readonly, nonatomic) NSRegularExpression *blacklistPathRegex; + +/// +/// Set the regex of blacklisted paths as received from a sync server. +/// +- (void)setSyncServerBlacklistPathRegex:(NSRegularExpression *)re; + +/// +/// The regex of paths to log file changes for. Regexes are specified in ICU format. +/// +/// The regex flags IXSM can be used, though the s (dotalL) and m (multiline) flags are +/// pointless as a path only ever has a single line. +/// If the regex doesn't begin with ^ to match from the beginning of the line, it will be added. +/// +@property(readonly, nonatomic) NSRegularExpression *fileChangesRegex; /// /// Enable __PAGEZERO protection, defaults to YES @@ -202,13 +215,8 @@ extern NSString *const kMobileConfigFilePath; + (instancetype)configurator; /// -/// Re-read config data from disk. -/// -- (void)reloadConfigData; - -/// -/// Notify the receiver that the sync state file has changed. +/// Clear the sync server configuration from the effective configuration. /// -- (void)syncStateFileChanged:(unsigned long)data; +- (void)clearSyncState; @end diff --git a/Source/common/SNTConfigurator.m b/Source/common/SNTConfigurator.m index b0f7793b7..d8c14082a 100644 --- a/Source/common/SNTConfigurator.m +++ b/Source/common/SNTConfigurator.m @@ -16,23 +16,25 @@ #include +#import "SNTFileWatcher.h" #import "SNTLogging.h" +#import "SNTStrengthify.h" #import "SNTSystemInfo.h" @interface SNTConfigurator () -@property NSMutableDictionary *configData; - -/// Creating NSRegularExpression objects is not fast, so cache them. -@property NSRegularExpression *cachedFileChangesRegex; -@property NSRegularExpression *cachedWhitelistDirRegex; -@property NSRegularExpression *cachedBlacklistDirRegex; - /// A NSUserDefaults object set to use the com.google.santa suite. @property(readonly, nonatomic) NSUserDefaults *defaults; -/// Keys used by a mobileconfig or sync server -@property(readonly, nonatomic) NSArray *syncServerKeys; -@property(readonly, nonatomic) NSArray *mobileConfigKeys; +// Keys and expected value types. +@property(readonly, nonatomic) NSDictionary *syncServerKeyTypes; +@property(readonly, nonatomic) NSDictionary *forcedConfigKeyTypes; + +/// Holds the configurations from a sync server and mobileconfig. +@property NSMutableDictionary *syncState; +@property NSMutableDictionary *configState; + +/// Watcher for the sync-state.plist. +@property(nonatomic) SNTFileWatcher *syncStateWatcher; @end @implementation SNTConfigurator @@ -43,9 +45,6 @@ @implementation SNTConfigurator /// The domain used by mobileconfig. static NSString *const kMobileConfigDomain = @"com.google.santa"; -/// The hard-coded path to the mobileconfig file. -NSString *const kMobileConfigFilePath = @"/Library/Managed Preferences/com.google.santa.plist"; - /// The keys managed by a mobileconfig. static NSString *const kSyncBaseURLKey = @"SyncBaseURL"; static NSString *const kClientAuthCertificateFileKey = @"ClientAuthCertificateFile"; @@ -72,11 +71,12 @@ @implementation SNTConfigurator static NSString *const kEnablePageZeroProtectionKey = @"EnablePageZeroProtection"; +static NSString *const kFileChangesRegexKey = @"FileChangesRegex"; + // The keys managed by a sync server or mobileconfig. static NSString *const kClientModeKey = @"ClientMode"; static NSString *const kWhitelistRegexKey = @"WhitelistRegex"; static NSString *const kBlacklistRegexKey = @"BlacklistRegex"; -static NSString *const kFileChangesRegexKey = @"FileChangesRegex"; // The keys managed by a sync server. static NSString *const kFullSyncLastSuccess = @"FullSyncLastSuccess"; @@ -86,22 +86,46 @@ @implementation SNTConfigurator - (instancetype)init { self = [super init]; if (self) { - _defaults = [[NSUserDefaults alloc] initWithSuiteName:kMobileConfigDomain]; - _syncServerKeys = @[ - kClientModeKey, kWhitelistRegexKey, kBlacklistRegexKey, kFileChangesRegexKey, - kFullSyncLastSuccess, kRuleSyncLastSuccess, kSyncCleanRequired - ]; - _mobileConfigKeys = @[ - kClientModeKey, kFileChangesRegexKey, kWhitelistRegexKey, kBlacklistRegexKey, - kEnablePageZeroProtectionKey, kMoreInfoURLKey, kEventDetailURLKey, kEventDetailTextKey, - kUnknownBlockMessage, kBannedBlockMessage, kModeNotificationMonitor, - kModeNotificationLockdown, kSyncBaseURLKey, kClientAuthCertificateFileKey, - kClientAuthCertificatePasswordKey, kClientAuthCertificateCNKey, - kClientAuthCertificateIssuerKey, kServerAuthRootsDataKey, kServerAuthRootsFileKey, - kMachineOwnerKey, kMachineIDKey, kMachineOwnerPlistFileKey, kMachineOwnerPlistKeyKey, - kMachineIDPlistFileKey, kMachineIDPlistKeyKey - ]; - [self reloadConfigData]; + _syncServerKeyTypes = @{ + kClientModeKey : [NSNumber class], + kWhitelistRegexKey : [NSRegularExpression class], + kBlacklistRegexKey : [NSRegularExpression class], + kFullSyncLastSuccess : [NSDate class], + kRuleSyncLastSuccess : [NSDate class], + kSyncCleanRequired : [NSNumber class] + }; + _forcedConfigKeyTypes = @{ + kClientModeKey : [NSNumber class], + kFileChangesRegexKey : [NSRegularExpression class], + kWhitelistRegexKey : [NSRegularExpression class], + kBlacklistRegexKey : [NSRegularExpression class], + kEnablePageZeroProtectionKey : [NSNumber class], + kMoreInfoURLKey : [NSString class], + kEventDetailURLKey : [NSString class], + kEventDetailTextKey : [NSString class], + kUnknownBlockMessage : [NSString class], + kBannedBlockMessage : [NSString class], + kModeNotificationMonitor : [NSString class], + kModeNotificationLockdown : [NSString class], + kSyncBaseURLKey : [NSString class], + kClientAuthCertificateFileKey : [NSString class], + kClientAuthCertificatePasswordKey : [NSString class], + kClientAuthCertificateCNKey : [NSString class], + kClientAuthCertificateIssuerKey : [NSString class], + kServerAuthRootsDataKey : [NSData class], + kServerAuthRootsFileKey : [NSString class], + kMachineOwnerKey : [NSString class], + kMachineIDKey : [NSString class], + kMachineOwnerPlistFileKey : [NSString class], + kMachineOwnerPlistKeyKey : [NSString class], + kMachineIDPlistFileKey : [NSString class], + kMachineIDPlistKeyKey : [NSString class], + }; + _defaults = [NSUserDefaults standardUserDefaults]; + [_defaults addSuiteNamed:@"com.google.santa"]; + _configState = [self readForcedConfig]; + _syncState = [self readSyncStateFromDisk] ?: [NSMutableDictionary dictionary]; + [self startWatchingDefaults]; } return self; } @@ -117,277 +141,301 @@ + (instancetype)configurator { return sharedConfigurator; } +#pragma mark KVO Dependencies + ++ (NSSet *)keyPathsForValuesAffectingClientMode { + return [NSSet setWithObjects:@"syncState", @"configState", nil]; +} + ++ (NSSet *)keyPathsForValuesAffectingWhitelistPathRegex { + return [NSSet setWithObjects:@"syncState", @"configState", nil]; +} + ++ (NSSet *)keyPathsForValuesAffectingBlacklistPathRegex { + return [NSSet setWithObjects:@"syncState", @"configState", nil]; +} + ++ (NSSet *)keyPathsForValuesAffectingFileChangesRegex { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncBaseURL { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingEnablePageZeroProtection { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingMoreInfoURL { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingEventDetailURL { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingEventDetailText { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingUnknownBlockMessage { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingBannedBlockMessage { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingModeNotificationMonitor { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingModeNotificationLockdown { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateFile { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificatePassword { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateCn { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateIssuer { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncServerAuthRootsData { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncServerAuthRootsFile { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingFullSyncLastSuccess { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingMachineOwner { + return [NSSet setWithObject:@"configState"]; +} + ++ (NSSet *)keyPathsForValuesAffectingMachineID { + return [NSSet setWithObject:@"configState"]; +} + #pragma mark Public Interface - (SNTClientMode)clientMode { - NSInteger cm = SNTClientModeUnknown; - - id mode = self.configData[kClientModeKey]; - if ([mode respondsToSelector:@selector(longLongValue)]) { - cm = (NSInteger)[mode longLongValue]; + SNTClientMode cm = [self.syncState[kClientModeKey] longLongValue]; + if (cm == SNTClientModeMonitor || cm == SNTClientModeLockdown) { + return cm; } + cm = [self.configState[kClientModeKey] longLongValue]; if (cm == SNTClientModeMonitor || cm == SNTClientModeLockdown) { - return (SNTClientMode)cm; - } else { - LOGE(@"Client mode was set to bad value: %ld. Resetting to MONITOR.", cm); - self.clientMode = SNTClientModeMonitor; - return SNTClientModeMonitor; + return cm; } + + return SNTClientModeMonitor; } -- (void)setClientMode:(SNTClientMode)newMode { +- (void)setSyncServerClientMode:(SNTClientMode)newMode { if (newMode == SNTClientModeMonitor || newMode == SNTClientModeLockdown) { - self.configData[kClientModeKey] = @(newMode); - [self saveSyncStateToDisk]; + [self updateSyncStateForKey:kClientModeKey value:@(newMode)]; } else { LOGW(@"Ignoring request to change client mode to %ld", newMode); } } - (NSRegularExpression *)whitelistPathRegex { - if (!self.cachedWhitelistDirRegex && self.configData[kWhitelistRegexKey]) { - NSString *re = self.configData[kWhitelistRegexKey]; - if (![re hasPrefix:@"^"]) re = [@"^" stringByAppendingString:re]; - self.cachedWhitelistDirRegex = [NSRegularExpression regularExpressionWithPattern:re - options:0 - error:NULL]; - } - return self.cachedWhitelistDirRegex; + return self.syncState[kWhitelistRegexKey] ?: self.configState[kWhitelistRegexKey]; } -- (void)setWhitelistPathRegex:(NSRegularExpression *)re { - if (!re) { - [self.configData removeObjectForKey:kWhitelistRegexKey]; - } else { - self.configData[kWhitelistRegexKey] = [re pattern]; - } - self.cachedWhitelistDirRegex = nil; - [self saveSyncStateToDisk]; +- (void)setSyncServerWhitelistPathRegex:(NSRegularExpression *)re { + [self updateSyncStateForKey:kWhitelistRegexKey value:re]; } - (NSRegularExpression *)blacklistPathRegex { - if (!self.cachedBlacklistDirRegex && self.configData[kBlacklistRegexKey]) { - NSString *re = self.configData[kBlacklistRegexKey]; - if (![re hasPrefix:@"^"]) re = [@"^" stringByAppendingString:re]; - self.cachedBlacklistDirRegex = [NSRegularExpression regularExpressionWithPattern:re - options:0 - error:NULL]; - } - return self.cachedBlacklistDirRegex; + return self.syncState[kBlacklistRegexKey] ?: self.configState[kBlacklistRegexKey]; } -- (void)setBlacklistPathRegex:(NSRegularExpression *)re { - if (!re) { - [self.configData removeObjectForKey:kBlacklistRegexKey]; - } else { - self.configData[kBlacklistRegexKey] = [re pattern]; - } - self.cachedBlacklistDirRegex = nil; - [self saveSyncStateToDisk]; +- (void)setSyncServerBlacklistPathRegex:(NSRegularExpression *)re { + [self updateSyncStateForKey:kBlacklistRegexKey value:re]; } - (NSRegularExpression *)fileChangesRegex { - if (!self.cachedFileChangesRegex && self.configData[kFileChangesRegexKey]) { - NSString *re = self.configData[kFileChangesRegexKey]; - if (![re hasPrefix:@"^"]) re = [@"^" stringByAppendingString:re]; - self.cachedFileChangesRegex = [NSRegularExpression regularExpressionWithPattern:re - options:0 - error:NULL]; - } - return self.cachedFileChangesRegex; + return self.configState[kFileChangesRegexKey]; } -- (void)setFileChangesRegex:(NSRegularExpression *)re { - if (!re) { - [self.configData removeObjectForKey:kFileChangesRegexKey]; - } else { - self.configData[kFileChangesRegexKey] = [re pattern]; - } - self.cachedFileChangesRegex = nil; - [self saveSyncStateToDisk]; +- (NSURL *)syncBaseURL { + NSString *urlString = self.configState[kSyncBaseURLKey]; + NSURL *url = [NSURL URLWithString:urlString]; + if (urlString && !url) LOGW(@"SyncBaseURL is not a valid URL!"); + return url; } - (BOOL)enablePageZeroProtection { - NSNumber *keyValue = self.configData[kEnablePageZeroProtectionKey]; - return keyValue ? [keyValue boolValue] : YES; + NSNumber *number = self.configState[kEnablePageZeroProtectionKey]; + return number ? [number boolValue] : YES; } - (NSURL *)moreInfoURL { - return [NSURL URLWithString:self.configData[kMoreInfoURLKey]]; + return [NSURL URLWithString:self.configState[kMoreInfoURLKey]]; } - (NSString *)eventDetailURL { - return self.configData[kEventDetailURLKey]; + return self.configState[kEventDetailURLKey]; } - (NSString *)eventDetailText { - return self.configData[kEventDetailTextKey]; + return self.configState[kEventDetailTextKey]; } - (NSString *)unknownBlockMessage { - return self.configData[kUnknownBlockMessage]; + return self.configState[kUnknownBlockMessage]; } - (NSString *)bannedBlockMessage { - return self.configData[kBannedBlockMessage]; + return self.configState[kBannedBlockMessage]; } - (NSString *)modeNotificationMonitor { - return self.configData[kModeNotificationMonitor]; + return self.configState[kModeNotificationMonitor]; } - (NSString *)modeNotificationLockdown { - return self.configData[kModeNotificationLockdown]; -} - -- (NSURL *)syncBaseURL { - NSString *urlStr = self.configData[kSyncBaseURLKey]; - if (urlStr) { - NSURL *url = [NSURL URLWithString:urlStr]; - if (!url) LOGW(@"SyncBaseURL is not a valid URL!"); - return url; - } - return nil; + return self.configState[kModeNotificationLockdown]; } - (NSString *)syncClientAuthCertificateFile { - return self.configData[kClientAuthCertificateFileKey]; + return self.configState[kClientAuthCertificateFileKey]; } - (NSString *)syncClientAuthCertificatePassword { - return self.configData[kClientAuthCertificatePasswordKey]; + return self.configState[kClientAuthCertificatePasswordKey]; } - (NSString *)syncClientAuthCertificateCn { - return self.configData[kClientAuthCertificateCNKey]; + return self.configState[kClientAuthCertificateCNKey]; } - (NSString *)syncClientAuthCertificateIssuer { - return self.configData[kClientAuthCertificateIssuerKey]; + return self.configState[kClientAuthCertificateIssuerKey]; } - (NSData *)syncServerAuthRootsData { - return self.configData[kServerAuthRootsDataKey]; + return self.configState[kServerAuthRootsDataKey]; } - (NSString *)syncServerAuthRootsFile { - return self.configData[kServerAuthRootsFileKey]; + return self.configState[kServerAuthRootsFileKey]; } - (NSDate *)fullSyncLastSuccess { - return self.configData[kFullSyncLastSuccess]; + return self.syncState[kFullSyncLastSuccess]; } - (void)setFullSyncLastSuccess:(NSDate *)fullSyncLastSuccess { - self.configData[kFullSyncLastSuccess] = fullSyncLastSuccess; - [self saveSyncStateToDisk]; + self.syncState[kFullSyncLastSuccess] = fullSyncLastSuccess; self.ruleSyncLastSuccess = fullSyncLastSuccess; } - (NSDate *)ruleSyncLastSuccess { - return self.configData[kRuleSyncLastSuccess]; + return self.syncState[kRuleSyncLastSuccess]; } - (void)setRuleSyncLastSuccess:(NSDate *)ruleSyncLastSuccess { - self.configData[kRuleSyncLastSuccess] = ruleSyncLastSuccess; + self.syncState[kRuleSyncLastSuccess] = ruleSyncLastSuccess; [self saveSyncStateToDisk]; } - (BOOL)syncCleanRequired { - return [self.configData[kSyncCleanRequired] boolValue]; + return [self.syncState[kSyncCleanRequired] boolValue]; } - (void)setSyncCleanRequired:(BOOL)syncCleanRequired { - self.configData[kSyncCleanRequired] = @(syncCleanRequired); + self.syncState[kSyncCleanRequired] = @(syncCleanRequired); [self saveSyncStateToDisk]; } - (NSString *)machineOwner { - NSString *machineOwner; - - if (self.configData[kMachineOwnerPlistFileKey] && self.configData[kMachineOwnerPlistKeyKey]) { - NSDictionary *plist = - [NSDictionary dictionaryWithContentsOfFile:self.configData[kMachineOwnerPlistFileKey]]; - machineOwner = plist[self.configData[kMachineOwnerPlistKeyKey]]; + NSString *machineOwner = self.configState[kMachineOwnerKey]; + if (machineOwner) return machineOwner; + + NSString *plistPath = self.configState[kMachineOwnerPlistFileKey]; + NSString *plistKey = self.configState[kMachineOwnerPlistKeyKey]; + if (plistPath && plistKey) { + NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistPath]; + machineOwner = [plist[plistKey] isKindOfClass:[NSString class]] ? plist[plistKey] : nil; } - if (self.configData[kMachineOwnerKey]) { - machineOwner = self.configData[kMachineOwnerKey]; - } - - if (!machineOwner) machineOwner = @""; - - return machineOwner; + return machineOwner ?: @""; } - (NSString *)machineID { - NSString *machineId; - - if (self.configData[kMachineIDPlistFileKey] && self.configData[kMachineIDPlistKeyKey]) { - NSDictionary *plist = - [NSDictionary dictionaryWithContentsOfFile:self.configData[kMachineIDPlistFileKey]]; - machineId = plist[self.configData[kMachineIDPlistKeyKey]]; - } + NSString *machineId = self.configState[kMachineIDKey]; + if (machineId) return machineId; - if (self.configData[kMachineIDKey]) { - machineId = self.configData[kMachineIDKey]; - } + NSString *plistPath = self.configState[kMachineIDPlistFileKey]; + NSString *plistKey = self.configState[kMachineIDPlistKeyKey]; - if ([machineId length] == 0) { - machineId = [SNTSystemInfo hardwareUUID]; + if (plistPath && plistKey) { + NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistPath]; + machineId = [plist[plistKey] isKindOfClass:[NSString class]] ? plist[plistKey] : nil; } - return machineId; + return machineId.length ? machineId : [SNTSystemInfo hardwareUUID]; } -- (void)reloadConfigData { - // Load the mobileconfig - self.configData = [self mobileConfig]; - if (!self.configData[kClientModeKey]) { - // Default to Monitor if the config is missing or invalid - self.configData[kClientModeKey] = @(SNTClientModeMonitor); - } - - // Nothing else to do if a sync server is not involved - if (!self.configData[kSyncBaseURLKey]) return; - - // Load the last known sync state - if (![[NSFileManager defaultManager] fileExistsAtPath:kSyncStateFilePath]) return; - NSMutableDictionary *syncState = [self syncState]; - if (!self) return; +#pragma mark Private - // Overwrite or add the sync state to the running config - for (NSString *key in [self syncServerKeys]) { - self.configData[key] = syncState[key]; - } +/// +/// Update the syncState. Triggers a KVO event for all dependents. +/// +- (BOOL)updateSyncStateForKey:(NSString *)key value:(id)value { + NSMutableDictionary *syncState = self.syncState.mutableCopy; + syncState[key] = value; + self.syncState = syncState; [self saveSyncStateToDisk]; + return YES; } -#pragma mark Private - -- (NSMutableDictionary *)syncState { - NSError *error; - NSData *readData = [NSData dataWithContentsOfFile:kSyncStateFilePath - options:NSDataReadingMappedIfSafe - error:&error]; - if (!readData) { - LOGE(@"Could not read sync state file: %@, replacing.", [error localizedDescription]); - [self saveSyncStateToDisk]; - return nil; - } - +/// +/// Read the saved syncState. +/// +- (NSMutableDictionary *)readSyncStateFromDisk { + // Only read the sync state if a sync server is configured. + if (!self.syncBaseURL) return nil; + // Only santad should read this file. + if (geteuid() != 0) return nil; NSMutableDictionary *syncState = - [NSPropertyListSerialization propertyListWithData:readData - options:NSPropertyListMutableContainers - format:NULL - error:&error]; - if (!syncState) { - LOGE(@"Could not parse sync state file: %@, replacing.", [error localizedDescription]); - [self saveSyncStateToDisk]; - return nil; + [NSMutableDictionary dictionaryWithContentsOfFile:kSyncStateFilePath]; + for (NSString *key in syncState.allKeys) { + if (self.syncServerKeyTypes[key] == [NSRegularExpression class]) { + NSString *pattern = [syncState[key] isKindOfClass:[NSString class]] ? syncState[key] : nil; + syncState[key] = [self expressionForPattern:pattern]; + } else if (![syncState[key] isKindOfClass:self.syncServerKeyTypes[key]]) { + syncState[key] = nil; + continue; + } } - + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + WEAKIFY(self); + self.syncStateWatcher = [[SNTFileWatcher alloc] initWithFilePath:kSyncStateFilePath + handler:^(unsigned long data) { + STRONGIFY(self); + [self syncStateFileChanged:data]; + }]; + }); return syncState; } @@ -395,13 +443,14 @@ - (NSMutableDictionary *)syncState { /// Saves the current effective syncState to disk. /// - (void)saveSyncStateToDisk { + // Only save the sync state if a sync server is configured. + if (!self.syncBaseURL) return; // Only santad should write to this file. if (geteuid() != 0) return; - NSMutableDictionary *syncState = - [NSMutableDictionary dictionaryWithCapacity:[self syncServerKeys].count]; - for (NSString *key in [self syncServerKeys]) { - syncState[key] = self.configData[key]; - } + // Either remove + NSMutableDictionary *syncState = self.syncState.mutableCopy; + syncState[kWhitelistRegexKey] = [syncState[kWhitelistRegexKey] pattern]; + syncState[kBlacklistRegexKey] = [syncState[kBlacklistRegexKey] pattern]; [syncState writeToFile:kSyncStateFilePath atomically:YES]; [[NSFileManager defaultManager] setAttributes:@{ NSFilePosixPermissions : @0644 } ofItemAtPath:kSyncStateFilePath error:NULL]; @@ -419,19 +468,18 @@ - (void)syncStateFileChanged:(unsigned long)data { int mask = S_IRWXU | S_IRWXG | S_IRWXO; int desired = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; if (fileStat.st_uid != 0 || fileStat.st_gid != 0 || (fileStat.st_mode & mask) != desired) { - LOGD(@"Sync state file permissions changed, fixing."); + LOGI(@"Sync state file permissions changed, fixing."); chown(cPath, 0, 0); chmod(cPath, desired); } } else { - NSDictionary *syncState = [self syncState]; - for (NSString *key in self.syncServerKeys) { - if (((self.configData[key] && !syncState[key]) || - (!self.configData[key] && syncState[key]) || - (self.configData[key] && ![self.configData[key] isEqualTo:syncState[key]]))) { + NSDictionary *newSyncState = [self readSyncStateFromDisk]; + for (NSString *key in self.syncState) { + if (((self.syncState[key] && !newSyncState[key]) || + (!self.syncState[key] && newSyncState[key]) || + (self.syncState[key] && ![self.syncState[key] isEqualTo:newSyncState[key]]))) { // Ignore sync url and dates - if ([key isEqualToString:kSyncBaseURLKey] || - [key isEqualToString:kRuleSyncLastSuccess] || + if ([key isEqualToString:kRuleSyncLastSuccess] || [key isEqualToString:kFullSyncLastSuccess]) continue; LOGE(@"Sync state file changed, replacing"); [self saveSyncStateToDisk]; @@ -441,25 +489,57 @@ - (void)syncStateFileChanged:(unsigned long)data { } } -/// -/// Returns a config provided by a com.google.santa mobileconfig or an empty -/// NSMutableDictionary object if no config applies. -/// -- (NSMutableDictionary *)mobileConfig { - NSMutableDictionary *config = - [NSMutableDictionary dictionaryWithCapacity:[self mobileConfigKeys].count]; - for (NSString *key in [self mobileConfigKeys]) { - if ([self.defaults objectIsForcedForKey:key]) { - config[key] = [self.defaults objectForKey:key]; - } - } - if (config[kSyncBaseURLKey]) { - for (NSString *key in [self syncServerKeys]) { - if ([key isEqualToString:kSyncBaseURLKey]) continue; - [config removeObjectForKey:key]; +- (void)clearSyncState { + self.syncState = [NSMutableDictionary dictionary]; +} + +#pragma mark Private Defaults Methods + +- (NSRegularExpression *)expressionForPattern:(NSString *)pattern { + if (!pattern) return nil; + if (![pattern hasPrefix:@"^"]) pattern = [@"^" stringByAppendingString:pattern]; + return [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]; +} + +- (NSMutableDictionary *)readForcedConfig { + NSMutableDictionary *forcedConfig = [NSMutableDictionary dictionary]; + for (NSString *key in self.forcedConfigKeyTypes) { + id obj = [self forcedConfigValueForKey:key]; + forcedConfig[key] = [obj isKindOfClass:self.forcedConfigKeyTypes[key]] ? obj : nil; + // Create the regex objects now + if (self.forcedConfigKeyTypes[key] == [NSRegularExpression class]) { + NSString *pattern = [obj isKindOfClass:[NSString class]] ? obj : nil; + forcedConfig[key] = [self expressionForPattern:pattern]; } } - return config; + return forcedConfig; +} + +- (id)forcedConfigValueForKey:(NSString *)key { + id obj = [self.defaults objectForKey:key]; + return [self.defaults objectIsForcedForKey:key inDomain:kMobileConfigDomain] ? obj : nil; +} + +- (void)startWatchingDefaults { + // Only santad should listen. + if (geteuid() != 0) return; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(defaultsChanged:) + name:NSUserDefaultsDidChangeNotification + object:nil]; +} + +- (void)defaultsChanged:(void *)v { + SEL handleChange = @selector(handleChange); + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:handleChange object:nil]; + [self performSelector:handleChange withObject:nil afterDelay:5.0f]; +} + +/// +/// Update the configState. Triggers a KVO event for all dependents. +/// +- (void)handleChange { + self.configState = [self readForcedConfig]; } @end diff --git a/Source/common/SNTXPCControlInterface.h b/Source/common/SNTXPCControlInterface.h index de177cd03..da5c060d1 100644 --- a/Source/common/SNTXPCControlInterface.h +++ b/Source/common/SNTXPCControlInterface.h @@ -75,8 +75,11 @@ - (void)setClientMode:(SNTClientMode)mode reply:(void (^)())reply; - (void)xsrfToken:(void (^)(NSString *))reply; - (void)setXsrfToken:(NSString *)token reply:(void (^)())reply; -- (void)setSyncLastSuccess:(NSDate *)date reply:(void (^)())reply; +- (void)fullSyncLastSuccess:(void (^)(NSDate *))reply; +- (void)setFullSyncLastSuccess:(NSDate *)date reply:(void (^)())reply; +- (void)ruleSyncLastSuccess:(void (^)(NSDate *))reply; - (void)setRuleSyncLastSuccess:(NSDate *)date reply:(void (^)())reply; +- (void)syncCleanRequired:(void (^)(BOOL))reply; - (void)setSyncCleanRequired:(BOOL)cleanReqd reply:(void (^)())reply; - (void)setWhitelistPathRegex:(NSString *)pattern reply:(void (^)())reply; - (void)setBlacklistPathRegex:(NSString *)pattern reply:(void (^)())reply; diff --git a/Source/santactl/Commands/SNTCommandStatus.m b/Source/santactl/Commands/SNTCommandStatus.m index 7b427ba59..4967ffb79 100644 --- a/Source/santactl/Commands/SNTCommandStatus.m +++ b/Source/santactl/Commands/SNTCommandStatus.m @@ -103,15 +103,26 @@ - (void)runWithArguments:(NSArray *)arguments { }]; // Sync status - NSString *syncURLStr = [[[SNTConfigurator configurator] syncBaseURL] absoluteString]; - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - dateFormatter.dateFormat = @"yyyy/MM/dd HH:mm:ss Z"; - NSDate *lastSyncSuccess = [[SNTConfigurator configurator] fullSyncLastSuccess]; - NSString *lastSyncSuccessStr = [dateFormatter stringFromDate:lastSyncSuccess] ?: @"Never"; - NSDate *lastRuleSyncSuccess = [[SNTConfigurator configurator] ruleSyncLastSuccess]; - NSString *lastRuleSyncSuccessStr = - [dateFormatter stringFromDate:lastRuleSyncSuccess] ?: lastSyncSuccessStr; - BOOL syncCleanReqd = [[SNTConfigurator configurator] syncCleanRequired]; + __block NSDate *fullSyncLastSuccess; + dispatch_group_enter(group); + [[self.daemonConn remoteObjectProxy] fullSyncLastSuccess:^(NSDate *date) { + fullSyncLastSuccess = date; + dispatch_group_leave(group); + }]; + + __block NSDate *ruleSyncLastSuccess; + dispatch_group_enter(group); + [[self.daemonConn remoteObjectProxy] ruleSyncLastSuccess:^(NSDate *date) { + ruleSyncLastSuccess = date; + dispatch_group_leave(group); + }]; + + __block BOOL syncCleanReqd = NO; + dispatch_group_enter(group); + [[self.daemonConn remoteObjectProxy] syncCleanRequired:^(BOOL clean) { + syncCleanReqd = clean; + dispatch_group_leave(group); + }]; __block BOOL pushNotifications = NO; if ([[SNTConfigurator configurator] syncBaseURL]) { @@ -136,6 +147,15 @@ - (void)runWithArguments:(NSArray *)arguments { fprintf(stderr, "Failed to retrieve some stats from daemon\n\n"); } + // Format dates + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.dateFormat = @"yyyy/MM/dd HH:mm:ss Z"; + NSString *fullSyncLastSuccessStr = [dateFormatter stringFromDate:fullSyncLastSuccess] ?: @"Never"; + NSString *ruleSyncLastSuccessStr = + [dateFormatter stringFromDate:ruleSyncLastSuccess] ?: fullSyncLastSuccessStr; + + NSString *syncURLStr = [[[SNTConfigurator configurator] syncBaseURL] absoluteString]; + if ([arguments containsObject:@"--json"]) { NSDictionary *stats = @{ @"daemon" : @{ @@ -158,8 +178,8 @@ - (void)runWithArguments:(NSArray *)arguments { @"sync" : @{ @"server" : syncURLStr ?: @"null", @"clean_required" : @(syncCleanReqd), - @"last_successful_full" : lastSyncSuccessStr ?: @"null", - @"last_successful_rule" : lastRuleSyncSuccessStr ?: @"null", + @"last_successful_full" : fullSyncLastSuccessStr ?: @"null", + @"last_successful_rule" : ruleSyncLastSuccessStr ?: @"null", @"push_notifications" : pushNotifications ? @"Connected" : @"Disconnected", @"bundle_scanning" : @(bundlesEnabled) }, @@ -187,8 +207,8 @@ - (void)runWithArguments:(NSArray *)arguments { printf(">>> Sync Info\n"); printf(" %-25s | %s\n", "Sync Server", [syncURLStr UTF8String]); printf(" %-25s | %s\n", "Clean Sync Required", (syncCleanReqd ? "Yes" : "No")); - printf(" %-25s | %s\n", "Last Successful Full Sync", [lastSyncSuccessStr UTF8String]); - printf(" %-25s | %s\n", "Last Successful Rule Sync", [lastRuleSyncSuccessStr UTF8String]); + printf(" %-25s | %s\n", "Last Successful Full Sync", [fullSyncLastSuccessStr UTF8String]); + printf(" %-25s | %s\n", "Last Successful Rule Sync", [ruleSyncLastSuccessStr UTF8String]); printf(" %-25s | %s\n", "Push Notifications", (pushNotifications ? "Connected" : "Disconnected")); printf(" %-25s | %s\n", "Bundle Scanning", (bundlesEnabled ? "Yes" : "No")); diff --git a/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m b/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m index 32ef3f539..5595c0d83 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m @@ -63,7 +63,7 @@ - (BOOL)sync { // Update last sync success dispatch_group_enter(group); - [[self.daemonConn remoteObjectProxy] setSyncLastSuccess:[NSDate date] reply:replyBlock]; + [[self.daemonConn remoteObjectProxy] setFullSyncLastSuccess:[NSDate date] reply:replyBlock]; // Wait for dispatch group dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)); diff --git a/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m b/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m index 96bc650c3..e2dab076a 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m @@ -60,11 +60,17 @@ - (BOOL)sync { dispatch_group_leave(group); }]; + __block BOOL syncClean = NO; + dispatch_group_enter(group); + [[self.daemonConn remoteObjectProxy] syncCleanRequired:^(BOOL clean) { + syncClean = clean; + dispatch_group_leave(group); + }]; + dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC)); // If user requested it or we've never had a successful sync, try from a clean slate. - if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--clean"] || - [[SNTConfigurator configurator] syncCleanRequired]) { + if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--clean"] || syncClean) { LOGD(@"Clean sync requested by user"); requestDict[kRequestCleanSync] = @YES; } diff --git a/Source/santad/SNTApplication.m b/Source/santad/SNTApplication.m index 0bc5d8437..7f13f6e0f 100644 --- a/Source/santad/SNTApplication.m +++ b/Source/santad/SNTApplication.m @@ -16,9 +16,6 @@ @import DiskArbitration; -#include -#include - #import "SNTCommonEnums.h" #import "SNTConfigurator.h" #import "SNTDaemonControlController.h" @@ -28,22 +25,22 @@ #import "SNTEventLog.h" #import "SNTEventTable.h" #import "SNTExecutionController.h" -#import "SNTFileWatcher.h" #import "SNTLogging.h" #import "SNTNotificationQueue.h" #import "SNTRuleTable.h" #import "SNTSyncdQueue.h" #import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" +#import "SNTXPCNotifierInterface.h" @interface SNTApplication () @property DASessionRef diskArbSession; @property SNTDriverManager *driverManager; @property SNTEventLog *eventLog; @property SNTExecutionController *execController; -@property SNTFileWatcher *configFileWatcher; -@property SNTFileWatcher *syncStateWatcher; @property SNTXPCConnection *controlConnection; +@property SNTNotificationQueue *notQueue; +@property pid_t syncdPID; @end @implementation SNTApplication @@ -73,18 +70,37 @@ - (instancetype)init { _eventLog = [[SNTEventLog alloc] init]; - SNTNotificationQueue *notQueue = [[SNTNotificationQueue alloc] init]; + self.notQueue = [[SNTNotificationQueue alloc] init]; SNTSyncdQueue *syncdQueue = [[SNTSyncdQueue alloc] init]; // Restart santactl if it goes down syncdQueue.invalidationHandler = ^{ [self startSyncd]; }; - + + // Listen for actionable config changes. + NSKeyValueObservingOptions bits = (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld); + [[SNTConfigurator configurator] addObserver:self + forKeyPath:@"clientMode" + options:bits + context:NULL]; + [[SNTConfigurator configurator] addObserver:self + forKeyPath:@"syncBaseURL" + options:bits + context:NULL]; + [[SNTConfigurator configurator] addObserver:self + forKeyPath:@"whitelistPathRegex" + options:bits + context:NULL]; + [[SNTConfigurator configurator] addObserver:self + forKeyPath:@"blacklistPathRegex" + options:bits + context:NULL]; + // Establish XPC listener for Santa and santactl connections SNTDaemonControlController *dc = [[SNTDaemonControlController alloc] initWithDriverManager:_driverManager - notificationQueue:notQueue + notificationQueue:self.notQueue syncdQueue:syncdQueue eventLog:_eventLog]; @@ -94,43 +110,11 @@ - (instancetype)init { _controlConnection.exportedObject = dc; [_controlConnection resume]; - __block SNTClientMode origMode = [[SNTConfigurator configurator] clientMode]; - __block NSURL *origSyncURL = [[SNTConfigurator configurator] syncBaseURL]; - _configFileWatcher = [[SNTFileWatcher alloc] initWithFilePath:kMobileConfigFilePath - handler:^(unsigned long data) { - - LOGD(@"Mobileconfig changed, reloading."); - [[SNTConfigurator configurator] reloadConfigData]; - - // Flush cache if client just went into lockdown. - SNTClientMode newMode = [[SNTConfigurator configurator] clientMode]; - if (origMode != newMode) { - origMode = newMode; - if (newMode == SNTClientModeLockdown) { - LOGI(@"Changed client mode, flushing cache."); - [self.driverManager flushCacheNonRootOnly:NO]; - } - } - - // Start santactl if the syncBaseURL changed from nil --> somthing - NSURL *syncURL = [[SNTConfigurator configurator] syncBaseURL]; - if (!origSyncURL && syncURL) { - origSyncURL = syncURL; - LOGI(@"SyncBaseURL added, starting santactl."); - [self startSyncd]; - } - }]; - - _syncStateWatcher = [[SNTFileWatcher alloc] initWithFilePath:kSyncStateFilePath - handler:^(unsigned long data) { - [[SNTConfigurator configurator] syncStateFileChanged:data]; - }]; - // Initialize the binary checker object _execController = [[SNTExecutionController alloc] initWithDriverManager:_driverManager ruleTable:ruleTable eventTable:eventTable - notifierQueue:notQueue + notifierQueue:self.notQueue syncdQueue:syncdQueue eventLog:_eventLog]; // Start up santactl as a daemon if a sync server exists. @@ -142,18 +126,6 @@ - (instancetype)init { return self; } -- (void)startSyncd { - if (![[SNTConfigurator configurator] syncBaseURL]) return; - - if (fork() == 0) { - // Ensure we have no privileges - if (!DropRootPrivileges()) { - _exit(EPERM); - } - _exit(execl(kSantaCtlPath, kSantaCtlPath, "sync", "--daemon", "--syslog", NULL)); - } -} - - (void)start { LOGI(@"Connected to driver, activating."); @@ -270,4 +242,76 @@ void diskDisappearedCallback(DADiskRef disk, void *context) { [app.driverManager flushCacheNonRootOnly:YES]; } +- (void)startSyncd { + if (![[SNTConfigurator configurator] syncBaseURL]) return; + [self stopSyncd]; + self.syncdPID = fork(); + if (self.syncdPID == -1) { + LOGI(@"Failed to fork"); + self.syncdPID = 0; + } else if (self.syncdPID == 0) { + // Ensure we have no privileges + if (!DropRootPrivileges()) { + _exit(EPERM); + } + _exit(execl(kSantaCtlPath, kSantaCtlPath, "sync", "--daemon", "--syslog", NULL)); + } + LOGI(@"santactl started with pid: %i", self.syncdPID); +} + +- (void)stopSyncd { + if (!self.syncdPID) return; + int ret = kill(self.syncdPID, SIGKILL); + LOGD(@"kill(%i, 9) = %i", self.syncdPID, ret); + self.syncdPID = 0; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if ([keyPath isEqualToString:@"clientMode"]) { + SNTClientMode new = + [change[@"new"] isKindOfClass:[NSNumber class]] ? [change[@"new"] longLongValue] : 0; + SNTClientMode old = + [change[@"old"] isKindOfClass:[NSNumber class]] ? [change[@"old"] longLongValue] : 0; + if (new != old) [self clientModeDidChange:new]; + } else if ([keyPath isEqualToString:@"syncBaseURL"]) { + NSURL *new = [change[@"new"] isKindOfClass:[NSURL class]] ? change[@"new"] : nil; + NSURL *old = [change[@"old"] isKindOfClass:[NSURL class]] ? change[@"old"] : nil; + if (!new && !old) return; + if (![new.absoluteString isEqualToString:old.absoluteString]) [self syncBaseURLDidChange:new]; + } else if ([keyPath isEqualToString:@"whitelistPathRegex"] || + [keyPath isEqualToString:@"blacklistPathRegex"]) { + NSRegularExpression *new = + [change[@"new"] isKindOfClass:[NSRegularExpression class]] ? change[@"new"] : nil; + NSRegularExpression *old = + [change[@"old"] isKindOfClass:[NSRegularExpression class]] ? change[@"old"] : nil; + if (!new && !old) return; + if (![new.pattern isEqualToString:old.pattern]) { + LOGI(@"Changed [white|black]list regex, flushing cache"); + [self.driverManager flushCacheNonRootOnly:NO]; + } + } +} + +- (void)clientModeDidChange:(SNTClientMode)clientMode { + if (clientMode == SNTClientModeLockdown) { + LOGI(@"Changed client mode, flushing cache."); + [self.driverManager flushCacheNonRootOnly:NO]; + } + [[self.notQueue.notifierConnection remoteObjectProxy] postClientModeNotification:clientMode]; +} + +- (void)syncBaseURLDidChange:(NSURL *)syncBaseURL { + if (syncBaseURL) { + LOGI(@"Starting santactl with new SyncBaseURL: %@", syncBaseURL); + [self startSyncd]; + } else { + LOGI(@"SyncBaseURL removed, killing santactl pid: %i", self.syncdPID); + [self stopSyncd]; + [[SNTConfigurator configurator] clearSyncState]; + } +} + @end diff --git a/Source/santad/SNTDaemonControlController.m b/Source/santad/SNTDaemonControlController.m index 78a93988b..0ca6fc738 100644 --- a/Source/santad/SNTDaemonControlController.m +++ b/Source/santad/SNTDaemonControlController.m @@ -146,15 +146,7 @@ - (void)clientMode:(void (^)(SNTClientMode))reply { } - (void)setClientMode:(SNTClientMode)mode reply:(void (^)())reply { - if ([[SNTConfigurator configurator] clientMode] != mode) { - // Flush cache if client just went into lockdown. - if (mode == SNTClientModeLockdown) { - LOGI(@"Changed client mode, flushing cache."); - [self.driverManager flushCacheNonRootOnly:NO]; - } - [[SNTConfigurator configurator] setClientMode:mode]; - [[self.notQueue.notifierConnection remoteObjectProxy] postClientModeNotification:mode]; - } + [[SNTConfigurator configurator] setSyncServerClientMode:mode]; reply(); } @@ -167,16 +159,28 @@ - (void)setXsrfToken:(NSString *)token reply:(void (^)())reply { reply(); } -- (void)setSyncLastSuccess:(NSDate *)date reply:(void (^)())reply { +- (void)fullSyncLastSuccess:(void (^)(NSDate *))reply { + reply([[SNTConfigurator configurator] fullSyncLastSuccess]); +} + +- (void)setFullSyncLastSuccess:(NSDate *)date reply:(void (^)())reply { [[SNTConfigurator configurator] setFullSyncLastSuccess:date]; reply(); } +- (void)ruleSyncLastSuccess:(void (^)(NSDate *))reply { + reply([[SNTConfigurator configurator] ruleSyncLastSuccess]); +} + - (void)setRuleSyncLastSuccess:(NSDate *)date reply:(void (^)())reply { [[SNTConfigurator configurator] setRuleSyncLastSuccess:date]; reply(); } +- (void)syncCleanRequired:(void (^)(BOOL))reply { + reply([[SNTConfigurator configurator] syncCleanRequired]); +} + - (void)setSyncCleanRequired:(BOOL)cleanReqd reply:(void (^)())reply { [[SNTConfigurator configurator] setSyncCleanRequired:cleanReqd]; reply(); @@ -186,9 +190,7 @@ - (void)setWhitelistPathRegex:(NSString *)pattern reply:(void (^)())reply { NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]; - [[SNTConfigurator configurator] setWhitelistPathRegex:re]; - LOGI(@"Received new whitelist regex, flushing cache"); - [self.driverManager flushCacheNonRootOnly:NO]; + [[SNTConfigurator configurator] setSyncServerWhitelistPathRegex:re]; reply(); } @@ -196,9 +198,7 @@ - (void)setBlacklistPathRegex:(NSString *)pattern reply:(void (^)())reply { NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]; - [[SNTConfigurator configurator] setBlacklistPathRegex:re]; - LOGI(@"Received new blacklist regex, flushing cache"); - [self.driverManager flushCacheNonRootOnly:NO]; + [[SNTConfigurator configurator] setSyncServerBlacklistPathRegex:re]; reply(); } From c1bfbac2fefcc42e6676e31f2a3200903a833cac Mon Sep 17 00:00:00 2001 From: johnl Date: Tue, 13 Feb 2018 17:06:28 +0100 Subject: [PATCH 06/25] Various small fixes to README.md (#237) * Various small fixes to README.md * Apply changes --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 056e11cea..43aab8afd 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ execution decisions based on the contents of a SQLite database, a GUI agent that notifies the user in case of a block decision and a command-line utility for managing the system and synchronizing the database with a server. -Santa is not yet a 1.0. We're writing more tests, fixing bugs, working on TODOs +Santa is not yet at 1.0. We're writing more tests, fixing bugs, working on TODOs and finishing up a security audit. It is named Santa because it keeps track of binaries that are naughty or nice. @@ -29,21 +29,21 @@ The Santa docs are stored in the [Docs](https://github.com/google/santa/blob/mas Admin-Related Features ======== -* Multiple modes: In the default MONITOR mode, all binaries except +* Multiple modes: In the default MONITOR mode, all binaries except those marked as blacklisted will be allowed to run, whilst being logged and recorded in the events database. In LOCKDOWN mode, only whitelisted binaries are allowed to run. * Event logging: When the kext is loaded, all binary launches are logged. When in either mode, all unknown or denied binaries are stored in the database to enable later aggregation. -* Certificate-based rules, with override levels: Instead of relying on a binaries hash (or 'fingerprint'), executables can be whitelisted/blacklisted by their signing +* Certificate-based rules, with override levels: Instead of relying on a binary's hash (or 'fingerprint'), executables can be whitelisted/blacklisted by their signing certificate. You can therefore trust/block all binaries by a given publisher that were signed with that cert across version updates. A binary can only be whitelisted by its certificate if its signature validates -correctly, but a rule for a binaries fingerprint will override a decision for a +correctly, but a rule for a binary's fingerprint will override a decision for a certificate; i.e. you can whitelist a certificate while blacklisting a binary signed with that certificate, or vice-versa. -* Path-based rules (via NSRegularExpression/ICU): This allows a similar feature as Managed Client for OS X's (the precursor to configuration profiles, which used the same implementation mechanism) Application Launch Restrictions via the mcxalr binary. This implementation carries the added benefit of being configurable via regex, and doesn't rely on LaunchServices. As detailed in the wiki, when evaluating rules this holds the lowest precendence. +* Path-based rules (via NSRegularExpression/ICU): This allows a similar feature to that found in Managed Client (the precursor to configuration profiles, which used the same implementation mechanism), Application Launch Restrictions via the mcxalr binary. This implementation carries the added benefit of being configurable via regex, and not relying on LaunchServices. As detailed in the wiki, when evaluating rules this holds the lowest precendence. * Failsafe cert rules: You cannot put in a deny rule that would block the certificate used to sign launchd, a.k.a. pid 1, and therefore all components used in macOS. The binaries in every OS update (and in some cases entire new versions) are therefore auto-whitelisted. This does not affect binaries from Apple's App Store, which use various certs that change regularly for common apps. Likewise, you cannot blacklist Santa itself, and Santa uses a distinct separate cert than other Google apps. @@ -54,7 +54,7 @@ Santa is written with the intention of helping protect users from themselves. People often download malware and trust it, giving the malware credentials, or allowing unknown software to exfiltrate more data about your system. As a centrally managed component, Santa can help stop the spread of malware among a -larger fleet of machines. Independently, Santa can aid in analyzing what is +large fleet of machines. Independently, Santa can aid in analyzing what is running on your computer. Santa is part of a defense-in-depth strategy, and you should continue to protect @@ -62,7 +62,6 @@ hosts in whatever other ways you see fit. Get Help ======== - If you have questions or otherwise need help getting started, the [santa-dev](https://groups.google.com/forum/#!forum/santa-dev) group is a great place. Please consult the [wiki](https://github.com/google/santa/wiki) and [issues](https://github.com/google/santa/issues) as well. @@ -84,7 +83,7 @@ continue to work across OS versions. Known Issues ============ -Santa is not yet a 1.0 and we have some known issues to be aware of: +Santa is not yet at 1.0 and we have some known issues to be aware of: * Santa only blocks execution (execve and variants), it doesn't protect against dynamic libraries loaded with dlopen, libraries on disk that have been replaced, or From cce43829ebd568cbb1c9f5ef2fc6b1bacc08786e Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Fri, 16 Feb 2018 14:35:52 -0500 Subject: [PATCH 07/25] use MOLFCMClient v1.5 (#238) --- Podfile.lock | 6 +++--- Source/santactl/Commands/sync/SNTCommandSyncManager.m | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 551627fbc..ff6f38840 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -7,7 +7,7 @@ PODS: - MOLCertificate (1.5) - MOLCodesignChecker (1.5): - MOLCertificate (~> 1.3) - - MOLFCMClient (1.3): + - MOLFCMClient (1.5): - MOLAuthenticatingURLSession (~> 2.1) - OCMock (3.4) @@ -24,9 +24,9 @@ SPEC CHECKSUMS: MOLAuthenticatingURLSession: 5a5e31eb73248c3e92c79b9a285f031194e8404c MOLCertificate: c39cae866d24d36fbc78032affff83d401b5384a MOLCodesignChecker: fc9c64147811d7b0d0739127003e0630dff9213a - MOLFCMClient: 13d8b42db9d750e772f09cc38fc453922fece09f + MOLFCMClient: 88debb79f8c0454c3dd4f6514c2453e57a963c08 OCMock: 35ae71d6a8fcc1b59434d561d1520b9dd4f15765 PODFILE CHECKSUM: acd378b3727c923d912e09812da344f7375c14fe -COCOAPODS: 1.3.1 +COCOAPODS: 1.4.0 diff --git a/Source/santactl/Commands/sync/SNTCommandSyncManager.m b/Source/santactl/Commands/sync/SNTCommandSyncManager.m index 21c9abfc3..7f7a36bc1 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncManager.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncManager.m @@ -178,7 +178,7 @@ - (void)postBundleEventToSyncServer:(SNTStoredEvent *)event } - (void)isFCMListening:(void (^)(BOOL))reply { - reply((self.FCMClient.FCMToken != nil)); + reply(self.FCMClient.isConnected); } #pragma mark push notification methods @@ -205,16 +205,17 @@ - (void)listenForPushNotificationsWithSyncState:(SNTCommandSyncState *)syncState [self processFCMMessage:message withMachineID:machineID]; }]; - self.FCMClient.connectionErrorHandler = ^(NSError *error) { + self.FCMClient.connectionErrorHandler = ^(NSHTTPURLResponse *response, NSError *error) { STRONGIFY(self); - LOGE(@"FCM connection error: %@", error); + if (response) LOGE(@"FCM fatal response: %@", response); + if (error) LOGE(@"FCM fatal error: %@", error); [self.FCMClient disconnect]; self.FCMClient = nil; [self rescheduleTimerQueue:self.fullSyncTimer secondsFromNow:kDefaultFullSyncInterval]; }; self.FCMClient.loggingBlock = ^(NSString *log) { - LOGD(@"%@", log); + LOGD(@"FCMClient: %@", log); }; [self.FCMClient connect]; From d4ba4b082f4c1c3fbc1c67971f6f8b427bfaaab4 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Thu, 22 Feb 2018 14:41:47 -0500 Subject: [PATCH 08/25] codesign check: verify all architectures (#239) * fileinfo rule: don't use certs that have codesigning errors * pods: MOLCodesignChecker --> 1.8 --- Podfile.lock | 10 +++++----- Source/santactl/Commands/SNTCommandFileInfo.m | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index ff6f38840..1270f38f6 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -4,9 +4,9 @@ PODS: - FMDB/standard (2.6.2) - MOLAuthenticatingURLSession (2.2): - MOLCertificate (~> 1.5) - - MOLCertificate (1.5) - - MOLCodesignChecker (1.5): - - MOLCertificate (~> 1.3) + - MOLCertificate (1.7) + - MOLCodesignChecker (1.8): + - MOLCertificate (~> 1.7) - MOLFCMClient (1.5): - MOLAuthenticatingURLSession (~> 2.1) - OCMock (3.4) @@ -22,8 +22,8 @@ DEPENDENCIES: SPEC CHECKSUMS: FMDB: 854a0341b4726e53276f2a8996f06f1b80f9259a MOLAuthenticatingURLSession: 5a5e31eb73248c3e92c79b9a285f031194e8404c - MOLCertificate: c39cae866d24d36fbc78032affff83d401b5384a - MOLCodesignChecker: fc9c64147811d7b0d0739127003e0630dff9213a + MOLCertificate: 1cdb264405631b4bbdcf4cde7627469290cf1187 + MOLCodesignChecker: 93460b82eb41b671c1c8eff9fc904d0d3d149e16 MOLFCMClient: 88debb79f8c0454c3dd4f6514c2453e57a963c08 OCMock: 35ae71d6a8fcc1b59434d561d1520b9dd4f15765 diff --git a/Source/santactl/Commands/SNTCommandFileInfo.m b/Source/santactl/Commands/SNTCommandFileInfo.m index 602c2c7ed..58d0acd57 100644 --- a/Source/santactl/Commands/SNTCommandFileInfo.m +++ b/Source/santactl/Commands/SNTCommandFileInfo.m @@ -345,10 +345,11 @@ - (SNTAttributeBlock)rule { dispatch_once(&token, ^{ [cmd.daemonConn resume]; }); __block SNTEventState state; dispatch_semaphore_t sema = dispatch_semaphore_create(0); - MOLCodesignChecker *csc = [fileInfo codesignCheckerWithError:NULL]; + NSError *err; + MOLCodesignChecker *csc = [fileInfo codesignCheckerWithError:&err]; [[cmd.daemonConn remoteObjectProxy] decisionForFilePath:fileInfo.path fileSHA256:fileInfo.SHA256 - certificateSHA256:csc.leafCertificate.SHA256 + certificateSHA256:err ? nil : csc.leafCertificate.SHA256 reply:^(SNTEventState s) { state = s; dispatch_semaphore_signal(sema); From 9f6ccf092ad94505d0b1e479dd914bbfd52a974d Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Mon, 26 Feb 2018 10:51:44 -0500 Subject: [PATCH 09/25] code cleanup (#241) --- Source/common/SNTConfigurator.m | 133 +++++++++++++++++------------ Source/common/SNTKernelCommon.h | 2 +- Source/santad/SNTApplication.m | 55 ++++++------ Source/santad/SNTPolicyProcessor.m | 4 +- 4 files changed, 110 insertions(+), 84 deletions(-) diff --git a/Source/common/SNTConfigurator.m b/Source/common/SNTConfigurator.m index d8c14082a..4768eace8 100644 --- a/Source/common/SNTConfigurator.m +++ b/Source/common/SNTConfigurator.m @@ -86,40 +86,45 @@ @implementation SNTConfigurator - (instancetype)init { self = [super init]; if (self) { + Class number = [NSNumber class]; + Class re = [NSRegularExpression class]; + Class date = [NSDate class]; + Class string = [NSString class]; + Class data = [NSData class]; _syncServerKeyTypes = @{ - kClientModeKey : [NSNumber class], - kWhitelistRegexKey : [NSRegularExpression class], - kBlacklistRegexKey : [NSRegularExpression class], - kFullSyncLastSuccess : [NSDate class], - kRuleSyncLastSuccess : [NSDate class], - kSyncCleanRequired : [NSNumber class] + kClientModeKey : number, + kWhitelistRegexKey : re, + kBlacklistRegexKey : re, + kFullSyncLastSuccess : date, + kRuleSyncLastSuccess : date, + kSyncCleanRequired : number }; _forcedConfigKeyTypes = @{ - kClientModeKey : [NSNumber class], - kFileChangesRegexKey : [NSRegularExpression class], - kWhitelistRegexKey : [NSRegularExpression class], - kBlacklistRegexKey : [NSRegularExpression class], - kEnablePageZeroProtectionKey : [NSNumber class], - kMoreInfoURLKey : [NSString class], - kEventDetailURLKey : [NSString class], - kEventDetailTextKey : [NSString class], - kUnknownBlockMessage : [NSString class], - kBannedBlockMessage : [NSString class], - kModeNotificationMonitor : [NSString class], - kModeNotificationLockdown : [NSString class], - kSyncBaseURLKey : [NSString class], - kClientAuthCertificateFileKey : [NSString class], - kClientAuthCertificatePasswordKey : [NSString class], - kClientAuthCertificateCNKey : [NSString class], - kClientAuthCertificateIssuerKey : [NSString class], - kServerAuthRootsDataKey : [NSData class], - kServerAuthRootsFileKey : [NSString class], - kMachineOwnerKey : [NSString class], - kMachineIDKey : [NSString class], - kMachineOwnerPlistFileKey : [NSString class], - kMachineOwnerPlistKeyKey : [NSString class], - kMachineIDPlistFileKey : [NSString class], - kMachineIDPlistKeyKey : [NSString class], + kClientModeKey : number, + kFileChangesRegexKey : re, + kWhitelistRegexKey : re, + kBlacklistRegexKey : re, + kEnablePageZeroProtectionKey : number, + kMoreInfoURLKey : string, + kEventDetailURLKey : string, + kEventDetailTextKey : string, + kUnknownBlockMessage : string, + kBannedBlockMessage : string, + kModeNotificationMonitor : string, + kModeNotificationLockdown : string, + kSyncBaseURLKey : string, + kClientAuthCertificateFileKey : string, + kClientAuthCertificatePasswordKey : string, + kClientAuthCertificateCNKey : string, + kClientAuthCertificateIssuerKey : string, + kServerAuthRootsDataKey : data, + kServerAuthRootsFileKey : string, + kMachineOwnerKey : string, + kMachineIDKey : string, + kMachineOwnerPlistFileKey : string, + kMachineOwnerPlistKeyKey : string, + kMachineIDPlistFileKey : string, + kMachineIDPlistKeyKey : string, }; _defaults = [NSUserDefaults standardUserDefaults]; [_defaults addSuiteNamed:@"com.google.santa"]; @@ -141,94 +146,112 @@ + (instancetype)configurator { return sharedConfigurator; } ++ (NSSet *)syncAndConfigStateSet { + static NSSet *set; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + set = [[self configStateSet] setByAddingObject:NSStringFromSelector(@selector(syncState))]; + }); + return set; +} + ++ (NSSet *)configStateSet { + static NSSet *set; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + set = [NSSet setWithObject:NSStringFromSelector(@selector(configState))]; + }); + return set; +} + #pragma mark KVO Dependencies + (NSSet *)keyPathsForValuesAffectingClientMode { - return [NSSet setWithObjects:@"syncState", @"configState", nil]; + return [self syncAndConfigStateSet]; } + (NSSet *)keyPathsForValuesAffectingWhitelistPathRegex { - return [NSSet setWithObjects:@"syncState", @"configState", nil]; + return [self syncAndConfigStateSet]; } + (NSSet *)keyPathsForValuesAffectingBlacklistPathRegex { - return [NSSet setWithObjects:@"syncState", @"configState", nil]; + return [self syncAndConfigStateSet]; } + (NSSet *)keyPathsForValuesAffectingFileChangesRegex { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingSyncBaseURL { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingEnablePageZeroProtection { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingMoreInfoURL { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingEventDetailURL { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingEventDetailText { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingUnknownBlockMessage { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingBannedBlockMessage { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingModeNotificationMonitor { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingModeNotificationLockdown { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateFile { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificatePassword { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateCn { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateIssuer { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingSyncServerAuthRootsData { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingSyncServerAuthRootsFile { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingFullSyncLastSuccess { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingMachineOwner { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } + (NSSet *)keyPathsForValuesAffectingMachineID { - return [NSSet setWithObject:@"configState"]; + return [self configStateSet]; } #pragma mark Public Interface @@ -469,8 +492,8 @@ - (void)syncStateFileChanged:(unsigned long)data { int desired = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; if (fileStat.st_uid != 0 || fileStat.st_gid != 0 || (fileStat.st_mode & mask) != desired) { LOGI(@"Sync state file permissions changed, fixing."); - chown(cPath, 0, 0); - chmod(cPath, desired); + if (chown(cPath, 0, 0) != 0) LOGE(@"Failed to chown(%s, 0, 0)", cPath); + if (chmod(cPath, desired) != 0) LOGE(@"Failed to chmod(%s, %i)", cPath, desired); } } else { NSDictionary *newSyncState = [self readSyncStateFromDisk]; diff --git a/Source/common/SNTKernelCommon.h b/Source/common/SNTKernelCommon.h index a127eec7f..793288200 100644 --- a/Source/common/SNTKernelCommon.h +++ b/Source/common/SNTKernelCommon.h @@ -66,7 +66,7 @@ typedef enum { ACTION_RESPOND_DENY = 21, ACTION_RESPOND_TOOLONG = 22, ACTION_RESPOND_ACK = 23, - + // NOTIFY ACTION_NOTIFY_EXEC = 30, ACTION_NOTIFY_WRITE = 31, diff --git a/Source/santad/SNTApplication.m b/Source/santad/SNTApplication.m index 7f13f6e0f..a5e2fbc68 100644 --- a/Source/santad/SNTApplication.m +++ b/Source/santad/SNTApplication.m @@ -80,22 +80,23 @@ - (instancetype)init { // Listen for actionable config changes. NSKeyValueObservingOptions bits = (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld); - [[SNTConfigurator configurator] addObserver:self - forKeyPath:@"clientMode" - options:bits - context:NULL]; - [[SNTConfigurator configurator] addObserver:self - forKeyPath:@"syncBaseURL" - options:bits - context:NULL]; - [[SNTConfigurator configurator] addObserver:self - forKeyPath:@"whitelistPathRegex" - options:bits - context:NULL]; - [[SNTConfigurator configurator] addObserver:self - forKeyPath:@"blacklistPathRegex" - options:bits - context:NULL]; + SNTConfigurator *configurator = [SNTConfigurator configurator]; + [configurator addObserver:self + forKeyPath:NSStringFromSelector(@selector(clientMode)) + options:bits + context:NULL]; + [configurator addObserver:self + forKeyPath:NSStringFromSelector(@selector(syncBaseURL)) + options:bits + context:NULL]; + [configurator addObserver:self + forKeyPath:NSStringFromSelector(@selector(whitelistPathRegex)) + options:bits + context:NULL]; + [configurator addObserver:self + forKeyPath:NSStringFromSelector(@selector(blacklistPathRegex)) + options:bits + context:NULL]; // Establish XPC listener for Santa and santactl connections SNTDaemonControlController *dc = @@ -270,23 +271,25 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - if ([keyPath isEqualToString:@"clientMode"]) { + NSString *newKey = NSKeyValueChangeNewKey; + NSString *oldKey = NSKeyValueChangeOldKey; + if ([keyPath isEqualToString:NSStringFromSelector(@selector(clientMode))]) { SNTClientMode new = - [change[@"new"] isKindOfClass:[NSNumber class]] ? [change[@"new"] longLongValue] : 0; + [change[newKey] isKindOfClass:[NSNumber class]] ? [change[newKey] longLongValue] : 0; SNTClientMode old = - [change[@"old"] isKindOfClass:[NSNumber class]] ? [change[@"old"] longLongValue] : 0; + [change[oldKey] isKindOfClass:[NSNumber class]] ? [change[oldKey] longLongValue] : 0; if (new != old) [self clientModeDidChange:new]; - } else if ([keyPath isEqualToString:@"syncBaseURL"]) { - NSURL *new = [change[@"new"] isKindOfClass:[NSURL class]] ? change[@"new"] : nil; - NSURL *old = [change[@"old"] isKindOfClass:[NSURL class]] ? change[@"old"] : nil; + } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(syncBaseURL))]) { + NSURL *new = [change[newKey] isKindOfClass:[NSURL class]] ? change[newKey] : nil; + NSURL *old = [change[oldKey] isKindOfClass:[NSURL class]] ? change[oldKey] : nil; if (!new && !old) return; if (![new.absoluteString isEqualToString:old.absoluteString]) [self syncBaseURLDidChange:new]; - } else if ([keyPath isEqualToString:@"whitelistPathRegex"] || - [keyPath isEqualToString:@"blacklistPathRegex"]) { + } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(whitelistPathRegex))] || + [keyPath isEqualToString:NSStringFromSelector(@selector(blacklistPathRegex))]) { NSRegularExpression *new = - [change[@"new"] isKindOfClass:[NSRegularExpression class]] ? change[@"new"] : nil; + [change[newKey] isKindOfClass:[NSRegularExpression class]] ? change[newKey] : nil; NSRegularExpression *old = - [change[@"old"] isKindOfClass:[NSRegularExpression class]] ? change[@"old"] : nil; + [change[oldKey] isKindOfClass:[NSRegularExpression class]] ? change[oldKey] : nil; if (!new && !old) return; if (![new.pattern isEqualToString:old.pattern]) { LOGI(@"Changed [white|black]list regex, flushing cache"); diff --git a/Source/santad/SNTPolicyProcessor.m b/Source/santad/SNTPolicyProcessor.m index 1171a9035..0b6c30432 100644 --- a/Source/santad/SNTPolicyProcessor.m +++ b/Source/santad/SNTPolicyProcessor.m @@ -133,7 +133,7 @@ - (SNTCachedDecision *)decisionForFilePath:(NSString *)filePath /// - (NSString *)fileIsScopeWhitelisted:(SNTFileInfo *)fi { if (!fi) return nil; - + // Determine if file is within a whitelisted path NSRegularExpression *re = [[SNTConfigurator configurator] whitelistPathRegex]; if ([re numberOfMatchesInString:fi.path options:0 range:NSMakeRange(0, fi.path.length)]) { @@ -150,7 +150,7 @@ - (NSString *)fileIsScopeWhitelisted:(SNTFileInfo *)fi { - (NSString *)fileIsScopeBlacklisted:(SNTFileInfo *)fi { if (!fi) return nil; - + NSRegularExpression *re = [[SNTConfigurator configurator] blacklistPathRegex]; if ([re numberOfMatchesInString:fi.path options:0 range:NSMakeRange(0, fi.path.length)]) { return @"Blacklist Regex"; From 40e6c6aa9205f6464ae3b6fa55e60a721a464383 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Wed, 7 Mar 2018 17:35:02 -0500 Subject: [PATCH 10/25] sync-state: perform sync-state operations on a serial q (#242) * sync-state serial * delete it --- Santa.xcodeproj/project.pbxproj | 16 --- Source/common/SNTConfigurator.m | 94 ++++++----------- Source/common/SNTFileWatcher.h | 35 ------- Source/common/SNTFileWatcher.m | 94 ----------------- Tests/LogicTests/SNTFileWatcherTest.m | 140 -------------------------- 5 files changed, 32 insertions(+), 347 deletions(-) delete mode 100644 Source/common/SNTFileWatcher.h delete mode 100644 Source/common/SNTFileWatcher.m delete mode 100644 Tests/LogicTests/SNTFileWatcherTest.m diff --git a/Santa.xcodeproj/project.pbxproj b/Santa.xcodeproj/project.pbxproj index a552df836..3bdf01751 100644 --- a/Santa.xcodeproj/project.pbxproj +++ b/Santa.xcodeproj/project.pbxproj @@ -148,9 +148,6 @@ 0DEA5F7B1CF64C9200704398 /* sync_ruledownload_batch2.json in Resources */ = {isa = PBXBuildFile; fileRef = 0DEA5F781CF64C8B00704398 /* sync_ruledownload_batch2.json */; }; 0DEA5F7D1CF64EB600704398 /* SNTCommandSyncRuleDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D0A1EC2191998C900B8450F /* SNTCommandSyncRuleDownload.m */; }; 0DEFB7C01ACB28B000B92AAE /* SNTCommandSyncConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7BF1ACB28B000B92AAE /* SNTCommandSyncConstants.m */; }; - 0DEFB7C41ACDD80100B92AAE /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; - 0DEFB7C61ACDE5F600B92AAE /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; - 0DEFB7C81ACF0BFE00B92AAE /* SNTFileWatcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C71ACF0BFE00B92AAE /* SNTFileWatcherTest.m */; }; 0DF395641AB76A7900CBC520 /* NSData+Zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DF395631AB76A7900CBC520 /* NSData+Zlib.m */; }; 0DF395661AB76ABC00CBC520 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DF395651AB76ABC00CBC520 /* libz.dylib */; }; 168A4E09A2A5E0B7DF8A2F1A /* libPods-santad.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C11A10A5D6E112788769CF70 /* libPods-santad.a */; }; @@ -171,8 +168,6 @@ C76614EC1D142D3C00D150C1 /* SNTCommandCheckCache.m in Sources */ = {isa = PBXBuildFile; fileRef = C76614EB1D142D3C00D150C1 /* SNTCommandCheckCache.m */; }; C776A1071DEE160500A56616 /* SNTCommandSyncManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C776A1061DEE160500A56616 /* SNTCommandSyncManager.m */; }; C78227631E1C3C7D006EB2D6 /* santabs.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = C78227541E1C3C58006EB2D6 /* santabs.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - C7943FE92028B855008D4F76 /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; - C7943FEA2028C4F7008D4F76 /* SNTFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */; }; C795ED901D80A5BE007CFF42 /* SNTPolicyProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */; }; C795ED911D80B66B007CFF42 /* SNTPolicyProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */; }; C79A23581E23F7E80037AFA8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C79A23561E23F7E80037AFA8 /* main.m */; }; @@ -416,9 +411,6 @@ 0DEA5F781CF64C8B00704398 /* sync_ruledownload_batch2.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = sync_ruledownload_batch2.json; sourceTree = ""; }; 0DEFB7BF1ACB28B000B92AAE /* SNTCommandSyncConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandSyncConstants.m; sourceTree = ""; }; 0DEFB7C11ACB28BC00B92AAE /* SNTCommandSyncConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncConstants.h; sourceTree = ""; }; - 0DEFB7C21ACDD80100B92AAE /* SNTFileWatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTFileWatcher.h; sourceTree = ""; }; - 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTFileWatcher.m; sourceTree = ""; }; - 0DEFB7C71ACF0BFE00B92AAE /* SNTFileWatcherTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTFileWatcherTest.m; sourceTree = ""; }; 0DF395621AB76A7900CBC520 /* NSData+Zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Zlib.h"; sourceTree = ""; }; 0DF395631AB76A7900CBC520 /* NSData+Zlib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Zlib.m"; sourceTree = ""; }; 0DF395651AB76ABC00CBC520 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; @@ -540,7 +532,6 @@ 0D41DAD31A7C28C800A890FE /* SNTEventTableTest.m */, 0DD0D490194F9947005F27EB /* SNTExecutionControllerTest.m */, 0DD0D48E194F78F8005F27EB /* SNTFileInfoTest.m */, - 0DEFB7C71ACF0BFE00B92AAE /* SNTFileWatcherTest.m */, 0DB537861AFD36EB00487F92 /* SNTRuleTableTest.m */, 0D3AFBE618FB32CB0087BCEE /* SNTXPCConnectionTest.m */, ); @@ -733,8 +724,6 @@ 0D10BE851A0AABD600C0C944 /* SNTDropRootPrivs.m */, 0DCD6040190ACCB8006B445C /* SNTFileInfo.h */, 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */, - 0DEFB7C21ACDD80100B92AAE /* SNTFileWatcher.h */, - 0DEFB7C31ACDD80100B92AAE /* SNTFileWatcher.m */, 0D28E5E31926AFE400280F87 /* SNTKernelCommon.h */, 0D28E5E119269B3600280F87 /* SNTLogging.h */, 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */, @@ -1466,10 +1455,8 @@ 0DCD605819115E57006B445C /* SNTXPCControlInterface.m in Sources */, 0D202D1A1CDD464B00A88F16 /* SNTCommandSyncPreflight.m in Sources */, 0D10BE891A0AAF6700C0C944 /* SNTDropRootPrivs.m in Sources */, - 0DEFB7C61ACDE5F600B92AAE /* SNTFileWatcher.m in Sources */, C795ED911D80B66B007CFF42 /* SNTPolicyProcessor.m in Sources */, C72E8D941D7F399900C86DD3 /* SNTCommandFileInfoTest.m in Sources */, - 0DEFB7C81ACF0BFE00B92AAE /* SNTFileWatcherTest.m in Sources */, 0D28D53819D9F5910015C5EB /* SNTConfigurator.m in Sources */, 0DE5B54C1C92722300C00603 /* SNTNotificationQueue.m in Sources */, 0DEA5F651CF6057D00704398 /* SNTCommandSyncEventUpload.m in Sources */, @@ -1516,7 +1503,6 @@ C76614EC1D142D3C00D150C1 /* SNTCommandCheckCache.m in Sources */, 0D416401191974F1006A356A /* SNTCommandSyncState.m in Sources */, 0DC5D871192160180078A5C0 /* SNTCommandSyncLogUpload.m in Sources */, - C7943FE92028B855008D4F76 /* SNTFileWatcher.m in Sources */, 0DB77FDA1CD14092004DF060 /* SNTBlockMessage.m in Sources */, 0D35BDA218FD71CE00921A21 /* main.m in Sources */, 0DCD6043190ACCB8006B445C /* SNTFileInfo.m in Sources */, @@ -1535,7 +1521,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C7943FEA2028C4F7008D4F76 /* SNTFileWatcher.m in Sources */, 0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */, 0D385DF1180DE51600418BC6 /* SNTAppDelegate.m in Sources */, 0D88680A1AC48A1200B86659 /* SNTSystemInfo.m in Sources */, @@ -1583,7 +1568,6 @@ 0DE71A751B95F7F900518526 /* SNTCachedDecision.m in Sources */, C7FB56F61DBFB480004E14EF /* SNTXPCSyncdInterface.m in Sources */, 0DCD6042190ACCB8006B445C /* SNTFileInfo.m in Sources */, - 0DEFB7C41ACDD80100B92AAE /* SNTFileWatcher.m in Sources */, 0DC5D86D191AED220078A5C0 /* SNTRuleTable.m in Sources */, 0D7D01871774F93A005DBAB4 /* SNTDriverManager.m in Sources */, 0D8E18CD19107B56000F89B8 /* SNTDaemonControlController.m in Sources */, diff --git a/Source/common/SNTConfigurator.m b/Source/common/SNTConfigurator.m index 4768eace8..7e9db3c1e 100644 --- a/Source/common/SNTConfigurator.m +++ b/Source/common/SNTConfigurator.m @@ -16,7 +16,6 @@ #include -#import "SNTFileWatcher.h" #import "SNTLogging.h" #import "SNTStrengthify.h" #import "SNTSystemInfo.h" @@ -32,9 +31,6 @@ @interface SNTConfigurator () /// Holds the configurations from a sync server and mobileconfig. @property NSMutableDictionary *syncState; @property NSMutableDictionary *configState; - -/// Watcher for the sync-state.plist. -@property(nonatomic) SNTFileWatcher *syncStateWatcher; @end @implementation SNTConfigurator @@ -150,7 +146,16 @@ + (NSSet *)syncAndConfigStateSet { static NSSet *set; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - set = [[self configStateSet] setByAddingObject:NSStringFromSelector(@selector(syncState))]; + set = [[self syncStateSet] setByAddingObjectsFromSet:[self configStateSet]]; + }); + return set; +} + ++ (NSSet *)syncStateSet { + static NSSet *set; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + set = [NSSet setWithObject:NSStringFromSelector(@selector(syncState))]; }); return set; } @@ -242,10 +247,6 @@ + (NSSet *)keyPathsForValuesAffectingSyncServerAuthRootsFile { return [self configStateSet]; } -+ (NSSet *)keyPathsForValuesAffectingFullSyncLastSuccess { - return [self configStateSet]; -} - + (NSSet *)keyPathsForValuesAffectingMachineOwner { return [self configStateSet]; } @@ -254,6 +255,18 @@ + (NSSet *)keyPathsForValuesAffectingMachineID { return [self configStateSet]; } ++ (NSSet *)keyPathsForValuesAffectingFullSyncLastSuccess { + return [self syncStateSet]; +} + ++ (NSSet *)keyPathsForValuesAffectingRuleSyncLastSuccess { + return [self syncStateSet]; +} + ++ (NSSet *)keyPathsForValuesAffectingSyncCleanRequired { + return [self syncStateSet]; +} + #pragma mark Public Interface - (SNTClientMode)clientMode { @@ -367,7 +380,7 @@ - (NSDate *)fullSyncLastSuccess { } - (void)setFullSyncLastSuccess:(NSDate *)fullSyncLastSuccess { - self.syncState[kFullSyncLastSuccess] = fullSyncLastSuccess; + [self updateSyncStateForKey:kFullSyncLastSuccess value:fullSyncLastSuccess]; self.ruleSyncLastSuccess = fullSyncLastSuccess; } @@ -376,8 +389,7 @@ - (NSDate *)ruleSyncLastSuccess { } - (void)setRuleSyncLastSuccess:(NSDate *)ruleSyncLastSuccess { - self.syncState[kRuleSyncLastSuccess] = ruleSyncLastSuccess; - [self saveSyncStateToDisk]; + [self updateSyncStateForKey:kRuleSyncLastSuccess value:ruleSyncLastSuccess]; } - (BOOL)syncCleanRequired { @@ -385,8 +397,7 @@ - (BOOL)syncCleanRequired { } - (void)setSyncCleanRequired:(BOOL)syncCleanRequired { - self.syncState[kSyncCleanRequired] = @(syncCleanRequired); - [self saveSyncStateToDisk]; + [self updateSyncStateForKey:kSyncCleanRequired value:@(syncCleanRequired)]; } - (NSString *)machineOwner { @@ -423,12 +434,13 @@ - (NSString *)machineID { /// /// Update the syncState. Triggers a KVO event for all dependents. /// -- (BOOL)updateSyncStateForKey:(NSString *)key value:(id)value { - NSMutableDictionary *syncState = self.syncState.mutableCopy; - syncState[key] = value; - self.syncState = syncState; - [self saveSyncStateToDisk]; - return YES; +- (void)updateSyncStateForKey:(NSString *)key value:(id)value { + dispatch_async(dispatch_get_main_queue(), ^{ + NSMutableDictionary *syncState = self.syncState.mutableCopy; + syncState[key] = value; + self.syncState = syncState; + [self saveSyncStateToDisk]; + }); } /// @@ -450,15 +462,6 @@ - (NSMutableDictionary *)readSyncStateFromDisk { continue; } } - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - WEAKIFY(self); - self.syncStateWatcher = [[SNTFileWatcher alloc] initWithFilePath:kSyncStateFilePath - handler:^(unsigned long data) { - STRONGIFY(self); - [self syncStateFileChanged:data]; - }]; - }); return syncState; } @@ -479,39 +482,6 @@ - (void)saveSyncStateToDisk { ofItemAtPath:kSyncStateFilePath error:NULL]; } -/// -/// Ensure permissions are 0644. -/// Revert any out-of-band changes. -/// -- (void)syncStateFileChanged:(unsigned long)data { - if (data & DISPATCH_VNODE_ATTRIB) { - const char *cPath = [kSyncStateFilePath fileSystemRepresentation]; - struct stat fileStat; - stat(cPath, &fileStat); - int mask = S_IRWXU | S_IRWXG | S_IRWXO; - int desired = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - if (fileStat.st_uid != 0 || fileStat.st_gid != 0 || (fileStat.st_mode & mask) != desired) { - LOGI(@"Sync state file permissions changed, fixing."); - if (chown(cPath, 0, 0) != 0) LOGE(@"Failed to chown(%s, 0, 0)", cPath); - if (chmod(cPath, desired) != 0) LOGE(@"Failed to chmod(%s, %i)", cPath, desired); - } - } else { - NSDictionary *newSyncState = [self readSyncStateFromDisk]; - for (NSString *key in self.syncState) { - if (((self.syncState[key] && !newSyncState[key]) || - (!self.syncState[key] && newSyncState[key]) || - (self.syncState[key] && ![self.syncState[key] isEqualTo:newSyncState[key]]))) { - // Ignore sync url and dates - if ([key isEqualToString:kRuleSyncLastSuccess] || - [key isEqualToString:kFullSyncLastSuccess]) continue; - LOGE(@"Sync state file changed, replacing"); - [self saveSyncStateToDisk]; - return; - } - } - } -} - - (void)clearSyncState { self.syncState = [NSMutableDictionary dictionary]; } diff --git a/Source/common/SNTFileWatcher.h b/Source/common/SNTFileWatcher.h deleted file mode 100644 index 82d8a27a1..000000000 --- a/Source/common/SNTFileWatcher.h +++ /dev/null @@ -1,35 +0,0 @@ -/// Copyright 2015 Google Inc. All rights reserved. -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. - -@import Foundation; - -/// -/// Simple file watching class using dispatch sources. Will automatically -/// reload the watch if the file is deleted and continue watching for -/// events until deallocated. -/// -@interface SNTFileWatcher : NSObject - -/// -/// Designated initializer -/// Initializes the watcher and begins watching for modifications. -/// -/// @param filePath the file to watch. -/// @param handler the handler to call when changes happen. The argument to the block is the -/// type of change that happened as a bitmask to be compared with DISPATCH_VNODE_* constants. -/// -- (nonnull instancetype)initWithFilePath:(nonnull NSString *)filePath - handler:(nonnull void (^)(unsigned long))handler; - -@end diff --git a/Source/common/SNTFileWatcher.m b/Source/common/SNTFileWatcher.m deleted file mode 100644 index 038c80b99..000000000 --- a/Source/common/SNTFileWatcher.m +++ /dev/null @@ -1,94 +0,0 @@ -/// Copyright 2015 Google Inc. All rights reserved. -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. - -#import "SNTFileWatcher.h" - -#import "SNTStrengthify.h" - -@interface SNTFileWatcher () -@property NSString *filePath; -@property(copy) void (^handler)(unsigned long); - -@property dispatch_source_t source; -@end - -@implementation SNTFileWatcher - -- (instancetype)init { - [self doesNotRecognizeSelector:_cmd]; - return nil; -} - -- (instancetype)initWithFilePath:(nonnull NSString *)filePath - handler:(nonnull void (^)(unsigned long))handler { - self = [super init]; - if (self) { - _filePath = filePath; - _handler = handler; - [self startWatchingFile]; - } - return self; -} - -- (void)dealloc { - [self stopWatchingFile]; -} - -- (void)startWatchingFile { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); - int mask = (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME | - DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB); - - dispatch_async(queue, ^{ - int fd = -1; - const char *filePath = [self.filePath fileSystemRepresentation]; - while ((fd = open(filePath, O_EVTONLY | O_CLOEXEC)) < 0) { - usleep(200000); // wait 200ms - } - self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd, mask, queue); - - WEAKIFY(self); - - dispatch_source_set_event_handler(self.source, ^{ - STRONGIFY(self); - unsigned long data = dispatch_source_get_data(self.source); - self.handler(data); - if (data & DISPATCH_VNODE_DELETE || data & DISPATCH_VNODE_RENAME) { - [self stopWatchingFile]; - [self startWatchingFile]; - } - sleep(2); - }); - - dispatch_source_set_registration_handler(self.source, ^{ - STRONGIFY(self); - self.handler(0); - }); - - dispatch_source_set_cancel_handler(self.source, ^{ - close(fd); - }); - - dispatch_resume(self.source); - }); -} - -- (void)stopWatchingFile { - if (!self.source) return; - dispatch_source_set_event_handler_f(self.source, NULL); - dispatch_source_cancel(self.source); - self.source = nil; -} - -@end diff --git a/Tests/LogicTests/SNTFileWatcherTest.m b/Tests/LogicTests/SNTFileWatcherTest.m deleted file mode 100644 index fd2e84f0f..000000000 --- a/Tests/LogicTests/SNTFileWatcherTest.m +++ /dev/null @@ -1,140 +0,0 @@ -/// Copyright 2015 Google Inc. All rights reserved. -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. - -@import XCTest; - -#import "SNTFileWatcher.h" - -@interface SNTFileWatcherTest : XCTestCase -@property NSFileManager *fm; -@property NSString *file; -@end - -@implementation SNTFileWatcherTest - -- (void)setUp { - [super setUp]; - - self.fm = [NSFileManager defaultManager]; - self.file = [NSTemporaryDirectory() stringByAppendingString:@"SNTFileWatcherTest_File"]; - [self createFile]; - usleep(10000); -} - -- (void)tearDown { - [self deleteFile]; - usleep(10000); - - [super tearDown]; -} - -- (void)createFile { - [self.fm createFileAtPath:self.file contents:nil attributes:nil]; -} - -- (void)deleteFile { - [self.fm removeItemAtPath:self.file error:NULL]; -} - -- (void)testPlainInit { - XCTAssertThrows([[SNTFileWatcher alloc] init]); -} - -- (void)testInitFileExists { - __weak XCTestExpectation *exp = [self expectationWithDescription:@"Init: callback called"]; - __unused SNTFileWatcher *sut = [[SNTFileWatcher alloc] initWithFilePath:self.file - handler:^(unsigned long data) { - [exp fulfill]; - }]; - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - -- (void)testInitNewFile { - [self deleteFile]; - - __weak XCTestExpectation *exp = [self expectationWithDescription:@"Init: callback called"]; - __unused SNTFileWatcher *sut = [[SNTFileWatcher alloc] initWithFilePath:self.file - handler:^(unsigned long data) { - [exp fulfill]; - }]; - - [self createFile]; - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - -- (void)testFileChanged { - __block BOOL fulfilled = NO; - __weak XCTestExpectation *exp = [self expectationWithDescription:@"Changed: callback called"]; - __unused SNTFileWatcher *sut = [[SNTFileWatcher alloc] initWithFilePath:self.file - handler:^(unsigned long data) { - NSString *d = [NSString stringWithContentsOfFile:self.file - encoding:NSUTF8StringEncoding - error:nil]; - if (!fulfilled && [d isEqual:@"0x8BADF00D"]) { - fulfilled = YES; - [exp fulfill]; - } - }]; - - sleep(1); - - [[@"0x8BADF00D" dataUsingEncoding:NSUTF8StringEncoding] writeToFile:self.file atomically:NO]; - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - -- (void)testFileReplaced { - __block BOOL fulfilled = NO; - __weak XCTestExpectation *exp = [self expectationWithDescription:@"Replaced: callback called"]; - __unused SNTFileWatcher *sut = [[SNTFileWatcher alloc] initWithFilePath:self.file - handler:^(unsigned long data) { - NSString *d = [NSString stringWithContentsOfFile:self.file - encoding:NSUTF8StringEncoding - error:nil]; - if (!fulfilled && [d isEqual:@"0xFACEFEED"]) { - fulfilled = YES; - [exp fulfill]; - } - }]; - - [[@"0xFACEFEED" dataUsingEncoding:NSUTF8StringEncoding] writeToFile:self.file atomically:YES]; - - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - -- (void)testFileExtended { - int fd = open(self.file.fileSystemRepresentation, O_WRONLY); - write(fd, "0xDEAD", 6); - - __block BOOL fulfilled = NO; - __weak XCTestExpectation *exp = [self expectationWithDescription:@"Extended: callback called"]; - __unused SNTFileWatcher *sut = [[SNTFileWatcher alloc] initWithFilePath:self.file - handler:^(unsigned long data) { - int file = open(self.file.fileSystemRepresentation, O_RDONLY); - char fileData[10]; - read(file, fileData, 10); - - if (!fulfilled && strncmp(fileData, "0xDEADBEEF", 10) == 0) { - fulfilled = YES; - [exp fulfill]; - } - }]; - - write(fd, "BEEF", 4); - close(fd); - - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - -@end - From bbe9f8387838628c24aa691e6acbb7c1c275b39f Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Mon, 12 Mar 2018 16:02:55 -0400 Subject: [PATCH 11/25] Import fixes (#243) * All: use common import style for cocoapods * All: Update Pods --- Podfile.lock | 34 ++++++++++---------- Source/SantaGUI/SNTMessageWindowController.m | 4 +-- Source/common/SNTStoredEvent.m | 2 +- Source/common/SNTXPCConnection.m | 2 +- Source/santabs/SNTBundleService.m | 4 +-- Source/santactl/Commands/SNTCommandRule.m | 5 +-- Source/santad/DataLayer/SNTEventTable.m | 3 +- Source/santad/DataLayer/SNTRuleTable.m | 5 +-- Source/santad/SNTEventLog.m | 3 +- Source/santad/SNTExecutionController.m | 4 +-- Source/santad/SNTPolicyProcessor.h | 2 +- 11 files changed, 36 insertions(+), 32 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 1270f38f6..d1be00111 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,15 +1,15 @@ PODS: - - FMDB (2.6.2): - - FMDB/standard (= 2.6.2) - - FMDB/standard (2.6.2) - - MOLAuthenticatingURLSession (2.2): - - MOLCertificate (~> 1.5) - - MOLCertificate (1.7) - - MOLCodesignChecker (1.8): - - MOLCertificate (~> 1.7) - - MOLFCMClient (1.5): - - MOLAuthenticatingURLSession (~> 2.1) - - OCMock (3.4) + - FMDB (2.7.2): + - FMDB/standard (= 2.7.2) + - FMDB/standard (2.7.2) + - MOLAuthenticatingURLSession (2.4): + - MOLCertificate (~> 1.8) + - MOLCertificate (1.8) + - MOLCodesignChecker (1.9): + - MOLCertificate (~> 1.8) + - MOLFCMClient (1.6): + - MOLAuthenticatingURLSession (~> 2.4) + - OCMock (3.4.1) DEPENDENCIES: - FMDB @@ -20,12 +20,12 @@ DEPENDENCIES: - OCMock SPEC CHECKSUMS: - FMDB: 854a0341b4726e53276f2a8996f06f1b80f9259a - MOLAuthenticatingURLSession: 5a5e31eb73248c3e92c79b9a285f031194e8404c - MOLCertificate: 1cdb264405631b4bbdcf4cde7627469290cf1187 - MOLCodesignChecker: 93460b82eb41b671c1c8eff9fc904d0d3d149e16 - MOLFCMClient: 88debb79f8c0454c3dd4f6514c2453e57a963c08 - OCMock: 35ae71d6a8fcc1b59434d561d1520b9dd4f15765 + FMDB: 6198a90e7b6900cfc046e6bc0ef6ebb7be9236aa + MOLAuthenticatingURLSession: c238aa1c9a7b1077eb39a6f40204bfe76a7d204e + MOLCertificate: c999513316d511c69f290fbf313dfe8dca4ad592 + MOLCodesignChecker: 303c01755646a0045c97f9f0b0fe5945ead42130 + MOLFCMClient: a9dad7e686eb359c33cdd742c64427bfdd843146 + OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3 PODFILE CHECKSUM: acd378b3727c923d912e09812da344f7375c14fe diff --git a/Source/SantaGUI/SNTMessageWindowController.m b/Source/SantaGUI/SNTMessageWindowController.m index 3d58a5153..5e6078b5f 100644 --- a/Source/SantaGUI/SNTMessageWindowController.m +++ b/Source/SantaGUI/SNTMessageWindowController.m @@ -16,10 +16,10 @@ @import SecurityInterface.SFCertificatePanel; -#import "MOLCertificate.h" +#import + #import "SNTBlockMessage.h" #import "SNTConfigurator.h" -#import "SNTFileInfo.h" #import "SNTMessageWindow.h" #import "SNTStoredEvent.h" diff --git a/Source/common/SNTStoredEvent.m b/Source/common/SNTStoredEvent.m index 3cdbaac7a..455386dd9 100644 --- a/Source/common/SNTStoredEvent.m +++ b/Source/common/SNTStoredEvent.m @@ -14,7 +14,7 @@ #import "SNTStoredEvent.h" -#import "MOLCertificate.h" +#import @implementation SNTStoredEvent diff --git a/Source/common/SNTXPCConnection.m b/Source/common/SNTXPCConnection.m index 24b8f2a7e..6d5041963 100644 --- a/Source/common/SNTXPCConnection.m +++ b/Source/common/SNTXPCConnection.m @@ -14,7 +14,7 @@ #import "SNTXPCConnection.h" -#import "MOLCodesignChecker.h" +#import #import "SNTStrengthify.h" diff --git a/Source/santabs/SNTBundleService.m b/Source/santabs/SNTBundleService.m index e93ded9a6..24032f6e5 100644 --- a/Source/santabs/SNTBundleService.m +++ b/Source/santabs/SNTBundleService.m @@ -17,8 +17,8 @@ #import #import -#import "MOLCertificate.h" -#import "MOLCodesignChecker.h" +#import + #import "SNTFileInfo.h" #import "SNTStoredEvent.h" #import "SNTXPCConnection.h" diff --git a/Source/santactl/Commands/SNTCommandRule.m b/Source/santactl/Commands/SNTCommandRule.m index 0784ce381..5c2ba6187 100644 --- a/Source/santactl/Commands/SNTCommandRule.m +++ b/Source/santactl/Commands/SNTCommandRule.m @@ -17,8 +17,9 @@ #import "SNTCommand.h" #import "SNTCommandController.h" -#import "MOLCertificate.h" -#import "MOLCodesignChecker.h" +#import +#import + #import "SNTConfigurator.h" #import "SNTDropRootPrivs.h" #import "SNTFileInfo.h" diff --git a/Source/santad/DataLayer/SNTEventTable.m b/Source/santad/DataLayer/SNTEventTable.m index 11f91c6bc..d3a1dd7e7 100644 --- a/Source/santad/DataLayer/SNTEventTable.m +++ b/Source/santad/DataLayer/SNTEventTable.m @@ -14,7 +14,8 @@ #import "SNTEventTable.h" -#import "MOLCertificate.h" +#import + #import "SNTStoredEvent.h" @implementation SNTEventTable diff --git a/Source/santad/DataLayer/SNTRuleTable.m b/Source/santad/DataLayer/SNTRuleTable.m index e86231b9a..c298e33b7 100644 --- a/Source/santad/DataLayer/SNTRuleTable.m +++ b/Source/santad/DataLayer/SNTRuleTable.m @@ -14,8 +14,9 @@ #import "SNTRuleTable.h" -#import "MOLCertificate.h" -#import "MOLCodesignChecker.h" +#import +#import + #import "SNTConfigurator.h" #import "SNTLogging.h" #import "SNTRule.h" diff --git a/Source/santad/SNTEventLog.m b/Source/santad/SNTEventLog.m index 2554d7c91..86cad8bf0 100644 --- a/Source/santad/SNTEventLog.m +++ b/Source/santad/SNTEventLog.m @@ -20,7 +20,8 @@ #include #include -#import "MOLCertificate.h" +#import + #import "SNTCachedDecision.h" #import "SNTCommonEnums.h" #import "SNTConfigurator.h" diff --git a/Source/santad/SNTExecutionController.m b/Source/santad/SNTExecutionController.m index 2e27d6b6a..65269a00b 100644 --- a/Source/santad/SNTExecutionController.m +++ b/Source/santad/SNTExecutionController.m @@ -20,8 +20,8 @@ #include "SNTLogging.h" -#import "MOLCertificate.h" -#import "MOLCodesignChecker.h" +#import + #import "SNTBlockMessage.h" #import "SNTCachedDecision.h" #import "SNTCommonEnums.h" diff --git a/Source/santad/SNTPolicyProcessor.h b/Source/santad/SNTPolicyProcessor.h index 0051d002a..0f21ebdbb 100644 --- a/Source/santad/SNTPolicyProcessor.h +++ b/Source/santad/SNTPolicyProcessor.h @@ -17,7 +17,7 @@ #import "SNTCommonEnums.h" #import "SNTKernelCommon.h" -#import +#import @class SNTCachedDecision; @class SNTFileInfo; From ce03611b52f64b54baf886f00c38d926967e9763 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Mon, 12 Mar 2018 17:04:53 -0400 Subject: [PATCH 12/25] santabs: Serialize calls to -[SNTBundleService createConnection] (#244) --- Source/santabs/SNTBundleService.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/santabs/SNTBundleService.m b/Source/santabs/SNTBundleService.m index 24032f6e5..537f32918 100644 --- a/Source/santabs/SNTBundleService.m +++ b/Source/santabs/SNTBundleService.m @@ -72,18 +72,18 @@ - (void)createConnection { } - (void)attemptReconnection { - [self performSelectorInBackground:@selector(createConnection) withObject:nil]; + [self performSelectorOnMainThread:@selector(createConnection) withObject:nil waitUntilDone:NO]; } #pragma mark SNTBundleServiceXPC Methods // Connect to the SantaGUI - (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener { - SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener]; - c.remoteInterface = [SNTXPCNotifierInterface bundleNotifierInterface]; - [c resume]; - self.notifierConnection = c; - dispatch_async(self.queue, ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener]; + c.remoteInterface = [SNTXPCNotifierInterface bundleNotifierInterface]; + [c resume]; + self.notifierConnection = c; [self createConnection]; }); } From 6a6a32c1cf0eca31d4b35f6a85c8f2d0ab5640e6 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Tue, 13 Mar 2018 13:07:44 -0400 Subject: [PATCH 13/25] santactl: Update to MOLFCMClient v1.7 (#245) --- Podfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index d1be00111..e73799026 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -7,7 +7,7 @@ PODS: - MOLCertificate (1.8) - MOLCodesignChecker (1.9): - MOLCertificate (~> 1.8) - - MOLFCMClient (1.6): + - MOLFCMClient (1.7): - MOLAuthenticatingURLSession (~> 2.4) - OCMock (3.4.1) @@ -24,7 +24,7 @@ SPEC CHECKSUMS: MOLAuthenticatingURLSession: c238aa1c9a7b1077eb39a6f40204bfe76a7d204e MOLCertificate: c999513316d511c69f290fbf313dfe8dca4ad592 MOLCodesignChecker: 303c01755646a0045c97f9f0b0fe5945ead42130 - MOLFCMClient: a9dad7e686eb359c33cdd742c64427bfdd843146 + MOLFCMClient: ee45348909351f232e2759c580329072ae7e02d4 OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3 PODFILE CHECKSUM: acd378b3727c923d912e09812da344f7375c14fe From 4a2cf9d722a4e2d88f6b0b560ddee44706ea4442 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Tue, 3 Apr 2018 13:15:12 -0400 Subject: [PATCH 14/25] santad: event logger (#246) * kext symbols * santad: Create FileLog and Syslog options * review updates * review updates * be a good citizen and let go of things you do not need --- .gitignore | 1 + Conf/Package/Makefile | 10 + Conf/com.google.santa.newsyslog.conf | 2 + Conf/install.sh | 1 + Conf/uninstall.sh | 1 + Rakefile | 1 + Santa.xcodeproj/project.pbxproj | 42 +++- Source/common/SNTCommonEnums.h | 6 + Source/common/SNTConfigurator.h | 19 ++ Source/common/SNTConfigurator.m | 22 ++ Source/common/SNTLogging.m | 8 +- Source/santad/{ => Logs}/SNTEventLog.h | 29 ++- Source/santad/{ => Logs}/SNTEventLog.m | 238 ++------------------ Source/santad/Logs/SNTFileEventLog.h | 18 ++ Source/santad/Logs/SNTFileEventLog.m | 101 +++++++++ Source/santad/Logs/SNTSyslogEventLog.h | 18 ++ Source/santad/Logs/SNTSyslogEventLog.m | 242 +++++++++++++++++++++ Source/santad/SNTApplication.m | 15 +- Source/santad/SNTDaemonControlController.m | 1 + Source/santad/SNTExecutionController.m | 2 +- 20 files changed, 541 insertions(+), 236 deletions(-) create mode 100644 Conf/com.google.santa.newsyslog.conf rename Source/santad/{ => Logs}/SNTEventLog.h (53%) rename Source/santad/{ => Logs}/SNTEventLog.m (63%) create mode 100644 Source/santad/Logs/SNTFileEventLog.h create mode 100644 Source/santad/Logs/SNTFileEventLog.m create mode 100644 Source/santad/Logs/SNTSyslogEventLog.h create mode 100644 Source/santad/Logs/SNTSyslogEventLog.m diff --git a/.gitignore b/.gitignore index d3614ab8a..dc5e7d6ab 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ Santa.xcodeproj/project.xcworkspace Santa.xcworkspace/xcuserdata Santa.xcworkspace/xcshareddata Source/DevelopmentTeam.xcconfig +default.profraw diff --git a/Conf/Package/Makefile b/Conf/Package/Makefile index 056f7e3c7..b6f786b3a 100644 --- a/Conf/Package/Makefile +++ b/Conf/Package/Makefile @@ -32,6 +32,7 @@ PACKAGE_VERSION:=$(shell curl -fs https://api.github.com/repos/google/santa/rele # | |-- com.google.santad.plist # | |-- com.google.santagui.plist # | +-- com.google.santa.asl.conf +# | +-- com.google.santa.newsyslog.conf # +--dsym # |-- santa-driver.kext.dSYM # |-- Santa.app.dSYM @@ -44,6 +45,7 @@ PAYLOAD:=pack-Library-Extensions-santa-driver.kext \ pack-Library-LaunchDaemons-com.google.santad.plist \ pack-Library-LaunchAgents-com.google.santagui.plist \ pack-etc-asl-com.google.santa.asl.conf \ + pack-etc-newsyslog.d-com.google.santa.newsyslog.conf \ pack-script-preinstall \ pack-script-postinstall @@ -52,6 +54,7 @@ Santa.app: download com.google.santad.plist: download com.google.santagui.plist: download com.google.santa.asl.conf: download +com.google.santa.newsyslog.conf: download download: $(if $(PACKAGE_VERSION),, $(error GitHub API returned unexpected result. Wait a while and try again)) @@ -65,6 +68,12 @@ pack-etc-asl-com.google.santa.asl.conf: com.google.santa.asl.conf l_private_etc @sudo chmod 755 ${WORK_D}/private/etc/asl @sudo install -m 644 -o root -g wheel com.google.santa.asl.conf ${WORK_D}/private/etc/asl +pack-etc-newsyslog.d-com.google.santa.newsyslog.conf: com.google.santa.newsyslog.conf l_private_etc + @sudo mkdir -p ${WORK_D}/private/etc/newsyslog.d + @sudo chown root:wheel ${WORK_D}/private/etc/newsyslog.d + @sudo chmod 755 ${WORK_D}/private/etc/newsyslog.d + @sudo install -m 644 -o root -g wheel com.google.santa.newsyslog.conf ${WORK_D}/private/etc/newsyslog.d + pack-Library-Extensions-santa-driver.kext: santa-driver.kext l_Library @sudo mkdir -p ${WORK_D}/Library/Extensions @sudo ${DITTO} --noqtn santa-driver.kext ${WORK_D}/Library/Extensions/santa-driver.kext @@ -79,6 +88,7 @@ myclean: @rm -rf santa-driver.kext @rm -f config.plist @rm -f com.google.santa.asl.conf + @rm -f com.google.santa.newsyslog.conf @rm -f com.google.santad.plist @rm -f com.google.santagui.plist @rm -f install.sh diff --git a/Conf/com.google.santa.newsyslog.conf b/Conf/com.google.santa.newsyslog.conf new file mode 100644 index 000000000..f5296c11b --- /dev/null +++ b/Conf/com.google.santa.newsyslog.conf @@ -0,0 +1,2 @@ +# logfilename [owner:group] mode count size(KiB) when flags [/pid_file] # [sig_num] +/var/db/santa/santa.log root:wheel 644 10 25000 * NZ diff --git a/Conf/install.sh b/Conf/install.sh index 895a75b5f..abeed5556 100755 --- a/Conf/install.sh +++ b/Conf/install.sh @@ -42,6 +42,7 @@ mkdir -p /usr/local/bin /bin/cp ${SOURCE}/conf/com.google.santad.plist /Library/LaunchDaemons /bin/cp ${SOURCE}/conf/com.google.santagui.plist /Library/LaunchAgents /bin/cp ${SOURCE}/conf/com.google.santa.asl.conf /etc/asl/ +/bin/cp ${SOURCE}/conf/com.google.santa.newsyslog.conf /etc/newsyslog.d/ # Reload syslogd to pick up ASL configuration change. /usr/bin/killall -HUP syslogd diff --git a/Conf/uninstall.sh b/Conf/uninstall.sh index e9cc4fa52..3812975c6 100755 --- a/Conf/uninstall.sh +++ b/Conf/uninstall.sh @@ -19,6 +19,7 @@ user=$(/usr/bin/stat -f '%u' /dev/console) /bin/rm -f /Library/LaunchAgents/com.google.santagui.plist /bin/rm -f /Library/LaunchDaemons/com.google.santad.plist /bin/rm -f /private/etc/asl/com.google.santa.asl.conf +/bin/rm -f /private/etc/newsyslog.d/com.google.santa.newsyslog.conf /bin/rm -f /usr/local/bin/santactl # just a symlink #uncomment to remove the config file and all databases, log files #/bin/rm -rf /var/db/santa diff --git a/Rakefile b/Rakefile index 148af12b5..ad4b6d68f 100644 --- a/Rakefile +++ b/Rakefile @@ -106,6 +106,7 @@ namespace :install do system 'sudo cp conf/com.google.santad.plist /Library/LaunchDaemons' system 'sudo cp conf/com.google.santagui.plist /Library/LaunchAgents' system 'sudo cp conf/com.google.santa.asl.conf /etc/asl' + system 'sudo cp conf/com.google.santa.newsyslog.conf /etc/newsyslog.d/' system '/usr/bin/killall -HUP syslogd' Rake::Task['build:build'].invoke(config) puts "Installing with configuration: #{config}" diff --git a/Santa.xcodeproj/project.pbxproj b/Santa.xcodeproj/project.pbxproj index 3bdf01751..aa301f2a2 100644 --- a/Santa.xcodeproj/project.pbxproj +++ b/Santa.xcodeproj/project.pbxproj @@ -72,8 +72,6 @@ 0D4644C6182AF81700098690 /* SantaDecisionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D4644C4182AF81700098690 /* SantaDecisionManager.h */; }; 0D536ED71B8E7A2E0039A26D /* bad_pagezero in Resources */ = {isa = PBXBuildFile; fileRef = 0D536ED51B8E7A2E0039A26D /* bad_pagezero */; }; 0D536ED81B8E7A2E0039A26D /* missing_pagezero in Resources */ = {isa = PBXBuildFile; fileRef = 0D536ED61B8E7A2E0039A26D /* missing_pagezero */; }; - 0D536EDB1B94E9230039A26D /* SNTEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D536EDA1B94E9230039A26D /* SNTEventLog.m */; }; - 0D536EDC1B94E9230039A26D /* SNTEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D536EDA1B94E9230039A26D /* SNTEventLog.m */; }; 0D63DD5C1906FCB400D346C4 /* SNTDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */; }; 0D63DD5E1906FCB400D346C4 /* SNTDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */; }; 0D668E8118D1121700E29A8B /* SNTMessageWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D668E8018D1121700E29A8B /* SNTMessageWindow.m */; }; @@ -164,6 +162,12 @@ C7479F051E53704E0054C1CF /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; }; C7479F071E5374BF0054C1CF /* SNTXPCControlInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD605419115D17006B445C /* SNTXPCControlInterface.m */; }; C7479F091E5374E50054C1CF /* SNTRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE50F671912716A007B2B0C /* SNTRule.m */; }; + C748E8A3206964E1006CFD1B /* SNTEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = C748E8A2206964DE006CFD1B /* SNTEventLog.m */; }; + C748E8A4206964EE006CFD1B /* SNTEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = C748E8A2206964DE006CFD1B /* SNTEventLog.m */; }; + C748E8A720696595006CFD1B /* SNTFileEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = C748E8A620696595006CFD1B /* SNTFileEventLog.m */; }; + C748E8A820696595006CFD1B /* SNTFileEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = C748E8A620696595006CFD1B /* SNTFileEventLog.m */; }; + C748E8B020697F01006CFD1B /* SNTSyslogEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = C748E8AF20697F01006CFD1B /* SNTSyslogEventLog.m */; }; + C748E8B120697F01006CFD1B /* SNTSyslogEventLog.m in Sources */ = {isa = PBXBuildFile; fileRef = C748E8AF20697F01006CFD1B /* SNTSyslogEventLog.m */; }; C74D6CC61EEB3B9B00BB5A33 /* BundleExample.app in Resources */ = {isa = PBXBuildFile; fileRef = C74D6CC51EEB3B9B00BB5A33 /* BundleExample.app */; }; C76614EC1D142D3C00D150C1 /* SNTCommandCheckCache.m in Sources */ = {isa = PBXBuildFile; fileRef = C76614EB1D142D3C00D150C1 /* SNTCommandCheckCache.m */; }; C776A1071DEE160500A56616 /* SNTCommandSyncManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C776A1061DEE160500A56616 /* SNTCommandSyncManager.m */; }; @@ -341,8 +345,6 @@ 0D5058CF1CB70123008784BA /* SNTStrengthify.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTStrengthify.h; sourceTree = ""; }; 0D536ED51B8E7A2E0039A26D /* bad_pagezero */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = bad_pagezero; sourceTree = ""; }; 0D536ED61B8E7A2E0039A26D /* missing_pagezero */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = missing_pagezero; sourceTree = ""; }; - 0D536ED91B94E9230039A26D /* SNTEventLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTEventLog.h; sourceTree = ""; }; - 0D536EDA1B94E9230039A26D /* SNTEventLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTEventLog.m; sourceTree = ""; }; 0D63DD5A1906FCB400D346C4 /* SNTDatabaseController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTDatabaseController.h; sourceTree = ""; }; 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTDatabaseController.m; sourceTree = ""; }; 0D668E7F18D1121700E29A8B /* SNTMessageWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTMessageWindow.h; sourceTree = ""; }; @@ -429,6 +431,12 @@ A6A91785C40257CC156B4F05 /* Pods-Santa.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Santa.release.xcconfig"; path = "Pods/Target Support Files/Pods-Santa/Pods-Santa.release.xcconfig"; sourceTree = ""; }; C11A10A5D6E112788769CF70 /* libPods-santad.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santad.a"; sourceTree = BUILT_PRODUCTS_DIR; }; C72E8D931D7F399900C86DD3 /* SNTCommandFileInfoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandFileInfoTest.m; sourceTree = ""; }; + C748E8A1206964DE006CFD1B /* SNTEventLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTEventLog.h; sourceTree = ""; }; + C748E8A2206964DE006CFD1B /* SNTEventLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SNTEventLog.m; sourceTree = ""; }; + C748E8A520696594006CFD1B /* SNTFileEventLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTFileEventLog.h; sourceTree = ""; }; + C748E8A620696595006CFD1B /* SNTFileEventLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SNTFileEventLog.m; sourceTree = ""; }; + C748E8AE20697F01006CFD1B /* SNTSyslogEventLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTSyslogEventLog.h; sourceTree = ""; }; + C748E8AF20697F01006CFD1B /* SNTSyslogEventLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SNTSyslogEventLog.m; sourceTree = ""; }; C74D6CC51EEB3B9B00BB5A33 /* BundleExample.app */ = {isa = PBXFileReference; lastKnownFileType = wrapper.application; path = BundleExample.app; sourceTree = ""; }; C76614EB1D142D3C00D150C1 /* SNTCommandCheckCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandCheckCache.m; sourceTree = ""; }; C776A1051DEE160500A56616 /* SNTCommandSyncManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncManager.h; sourceTree = ""; }; @@ -752,6 +760,7 @@ isa = PBXGroup; children = ( 0DA73CA519363C9F0056D7C4 /* DataLayer */, + C748E8A020696001006CFD1B /* Logs */, 0D9A7F411759330500035EB5 /* main.m */, 0DB8ACBF185662DC00FEF9C7 /* SNTApplication.h */, 0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */, @@ -765,8 +774,6 @@ C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */, 0D7D01851774F93A005DBAB4 /* SNTDriverManager.h */, 0D7D01861774F93A005DBAB4 /* SNTDriverManager.m */, - 0D536ED91B94E9230039A26D /* SNTEventLog.h */, - 0D536EDA1B94E9230039A26D /* SNTEventLog.m */, 0DE6788B1784A8C2007A9E52 /* SNTExecutionController.h */, 0DE6788C1784A8C2007A9E52 /* SNTExecutionController.m */, 0DE5B5491C926E3300C00603 /* SNTNotificationQueue.h */, @@ -840,6 +847,19 @@ name = Frameworks; sourceTree = ""; }; + C748E8A020696001006CFD1B /* Logs */ = { + isa = PBXGroup; + children = ( + C748E8A1206964DE006CFD1B /* SNTEventLog.h */, + C748E8A2206964DE006CFD1B /* SNTEventLog.m */, + C748E8AE20697F01006CFD1B /* SNTSyslogEventLog.h */, + C748E8AF20697F01006CFD1B /* SNTSyslogEventLog.m */, + C748E8A520696594006CFD1B /* SNTFileEventLog.h */, + C748E8A620696595006CFD1B /* SNTFileEventLog.m */, + ); + path = Logs; + sourceTree = ""; + }; C79A23541E23F7E80037AFA8 /* santabs */ = { isa = PBXGroup; children = ( @@ -1437,8 +1457,9 @@ C7DA62F71E241938009BDF2C /* SNTXPCBundleServiceInterface.m in Sources */, C714F8B11D8044D400700EDF /* SNTCommandFileInfo.m in Sources */, 0D88680C1AC48A1400B86659 /* SNTSystemInfo.m in Sources */, - 0D536EDC1B94E9230039A26D /* SNTEventLog.m in Sources */, 0DEA5F7D1CF64EB600704398 /* SNTCommandSyncRuleDownload.m in Sources */, + C748E8A4206964EE006CFD1B /* SNTEventLog.m in Sources */, + C748E8B120697F01006CFD1B /* SNTSyslogEventLog.m in Sources */, C73A4B9B1DC10758007B6789 /* SNTXPCSyncdInterface.m in Sources */, 0DB77FDB1CD14093004DF060 /* SNTBlockMessage.m in Sources */, 0D63DD5E1906FCB400D346C4 /* SNTDatabaseController.m in Sources */, @@ -1457,6 +1478,7 @@ 0D10BE891A0AAF6700C0C944 /* SNTDropRootPrivs.m in Sources */, C795ED911D80B66B007CFF42 /* SNTPolicyProcessor.m in Sources */, C72E8D941D7F399900C86DD3 /* SNTCommandFileInfoTest.m in Sources */, + C748E8A820696595006CFD1B /* SNTFileEventLog.m in Sources */, 0D28D53819D9F5910015C5EB /* SNTConfigurator.m in Sources */, 0DE5B54C1C92722300C00603 /* SNTNotificationQueue.m in Sources */, 0DEA5F651CF6057D00704398 /* SNTCommandSyncEventUpload.m in Sources */, @@ -1558,6 +1580,7 @@ 0D8868091AC48A1100B86659 /* SNTSystemInfo.m in Sources */, 0DE6788D1784A8C2007A9E52 /* SNTExecutionController.m in Sources */, 0D10BE861A0AABD600C0C944 /* SNTDropRootPrivs.m in Sources */, + C748E8B020697F01006CFD1B /* SNTSyslogEventLog.m in Sources */, 0D63DD5C1906FCB400D346C4 /* SNTDatabaseController.m in Sources */, 0DCD604B19105433006B445C /* SNTStoredEvent.m in Sources */, C7FB57001DBFC213004E14EF /* SNTSyncdQueue.m in Sources */, @@ -1576,10 +1599,11 @@ 0DE50F681912716A007B2B0C /* SNTRule.m in Sources */, 0DB77FD81CCE824A004DF060 /* SNTBlockMessage.m in Sources */, 0D37C10F18F6029A0069BC61 /* SNTDatabaseTable.m in Sources */, + C748E8A720696595006CFD1B /* SNTFileEventLog.m in Sources */, + C748E8A3206964E1006CFD1B /* SNTEventLog.m in Sources */, 0D42D2B819D2042900955F08 /* SNTConfigurator.m in Sources */, 0DCD605519115D17006B445C /* SNTXPCControlInterface.m in Sources */, C795ED901D80A5BE007CFF42 /* SNTPolicyProcessor.m in Sources */, - 0D536EDB1B94E9230039A26D /* SNTEventLog.m in Sources */, 0DCD604F19115A06006B445C /* SNTXPCNotifierInterface.m in Sources */, 0DE5B54B1C926E3300C00603 /* SNTNotificationQueue.m in Sources */, ); @@ -2026,6 +2050,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_CODE_COVERAGE = NO; CLANG_ENABLE_MODULES = NO; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -2064,6 +2089,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_CODE_COVERAGE = NO; CLANG_ENABLE_MODULES = NO; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_CONSTANT_CONVERSION = YES; diff --git a/Source/common/SNTCommonEnums.h b/Source/common/SNTCommonEnums.h index bde0c7a7f..3f17bdcf3 100644 --- a/Source/common/SNTCommonEnums.h +++ b/Source/common/SNTCommonEnums.h @@ -80,6 +80,12 @@ typedef NS_ENUM(NSInteger, SNTBundleEventAction) { SNTBundleEventActionSendEvents, }; +// Indicates where to store event logs. +typedef NS_ENUM(NSInteger, SNTEventLogType) { + SNTEventLogTypeSyslog, + SNTEventLogTypeFilelog, +}; + static const char *kKextPath = "/Library/Extensions/santa-driver.kext"; static const char *kSantaDPath = "/Library/Extensions/santa-driver.kext/Contents/MacOS/santad"; static const char *kSantaCtlPath = "/Library/Extensions/santa-driver.kext/Contents/MacOS/santactl"; diff --git a/Source/common/SNTConfigurator.h b/Source/common/SNTConfigurator.h index 808e3b565..33c574d59 100644 --- a/Source/common/SNTConfigurator.h +++ b/Source/common/SNTConfigurator.h @@ -79,6 +79,25 @@ /// @property(readonly, nonatomic) BOOL enablePageZeroProtection; +/// +/// Defines how event logs are stored. Options are: +/// SNTEventLogTypeSyslog: Sent to ASL or ULS (if built with the 10.12 SDK or later). +/// SNTEventLogTypeFilelog: Sent to a file on disk. Use eventLogPath to specify a path. +/// Defaults to SNTEventLogTypeFilelog. +/// For mobileconfigs use EventLogType as the key and syslog or filelog strings as the value. +/// +/// @note: This property is KVO compliant, but should only be read once at santad startup. +/// +@property(readonly, nonatomic) SNTEventLogType eventLogType; + +/// +/// If eventLogType is set to Filelog, eventLogPath will provide the path to save logs. +/// Defaults to /var/db/santa/santa.log. +/// +/// @note: This property is KVO compliant, but should only be read once at santad startup. +/// +@property(readonly, nonatomic) NSString *eventLogPath; + #pragma mark - GUI Settings /// diff --git a/Source/common/SNTConfigurator.m b/Source/common/SNTConfigurator.m index 7e9db3c1e..0b8b7e6c1 100644 --- a/Source/common/SNTConfigurator.m +++ b/Source/common/SNTConfigurator.m @@ -69,6 +69,9 @@ @implementation SNTConfigurator static NSString *const kFileChangesRegexKey = @"FileChangesRegex"; +static NSString *const kEventLogType = @"EventLogType"; +static NSString *const kEventLogPath = @"EventLogPath"; + // The keys managed by a sync server or mobileconfig. static NSString *const kClientModeKey = @"ClientMode"; static NSString *const kWhitelistRegexKey = @"WhitelistRegex"; @@ -121,6 +124,8 @@ - (instancetype)init { kMachineOwnerPlistKeyKey : string, kMachineIDPlistFileKey : string, kMachineIDPlistKeyKey : string, + kEventLogType : string, + kEventLogPath : string, }; _defaults = [NSUserDefaults standardUserDefaults]; [_defaults addSuiteNamed:@"com.google.santa"]; @@ -267,6 +272,14 @@ + (NSSet *)keyPathsForValuesAffectingSyncCleanRequired { return [self syncStateSet]; } ++ (NSSet *)keyPathsForValuesAffectingEventLogType { + return [self configStateSet]; +} + ++ (NSSet *)keyPathsForValuesAffectingEventLogPath { + return [self configStateSet]; +} + #pragma mark Public Interface - (SNTClientMode)clientMode { @@ -429,6 +442,15 @@ - (NSString *)machineID { return machineId.length ? machineId : [SNTSystemInfo hardwareUUID]; } +- (SNTEventLogType)eventLogType { + NSString *s = [self.configState[kEventLogType] lowercaseString]; + return [s isEqualToString:@"syslog"] ? SNTEventLogTypeSyslog : SNTEventLogTypeFilelog; +} + +- (NSString *)eventLogPath { + return self.configState[kEventLogPath] ?: @"/var/db/santa/santa.log"; +} + #pragma mark Private /// diff --git a/Source/common/SNTLogging.m b/Source/common/SNTLogging.m index c5f60044b..022216a15 100644 --- a/Source/common/SNTLogging.m +++ b/Source/common/SNTLogging.m @@ -29,12 +29,12 @@ void syslogClientDestructor(void *arg) { void logMessage(LogLevel level, FILE *destination, NSString *format, ...) { static BOOL useSyslog = NO; - static const char *binaryName; + static NSString *binaryName; static dispatch_once_t pred; static pthread_key_t syslogKey = 0; dispatch_once(&pred, ^{ - binaryName = [[[NSProcessInfo processInfo] processName] UTF8String]; + binaryName = [[NSProcessInfo processInfo] processName]; // If debug logging is enabled, the process must be restarted. if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--debug"]) { @@ -76,7 +76,7 @@ void logMessage(LogLevel level, FILE *destination, NSString *format, ...) { break; case LOG_LEVEL_INFO: levelName = "I"; - syslogLevel = ASL_LEVEL_INFO; + syslogLevel = ASL_LEVEL_NOTICE; // Maps to ULS Default break; case LOG_LEVEL_DEBUG: levelName = "D"; @@ -84,7 +84,7 @@ void logMessage(LogLevel level, FILE *destination, NSString *format, ...) { break; } - asl_log(client, NULL, syslogLevel, "%s %s: %s", levelName, binaryName, [s UTF8String]); + asl_log(client, NULL, syslogLevel, "%s %s: %s", levelName, binaryName.UTF8String, s.UTF8String); } else { [s appendString:@"\n"]; size_t len = [s lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; diff --git a/Source/santad/SNTEventLog.h b/Source/santad/Logs/SNTEventLog.h similarity index 53% rename from Source/santad/SNTEventLog.h rename to Source/santad/Logs/SNTEventLog.h index cc80ae1ae..5f36ce6fd 100644 --- a/Source/santad/SNTEventLog.h +++ b/Source/santad/Logs/SNTEventLog.h @@ -1,4 +1,4 @@ -/// Copyright 2015 Google Inc. All rights reserved. +/// Copyright 2018 Google Inc. All rights reserved. /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -23,15 +23,32 @@ /// Logs execution and file write events to syslog /// @interface SNTEventLog : NSObject - +// Methods implemented by a concrete subclass. - (void)logDiskAppeared:(NSDictionary *)diskProperties; - (void)logDiskDisappeared:(NSDictionary *)diskProperties; - - (void)logFileModification:(santa_message_t)message; - -- (void)saveDecisionDetails:(SNTCachedDecision *)cd; - (void)logDeniedExecution:(SNTCachedDecision *)cd withMessage:(santa_message_t)message; - (void)logAllowedExecution:(santa_message_t)message; - - (void)logBundleHashingEvents:(NSArray *)events; + +// Getter and setter for cached decisions. +- (SNTCachedDecision *)cachedDecisionForMessage:(santa_message_t)message; +- (void)cacheDecision:(SNTCachedDecision *)cd; + +// String formatter helpers. +- (void)addArgsForPid:(pid_t)pid toString:(NSMutableString *)str; +- (NSString *)diskImageForDevice:(NSString *)devPath; +- (NSString *)nameForUID:(uid_t)uid; +- (NSString *)nameForGID:(gid_t)gid; +- (NSString *)sanitizeCString:(const char *)str ofLength:(NSUInteger)length; +- (NSString *)sanitizeString:(NSString *)inStr; +- (NSString *)serialForDevice:(NSString *)devPath; +- (NSString *)originalPathForTranslocation:(santa_message_t)message; + +// A cache for usernames and groups. +@property(readonly, nonatomic) NSCache *userNameMap; +@property(readonly, nonatomic) NSCache *groupNameMap; + +// A UTC Date formatter. +@property(readonly, nonatomic) NSDateFormatter *dateFormatter; @end diff --git a/Source/santad/SNTEventLog.m b/Source/santad/Logs/SNTEventLog.m similarity index 63% rename from Source/santad/SNTEventLog.m rename to Source/santad/Logs/SNTEventLog.m index 86cad8bf0..cc60c307a 100644 --- a/Source/santad/SNTEventLog.m +++ b/Source/santad/Logs/SNTEventLog.m @@ -1,4 +1,4 @@ -/// Copyright 2015 Google Inc. All rights reserved. +/// Copyright 2018 Google Inc. All rights reserved. /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -16,29 +16,14 @@ #include #include -#include #include #include -#import - #import "SNTCachedDecision.h" -#import "SNTCommonEnums.h" -#import "SNTConfigurator.h" -#import "SNTFileInfo.h" -#import "SNTKernelCommon.h" -#import "SNTLogging.h" -#import "SNTStoredEvent.h" @interface SNTEventLog () @property NSMutableDictionary *detailStore; @property dispatch_queue_t detailStoreQueue; - -// Caches for uid->username and gid->groupname lookups. -@property NSCache *userNameMap; -@property NSCache *groupNameMap; - -@property NSDateFormatter *dateFormatter; @end @implementation SNTEventLog @@ -62,223 +47,48 @@ - (instancetype)init { return self; } -- (void)saveDecisionDetails:(SNTCachedDecision *)cd { - dispatch_sync(_detailStoreQueue, ^{ - _detailStore[@(cd.vnodeId)] = cd; - }); +- (void)logDiskAppeared:(NSDictionary *)diskProperties { + [self doesNotRecognizeSelector:_cmd]; } -- (void)logFileModification:(santa_message_t)message { - NSString *action, *newpath; - - NSString *path = @(message.path); - - switch (message.action) { - case ACTION_NOTIFY_DELETE: { - action = @"DELETE"; - break; - } - case ACTION_NOTIFY_EXCHANGE: { - action = @"EXCHANGE"; - newpath = @(message.newpath); - break; - } - case ACTION_NOTIFY_LINK: { - action = @"LINK"; - newpath = @(message.newpath); - break; - } - case ACTION_NOTIFY_RENAME: { - action = @"RENAME"; - newpath = @(message.newpath); - break; - } - case ACTION_NOTIFY_WRITE: { - action = @"WRITE"; - break; - } - default: action = @"UNKNOWN"; break; - } +- (void)logDiskDisappeared:(NSDictionary *)diskProperties { + [self doesNotRecognizeSelector:_cmd]; +} - // init the string with 2k capacity to avoid reallocs - NSMutableString *outStr = [NSMutableString stringWithCapacity:2048]; - [outStr appendFormat:@"action=%@|path=%@", action, [self sanitizeString:path]]; - if (newpath) { - [outStr appendFormat:@"|newpath=%@", [self sanitizeString:newpath]]; - } - char ppath[PATH_MAX] = "(null)"; - proc_pidpath(message.pid, ppath, PATH_MAX); - - [outStr appendFormat:@"|pid=%d|ppid=%d|process=%s|processpath=%s|uid=%d|user=%@|gid=%d|group=%@", - message.pid, message.ppid, message.pname, ppath, - message.uid, [self nameForUID:message.uid], - message.gid, [self nameForGID:message.gid]]; - LOGI(@"%@", outStr); +- (void)logFileModification:(santa_message_t)message { + [self doesNotRecognizeSelector:_cmd]; } - (void)logDeniedExecution:(SNTCachedDecision *)cd withMessage:(santa_message_t)message { - [self logExecution:message withDecision:cd]; + [self doesNotRecognizeSelector:_cmd]; } - (void)logAllowedExecution:(santa_message_t)message { - __block SNTCachedDecision *cd; - dispatch_sync(_detailStoreQueue, ^{ - cd = _detailStore[@(message.vnode_id)]; - }); - [self logExecution:message withDecision:cd]; + [self doesNotRecognizeSelector:_cmd]; } -- (void)logExecution:(santa_message_t)message withDecision:(SNTCachedDecision *)cd { - NSString *d, *r; - BOOL logArgs = NO; - - switch (cd.decision) { - case SNTEventStateAllowBinary: - d = @"ALLOW"; - r = @"BINARY"; - logArgs = YES; - break; - case SNTEventStateAllowCertificate: - d = @"ALLOW"; - r = @"CERT"; - logArgs = YES; - break; - case SNTEventStateAllowScope: - d = @"ALLOW"; - r = @"SCOPE"; - logArgs = YES; - break; - case SNTEventStateAllowUnknown: - d = @"ALLOW"; - r = @"UNKNOWN"; - logArgs = YES; - break; - case SNTEventStateBlockBinary: - d = @"DENY"; - r = @"BINARY"; - break; - case SNTEventStateBlockCertificate: - d = @"DENY"; - r = @"CERT"; - break; - case SNTEventStateBlockScope: - d = @"DENY"; - r = @"SCOPE"; - break; - case SNTEventStateBlockUnknown: - d = @"DENY"; - r = @"UNKNOWN"; - break; - default: - d = @"ALLOW"; - r = @"NOTRUNNING"; - logArgs = YES; - break; - } - - // init the string with 4k capacity to avoid reallocs - NSMutableString *outLog = [[NSMutableString alloc] initWithCapacity:4096]; - [outLog appendFormat:@"action=EXEC|decision=%@|reason=%@", d, r]; - - if (cd.decisionExtra) { - [outLog appendFormat:@"|explain=%@", cd.decisionExtra]; - } - - [outLog appendFormat:@"|sha256=%@", cd.sha256]; - - if (cd.certSHA256) { - [outLog appendFormat:@"|cert_sha256=%@|cert_cn=%@", cd.certSHA256, - [self sanitizeString:cd.certCommonName]]; - } - - if (cd.quarantineURL) { - [outLog appendFormat:@"|quarantine_url=%@", [self sanitizeString:cd.quarantineURL]]; - } - - NSString *mode; - switch ([[SNTConfigurator configurator] clientMode]) { - case SNTClientModeMonitor: - mode = @"M"; break; - case SNTClientModeLockdown: - mode = @"L"; break; - default: - mode = @"U"; break; - } - - [outLog appendFormat:@"|pid=%d|ppid=%d|uid=%d|user=%@|gid=%d|group=%@|mode=%@|path=%@", - message.pid, message.ppid, - message.uid, [self nameForUID:message.uid], - message.gid, [self nameForGID:message.gid], - mode, [self sanitizeString:@(message.path)]]; - - // Check for app translocation by GateKeeper, and log original path if the case. - NSString *originalPath = [self originalPathForTranslocation:message]; - if (originalPath) { - [outLog appendFormat:@"|origpath=%@", [self sanitizeString:originalPath]]; - } - - if (logArgs) { - [self addArgsForPid:message.pid toString:outLog]; - } - - LOGI(@"%@", outLog); +- (void)logBundleHashingEvents:(NSArray *)events { + [self doesNotRecognizeSelector:_cmd]; } -- (void)logDiskAppeared:(NSDictionary *)diskProperties { - NSString *dmgPath = @""; - NSString *serial = @""; - if ([diskProperties[@"DADeviceModel"] isEqual:@"Disk Image"]) { - dmgPath = [self diskImageForDevice:diskProperties[@"DADevicePath"]]; - } else { - serial = [self serialForDevice:diskProperties[@"DADevicePath"]]; - serial = [serial stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - } - - NSString *model = [NSString stringWithFormat:@"%@ %@", - diskProperties[@"DADeviceVendor"] ?: @"", - diskProperties[@"DADeviceModel"] ?: @""]; - model = [model stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - - double appearance = [diskProperties[@"DAAppearanceTime"] doubleValue]; - NSString *appearanceDateString = - [_dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSinceReferenceDate:appearance]]; - - NSString *log = - @"action=DISKAPPEAR|mount=%@|volume=%@|bsdname=%@|fs=%@|" - @"model=%@|serial=%@|bus=%@|dmgpath=%@|appearance=%@"; - LOGI(log, - [diskProperties[@"DAVolumePath"] path] ?: @"", - diskProperties[@"DAVolumeName"] ?: @"", - diskProperties[@"DAMediaBSDName"] ?: @"", - diskProperties[@"DAVolumeKind"] ?: @"", - model ?: @"", - serial, - diskProperties[@"DADeviceProtocol"] ?: @"", - dmgPath, - appearanceDateString); +- (void)writeLog:(NSString *)log { + [self doesNotRecognizeSelector:_cmd]; } -- (void)logDiskDisappeared:(NSDictionary *)diskProperties { - LOGI(@"action=DISKDISAPPEAR|mount=%@|volume=%@|bsdname=%@", - [diskProperties[@"DAVolumePath"] path] ?: @"", - diskProperties[@"DAVolumeName"] ?: @"", - diskProperties[@"DAMediaBSDName"]); +- (void)cacheDecision:(SNTCachedDecision *)cd { + dispatch_sync(self.detailStoreQueue, ^{ + self.detailStore[@(cd.vnodeId)] = cd; + }); } -- (void)logBundleHashingEvents:(NSArray *)events { - for (SNTStoredEvent *event in events) { - LOGI(@"action=BUNDLE|sha256=%@|bundlehash=%@|bundlename=%@|bundleid=%@|bundlepath=%@|path=%@", - event.fileSHA256, - event.fileBundleHash, - event.fileBundleName, - event.fileBundleID, - event.fileBundlePath, - event.filePath); - } +- (SNTCachedDecision *)cachedDecisionForMessage:(santa_message_t)message { + __block SNTCachedDecision *cd; + dispatch_sync(self.detailStoreQueue, ^{ + cd = self.detailStore[@(message.vnode_id)]; + }); + return cd; } -#pragma mark Helpers - /** Sanitizes a given string if necessary, otherwise returns the original. */ diff --git a/Source/santad/Logs/SNTFileEventLog.h b/Source/santad/Logs/SNTFileEventLog.h new file mode 100644 index 000000000..f95db70fd --- /dev/null +++ b/Source/santad/Logs/SNTFileEventLog.h @@ -0,0 +1,18 @@ +/// Copyright 2018 Google Inc. All rights reserved. +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. + +#import "SNTSyslogEventLog.h" + +@interface SNTFileEventLog : SNTSyslogEventLog +@end diff --git a/Source/santad/Logs/SNTFileEventLog.m b/Source/santad/Logs/SNTFileEventLog.m new file mode 100644 index 000000000..1859bf864 --- /dev/null +++ b/Source/santad/Logs/SNTFileEventLog.m @@ -0,0 +1,101 @@ +/// Copyright 2018 Google Inc. All rights reserved. +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. + +#import "SNTFileEventLog.h" + +#import "SNTConfigurator.h" +#import "SNTLogging.h" +#import "SNTStrengthify.h" + +@interface SNTFileEventLog () +@property NSFileHandle *fh; +@property(readonly, nonatomic) dispatch_queue_t q; +@property dispatch_source_t source; +@property(readonly, nonatomic) dispatch_source_t timer; +@property(readonly, nonatomic) NSString *path; +@property(readonly, nonatomic) NSMutableData *buffer; +@end + +@implementation SNTFileEventLog + +- (instancetype)init { + self = [super init]; + if (self) { + _q = dispatch_queue_create("com.google.santa.file_event_log", DISPATCH_QUEUE_SERIAL); + _path = [[SNTConfigurator configurator] eventLogPath]; + _fh = [self fileHandleForPath:_path]; + [self watchLogFile]; + // 8k buffer to batch logs for writing. + _buffer = [NSMutableData dataWithCapacity:8192]; + // To avoid long lulls in the log being updated, flush the buffer every second. + _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _q); + dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC * 1, 0); + WEAKIFY(self); + dispatch_source_set_event_handler(_timer, ^{ + STRONGIFY(self); + [self flushBuffer]; + }); + dispatch_resume(_timer); + } + return self; +} + +- (NSFileHandle *)fileHandleForPath:(NSString *)path { + NSFileManager *fm = [NSFileManager defaultManager]; + if (![fm fileExistsAtPath:path]) { + [fm createFileAtPath:path contents:nil attributes:nil]; + } + NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:path]; + [fh seekToEndOfFile]; + return fh; +} + +- (void)watchLogFile { + if (self.source) { + dispatch_source_set_event_handler_f(self.source, NULL); + dispatch_source_cancel(self.source); + } + self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, + self.fh.fileDescriptor, + DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME, + self.q); + WEAKIFY(self); + dispatch_source_set_event_handler(self.source, ^{ + STRONGIFY(self); + [self.fh closeFile]; + self.fh = [self fileHandleForPath:self.path]; + [self watchLogFile]; + }); + dispatch_resume(self.source); +} + +- (void)writeLog:(NSString *)log { + dispatch_async(self.q, ^{ + NSString *dateString = [self.dateFormatter stringFromDate:[NSDate date]]; + NSString *outLog = [NSString stringWithFormat:@"[%@] I santad: %@\n", dateString, log]; + [self.buffer appendBytes:outLog.UTF8String + length:[outLog lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + // Avoid excessive calls to write() by batching logs. + if (self.buffer.length >= 4096) { + [self flushBuffer]; + } + }); +} + +- (void)flushBuffer { + write(self.fh.fileDescriptor, self.buffer.bytes, self.buffer.length); + [self.buffer setLength:0]; +} + +@end diff --git a/Source/santad/Logs/SNTSyslogEventLog.h b/Source/santad/Logs/SNTSyslogEventLog.h new file mode 100644 index 000000000..4a5dc6303 --- /dev/null +++ b/Source/santad/Logs/SNTSyslogEventLog.h @@ -0,0 +1,18 @@ +/// Copyright 2018 Google Inc. All rights reserved. +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. + +#import "SNTEventLog.h" + +@interface SNTSyslogEventLog : SNTEventLog +@end diff --git a/Source/santad/Logs/SNTSyslogEventLog.m b/Source/santad/Logs/SNTSyslogEventLog.m new file mode 100644 index 000000000..6798d1ef3 --- /dev/null +++ b/Source/santad/Logs/SNTSyslogEventLog.m @@ -0,0 +1,242 @@ +/// Copyright 2018 Google Inc. All rights reserved. +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. + +#import "SNTSyslogEventLog.h" + +#import + +#import "SNTCachedDecision.h" +#import "SNTConfigurator.h" +#import "SNTLogging.h" +#import "SNTStoredEvent.h" + +@implementation SNTSyslogEventLog + +- (void)logFileModification:(santa_message_t)message { + NSString *action, *newpath; + + NSString *path = @(message.path); + + switch (message.action) { + case ACTION_NOTIFY_DELETE: { + action = @"DELETE"; + break; + } + case ACTION_NOTIFY_EXCHANGE: { + action = @"EXCHANGE"; + newpath = @(message.newpath); + break; + } + case ACTION_NOTIFY_LINK: { + action = @"LINK"; + newpath = @(message.newpath); + break; + } + case ACTION_NOTIFY_RENAME: { + action = @"RENAME"; + newpath = @(message.newpath); + break; + } + case ACTION_NOTIFY_WRITE: { + action = @"WRITE"; + break; + } + default: action = @"UNKNOWN"; break; + } + + // init the string with 2k capacity to avoid reallocs + NSMutableString *outStr = [NSMutableString stringWithCapacity:2048]; + [outStr appendFormat:@"action=%@|path=%@", action, [self sanitizeString:path]]; + if (newpath) { + [outStr appendFormat:@"|newpath=%@", [self sanitizeString:newpath]]; + } + char ppath[PATH_MAX] = "(null)"; + proc_pidpath(message.pid, ppath, PATH_MAX); + + [outStr appendFormat:@"|pid=%d|ppid=%d|process=%s|processpath=%s|uid=%d|user=%@|gid=%d|group=%@", + message.pid, message.ppid, message.pname, ppath, + message.uid, [self nameForUID:message.uid], + message.gid, [self nameForGID:message.gid]]; + + [self writeLog:outStr]; +} + +- (void)logExecution:(santa_message_t)message withDecision:(SNTCachedDecision *)cd { + NSString *d, *r; + BOOL logArgs = NO; + + switch (cd.decision) { + case SNTEventStateAllowBinary: + d = @"ALLOW"; + r = @"BINARY"; + logArgs = YES; + break; + case SNTEventStateAllowCertificate: + d = @"ALLOW"; + r = @"CERT"; + logArgs = YES; + break; + case SNTEventStateAllowScope: + d = @"ALLOW"; + r = @"SCOPE"; + logArgs = YES; + break; + case SNTEventStateAllowUnknown: + d = @"ALLOW"; + r = @"UNKNOWN"; + logArgs = YES; + break; + case SNTEventStateBlockBinary: + d = @"DENY"; + r = @"BINARY"; + break; + case SNTEventStateBlockCertificate: + d = @"DENY"; + r = @"CERT"; + break; + case SNTEventStateBlockScope: + d = @"DENY"; + r = @"SCOPE"; + break; + case SNTEventStateBlockUnknown: + d = @"DENY"; + r = @"UNKNOWN"; + break; + default: + d = @"ALLOW"; + r = @"NOTRUNNING"; + logArgs = YES; + break; + } + + // init the string with 4k capacity to avoid reallocs + NSMutableString *outLog = [[NSMutableString alloc] initWithCapacity:4096]; + [outLog appendFormat:@"action=EXEC|decision=%@|reason=%@", d, r]; + + if (cd.decisionExtra) { + [outLog appendFormat:@"|explain=%@", cd.decisionExtra]; + } + + [outLog appendFormat:@"|sha256=%@", cd.sha256]; + + if (cd.certSHA256) { + [outLog appendFormat:@"|cert_sha256=%@|cert_cn=%@", cd.certSHA256, + [self sanitizeString:cd.certCommonName]]; + } + + if (cd.quarantineURL) { + [outLog appendFormat:@"|quarantine_url=%@", [self sanitizeString:cd.quarantineURL]]; + } + + NSString *mode; + switch ([[SNTConfigurator configurator] clientMode]) { + case SNTClientModeMonitor: + mode = @"M"; break; + case SNTClientModeLockdown: + mode = @"L"; break; + default: + mode = @"U"; break; + } + + [outLog appendFormat:@"|pid=%d|ppid=%d|uid=%d|user=%@|gid=%d|group=%@|mode=%@|path=%@", + message.pid, message.ppid, + message.uid, [self nameForUID:message.uid], + message.gid, [self nameForGID:message.gid], + mode, [self sanitizeString:@(message.path)]]; + + // Check for app translocation by GateKeeper, and log original path if the case. + NSString *originalPath = [self originalPathForTranslocation:message]; + if (originalPath) { + [outLog appendFormat:@"|origpath=%@", [self sanitizeString:originalPath]]; + } + + if (logArgs) { + [self addArgsForPid:message.pid toString:outLog]; + } + + [self writeLog:outLog]; +} + +- (void)logDeniedExecution:(SNTCachedDecision *)cd withMessage:(santa_message_t)message { + [self logExecution:message withDecision:cd]; +} + +- (void)logAllowedExecution:(santa_message_t)message { + SNTCachedDecision *cd = [self cachedDecisionForMessage:message]; + [self logExecution:message withDecision:cd]; +} + +- (void)logDiskAppeared:(NSDictionary *)diskProperties { + NSString *dmgPath = @""; + NSString *serial = @""; + if ([diskProperties[@"DADeviceModel"] isEqual:@"Disk Image"]) { + dmgPath = [self diskImageForDevice:diskProperties[@"DADevicePath"]]; + } else { + serial = [self serialForDevice:diskProperties[@"DADevicePath"]]; + serial = [serial stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + } + + NSString *model = [NSString stringWithFormat:@"%@ %@", + diskProperties[@"DADeviceVendor"] ?: @"", + diskProperties[@"DADeviceModel"] ?: @""]; + model = [model stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + double a = [diskProperties[@"DAAppearanceTime"] doubleValue]; + NSString *appearanceDateString = + [self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSinceReferenceDate:a]]; + + NSString *format = + @"action=DISKAPPEAR|mount=%@|volume=%@|bsdname=%@|fs=%@|" + @"model=%@|serial=%@|bus=%@|dmgpath=%@|appearance=%@"; + NSString *outLog = [NSMutableString stringWithFormat:format, + [diskProperties[@"DAVolumePath"] path] ?: @"", + diskProperties[@"DAVolumeName"] ?: @"", + diskProperties[@"DAMediaBSDName"] ?: @"", + diskProperties[@"DAVolumeKind"] ?: @"", + model ?: @"", + serial, + diskProperties[@"DADeviceProtocol"] ?: @"", + dmgPath, + appearanceDateString]; + [self writeLog:outLog]; +} + +- (void)logDiskDisappeared:(NSDictionary *)diskProperties { + NSString *format = @"action=DISKDISAPPEAR|mount=%@|volume=%@|bsdname=%@"; + NSString *outLog = [NSMutableString stringWithFormat:format, + [diskProperties[@"DAVolumePath"] path] ?: @"", + diskProperties[@"DAVolumeName"] ?: @"", + diskProperties[@"DAMediaBSDName"]]; + [self writeLog:outLog]; +} + +- (void)logBundleHashingEvents:(NSArray *)events { + for (SNTStoredEvent *event in events) { + NSString *format = @"action=DISKDISAPPEAR|mount=%@|volume=%@|bsdname=%@"; + NSString *outLog = [NSMutableString stringWithFormat:format, + event.fileSHA256, + event.fileBundleHash, + event.fileBundleName, + event.fileBundleID, + event.fileBundlePath, + event.filePath]; + [self writeLog:outLog]; + } +} + +- (void)writeLog:(NSString *)log { + LOGI(@"%@", log); +} + +@end diff --git a/Source/santad/SNTApplication.m b/Source/santad/SNTApplication.m index a5e2fbc68..bcb338e83 100644 --- a/Source/santad/SNTApplication.m +++ b/Source/santad/SNTApplication.m @@ -22,13 +22,14 @@ #import "SNTDatabaseController.h" #import "SNTDriverManager.h" #import "SNTDropRootPrivs.h" -#import "SNTEventLog.h" #import "SNTEventTable.h" #import "SNTExecutionController.h" +#import "SNTFileEventLog.h" #import "SNTLogging.h" #import "SNTNotificationQueue.h" #import "SNTRuleTable.h" #import "SNTSyncdQueue.h" +#import "SNTSyslogEventLog.h" #import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" #import "SNTXPCNotifierInterface.h" @@ -68,7 +69,16 @@ - (instancetype)init { return nil; } - _eventLog = [[SNTEventLog alloc] init]; + // Choose an event logger. + SNTConfigurator *configurator = [SNTConfigurator configurator]; + switch ([configurator eventLogType]) { + case SNTEventLogTypeSyslog: + _eventLog = [[SNTSyslogEventLog alloc] init]; + break; + case SNTEventLogTypeFilelog: + _eventLog = [[SNTFileEventLog alloc] init]; + break; + } self.notQueue = [[SNTNotificationQueue alloc] init]; SNTSyncdQueue *syncdQueue = [[SNTSyncdQueue alloc] init]; @@ -80,7 +90,6 @@ - (instancetype)init { // Listen for actionable config changes. NSKeyValueObservingOptions bits = (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld); - SNTConfigurator *configurator = [SNTConfigurator configurator]; [configurator addObserver:self forKeyPath:NSStringFromSelector(@selector(clientMode)) options:bits diff --git a/Source/santad/SNTDaemonControlController.m b/Source/santad/SNTDaemonControlController.m index 0ca6fc738..96eae6958 100644 --- a/Source/santad/SNTDaemonControlController.m +++ b/Source/santad/SNTDaemonControlController.m @@ -225,6 +225,7 @@ - (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener { bs.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface]; [bs resume]; [[bs remoteObjectProxy] setBundleNotificationListener:listener]; + [bs invalidate]; } #pragma mark syncd Ops diff --git a/Source/santad/SNTExecutionController.m b/Source/santad/SNTExecutionController.m index 65269a00b..796fe1798 100644 --- a/Source/santad/SNTExecutionController.m +++ b/Source/santad/SNTExecutionController.m @@ -134,7 +134,7 @@ - (void)validateBinaryWithMessage:(santa_message_t)message { (SNTEventStateAllow & cd.decision) ? ACTION_RESPOND_ALLOW : ACTION_RESPOND_DENY; // Save decision details for logging the execution later. - if (action == ACTION_RESPOND_ALLOW) [_eventLog saveDecisionDetails:cd]; + if (action == ACTION_RESPOND_ALLOW) [_eventLog cacheDecision:cd]; // Send the decision to the kernel. [_driverManager postToKernelAction:action forVnodeID:cd.vnodeId]; From 1cf8ee09e18df405a9a27c14b617403c593d342b Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Mon, 9 Apr 2018 13:34:33 -0400 Subject: [PATCH 15/25] sync-state: Mitigate com.apple.ManagedClient flapping (#248) * sync-state: Mitigate com.apple.ManagedClient flapping * 10 min --- Source/santad/SNTApplication.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/santad/SNTApplication.m b/Source/santad/SNTApplication.m index bcb338e83..90c001188 100644 --- a/Source/santad/SNTApplication.m +++ b/Source/santad/SNTApplication.m @@ -318,11 +318,17 @@ - (void)clientModeDidChange:(SNTClientMode)clientMode { - (void)syncBaseURLDidChange:(NSURL *)syncBaseURL { if (syncBaseURL) { LOGI(@"Starting santactl with new SyncBaseURL: %@", syncBaseURL); + [NSObject cancelPreviousPerformRequestsWithTarget:[SNTConfigurator configurator] + selector:@selector(clearSyncState) + object:nil]; [self startSyncd]; } else { LOGI(@"SyncBaseURL removed, killing santactl pid: %i", self.syncdPID); [self stopSyncd]; - [[SNTConfigurator configurator] clearSyncState]; + // Keep the syncState active for 10 min in case com.apple.ManagedClient is flapping. + [[SNTConfigurator configurator] performSelector:@selector(clearSyncState) + withObject:nil + afterDelay:600]; } } From 5ee6531627d1e44e2d1a4979fbfbeef0eb652610 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Tue, 24 Apr 2018 16:11:49 -0400 Subject: [PATCH 16/25] santad / santactl: validate all architectures within universal binaries (#249) --- Podfile.lock | 4 +- Source/common/SNTFileInfo.h | 5 ++ Source/common/SNTFileInfo.m | 30 ++++---- Source/santactl/Commands/SNTCommandFileInfo.m | 74 +++++++++++++++++-- Source/santad/SNTExecutionController.m | 8 +- Tests/LogicTests/SNTExecutionControllerTest.m | 5 +- 6 files changed, 96 insertions(+), 30 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index e73799026..d37415248 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -5,7 +5,7 @@ PODS: - MOLAuthenticatingURLSession (2.4): - MOLCertificate (~> 1.8) - MOLCertificate (1.8) - - MOLCodesignChecker (1.9): + - MOLCodesignChecker (1.10): - MOLCertificate (~> 1.8) - MOLFCMClient (1.7): - MOLAuthenticatingURLSession (~> 2.4) @@ -23,7 +23,7 @@ SPEC CHECKSUMS: FMDB: 6198a90e7b6900cfc046e6bc0ef6ebb7be9236aa MOLAuthenticatingURLSession: c238aa1c9a7b1077eb39a6f40204bfe76a7d204e MOLCertificate: c999513316d511c69f290fbf313dfe8dca4ad592 - MOLCodesignChecker: 303c01755646a0045c97f9f0b0fe5945ead42130 + MOLCodesignChecker: b0d5db9d2f9bd94e0fd093891a5d40e5ad77cbc0 MOLFCMClient: ee45348909351f232e2759c580329072ae7e02d4 OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3 diff --git a/Source/common/SNTFileInfo.h b/Source/common/SNTFileInfo.h index 0ed73bc84..2099782b7 100644 --- a/Source/common/SNTFileInfo.h +++ b/Source/common/SNTFileInfo.h @@ -212,6 +212,11 @@ /// - (NSUInteger)fileSize; +/// +/// @return The underlying file handle. +/// +@property(readonly) NSFileHandle *fileHandle; + /// /// @return Returns an instance of MOLCodeSignChecker initialized with the file's binary path. /// Both the MOLCodesignChecker and any resulting NSError are cached and returned on subsequent diff --git a/Source/common/SNTFileInfo.m b/Source/common/SNTFileInfo.m index 05eebabe6..b87c9ebc3 100644 --- a/Source/common/SNTFileInfo.m +++ b/Source/common/SNTFileInfo.m @@ -17,6 +17,7 @@ #import #import +#include #include #include #include @@ -287,7 +288,8 @@ - (NSString *)humanReadableFileType { - (BOOL)isMissingPageZero { // This method only checks i386 arch because the kernel enforces this for other archs // See bsd/kern/mach_loader.c, search for enforce_hard_pagezero. - MachHeaderWithOffset *x86Header = self.machHeaders[[self nameForCPUType:CPU_TYPE_X86]]; + MachHeaderWithOffset *x86Header = self.machHeaders[[self nameForCPUType:CPU_TYPE_X86 + cpuSubType:CPU_SUBTYPE_I386_ALL]]; if (!x86Header) return NO; struct mach_header *mh = (struct mach_header *)[x86Header.data bytes]; @@ -443,7 +445,7 @@ - (NSDictionary *)machHeaders { if (machHeader) { struct mach_header *mh = (struct mach_header *)[machHeader bytes]; MachHeaderWithOffset *mhwo = [[MachHeaderWithOffset alloc] initWithData:machHeader offset:0]; - machHeaders[[self nameForCPUType:mh->cputype]] = mhwo; + machHeaders[[self nameForCPUType:mh->cputype cpuSubType:mh->cpusubtype]] = mhwo; } else { NSRange range = NSMakeRange(0, sizeof(struct fat_header)); NSData *fatHeader = [self safeSubdataWithRange:range]; @@ -459,11 +461,12 @@ - (NSDictionary *)machHeaders { int offset = OSSwapBigToHostInt32(fat_arch[i].offset); int size = OSSwapBigToHostInt32(fat_arch[i].size); int cputype = OSSwapBigToHostInt(fat_arch[i].cputype); + int cpusubtype = OSSwapBigToHostInt(fat_arch[i].cpusubtype); range = NSMakeRange(offset, size); NSData *machHeader = [self parseSingleMachHeader:[self safeSubdataWithRange:range]]; if (machHeader) { - NSString *key = [self nameForCPUType:cputype]; + NSString *key = [self nameForCPUType:cputype cpuSubType:cpusubtype]; MachHeaderWithOffset *mhwo = [[MachHeaderWithOffset alloc] initWithData:machHeader offset:offset]; machHeaders[key] = mhwo; @@ -647,20 +650,15 @@ - (NSDictionary *)quarantineData { /// /// Return a human-readable string for a cpu_type_t. /// -- (NSString *)nameForCPUType:(cpu_type_t)cpuType { - switch (cpuType) { - case CPU_TYPE_X86: - return @"i386"; - case CPU_TYPE_X86_64: - return @"x86-64"; - case CPU_TYPE_POWERPC: - return @"ppc"; - case CPU_TYPE_POWERPC64: - return @"ppc64"; - default: - return @"unknown"; +- (NSString *)nameForCPUType:(cpu_type_t)cpuType cpuSubType:(cpu_subtype_t)cpuSubType { + const NXArchInfo *archInfo = NXGetArchInfoFromCpuType(cpuType, cpuSubType); + NSString *arch; + if (archInfo && archInfo->name) { + arch = @(archInfo->name); + } else { + arch = [NSString stringWithFormat:@"%i:%i", cpuType, cpuSubType]; } - return nil; + return arch; } /// diff --git a/Source/santactl/Commands/SNTCommandFileInfo.m b/Source/santactl/Commands/SNTCommandFileInfo.m index 58d0acd57..ab92c7798 100644 --- a/Source/santactl/Commands/SNTCommandFileInfo.m +++ b/Source/santactl/Commands/SNTCommandFileInfo.m @@ -42,6 +42,7 @@ static NSString *const kCodeSigned = @"Code-signed"; static NSString *const kRule = @"Rule"; static NSString *const kSigningChain = @"Signing Chain"; +static NSString *const kUniversalSigningChain = @"Universal Signing Chain"; // signing chain keys static NSString *const kCommonName = @"Common Name"; @@ -115,6 +116,7 @@ @interface SNTCommandFileInfo : SNTCommand @property(readonly, copy, nonatomic) SNTAttributeBlock codeSigned; @property(readonly, copy, nonatomic) SNTAttributeBlock rule; @property(readonly, copy, nonatomic) SNTAttributeBlock signingChain; +@property(readonly, copy, nonatomic) SNTAttributeBlock universalSigningChain; // Mapping between property string keys and SNTAttributeBlocks @property(nonatomic) NSDictionary *propertyMap; @@ -182,7 +184,7 @@ + (NSString *)longHelpText { + (NSArray *)fileInfoKeys { return @[ kPath, kSHA256, kSHA1, kBundleName, kBundleVersion, kBundleVersionStr, kDownloadReferrerURL, kDownloadURL, kDownloadTimestamp, kDownloadAgent, - kType, kPageZero, kCodeSigned, kRule, kSigningChain ]; + kType, kPageZero, kCodeSigned, kRule, kSigningChain, kUniversalSigningChain ]; } + (NSArray *)signingChainKeys { @@ -210,7 +212,8 @@ - (instancetype)initWithDaemonConnection:(SNTXPCConnection *)daemonConn { kPageZero : self.pageZero, kCodeSigned : self.codeSigned, kRule : self.rule, - kSigningChain : self.signingChain }; + kSigningChain : self.signingChain, + kUniversalSigningChain : self.universalSigningChain }; _printQueue = dispatch_queue_create("com.google.santactl.print_queue", DISPATCH_QUEUE_SERIAL); } @@ -325,6 +328,10 @@ - (SNTAttributeBlock)codeSigned { return @"Yes, but failed requirement validation"; case errSecCSInfoPlistFailed: return @"Yes, but can't validate as Info.plist is missing"; + case errSecCSSignatureInvalid: + if ([error.domain isEqualToString:@"com.google.molcodesignchecker"]) { + return @"Yes, but signing is not consistent for all architectures"; + } default: { return [NSString stringWithFormat:@"Yes, but failed to validate (%ld)", error.code]; } @@ -418,6 +425,46 @@ - (SNTAttributeBlock)signingChain { }; } +- (SNTAttributeBlock)universalSigningChain { + return ^id (SNTCommandFileInfo *cmd, SNTFileInfo *fileInfo) { + MOLCodesignChecker *csc = [fileInfo codesignCheckerWithError:NULL]; + if (csc.certificates.count) return nil; + if (!csc.universalSigningInformation) return nil; + NSMutableArray *universal = [NSMutableArray array]; + for (NSDictionary *arch in csc.universalSigningInformation) { + [universal addObject:@{ @"arch" : arch.allKeys.firstObject }]; + int flags = [arch.allValues.firstObject[(__bridge id)kSecCodeInfoFlags] intValue]; + if (flags & kSecCodeSignatureAdhoc) { + [universal addObject:@{ @"ad-hoc" : @YES }]; + continue; + } + NSArray *certs = arch.allValues.firstObject[(__bridge id)kSecCodeInfoCertificates]; + NSArray *chain = [MOLCertificate certificatesFromArray:certs]; + if (!chain.count) { + [universal addObject:@{ @"unsigned" : @YES }]; + continue; + } + for (MOLCertificate *c in chain) { + [universal addObject:@{ + kSHA256 : c.SHA256 ?: @"null", + kSHA1 : c.SHA1 ?: @"null", + kCommonName : c.commonName ?: @"null", + kOrganization : c.orgName ?: @"null", + kOrganizationalUnit : c.orgUnit ?: @"null", + kValidFrom : [cmd.dateFormatter stringFromDate:c.validFrom] ?: @"null", + kValidUntil : [cmd.dateFormatter stringFromDate:c.validUntil] ?: @"null" + }]; + } + } + NSMutableSet *set = [NSMutableSet set]; + for (NSDictionary *cert in universal) { + if (cert[@"arch"]) continue; + [set addObject:cert]; + } + return (set.count > 1) ? universal : nil; + }; +} + # pragma mark - // Entry point for the command. @@ -591,8 +638,8 @@ - (void)printInfoForFile:(NSString *)path { } else { for (NSString *key in self.outputKeyList) { if (![outputDict objectForKey:key]) continue; - if ([key isEqual:kSigningChain]) { - [output appendString:[self stringForSigningChain:outputDict[key]]]; + if ([key isEqual:kSigningChain] || [key isEqual:kUniversalSigningChain]) { + [output appendString:[self stringForSigningChain:outputDict[key] key:key]]; } else { if (singleKey) { [output appendFormat:@"%@\n", outputDict[key]]; @@ -729,14 +776,25 @@ - (NSString *)jsonStringForDictionary:(NSDictionary *)dict { return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; } -- (NSString *)stringForSigningChain:(NSArray *)signingChain { +- (NSString *)stringForSigningChain:(NSArray *)signingChain key:(NSString *)key { if (!signingChain) return @""; NSMutableString *result = [NSMutableString string]; - [result appendFormat:@"%@:\n", kSigningChain]; + [result appendFormat:@"%@:\n", key]; int i = 1; NSArray *certKeys = [[self class] signingChainKeys]; for (NSDictionary *cert in signingChain) { if ([cert isEqual:[NSNull null]]) continue; + if (cert[@"arch"]) { + [result appendFormat:@" %2@\n", [@"Architecture: " stringByAppendingString:cert[@"arch"]]]; + i = 1; + continue; + } else if (cert[@"ad-hoc"]) { + [result appendFormat:@" %2d. %-20@\n", i, @"ad-hoc"]; + continue; + } else if (cert[@"unsigned"]) { + [result appendFormat:@" %2d. %-20@\n", i, @"unsigned"]; + continue; + } if (i > 1) [result appendFormat:@"\n"]; [result appendString:[self stringForCertificate:cert withKeys:certKeys index:i]]; i += 1; @@ -750,10 +808,10 @@ - (NSString *)stringForCertificate:(NSDictionary *)cert withKeys:(NSArray *)keys BOOL firstKey = YES; for (NSString *key in keys) { if (firstKey) { - [result appendFormat:@" %2d. %-20s: %@\n", index, key.UTF8String, cert[key]]; + [result appendFormat:@" %2d. %-20s: %@\n", index, key.UTF8String, cert[key]]; firstKey = NO; } else { - [result appendFormat:@" %-20s: %@\n", key.UTF8String, cert[key]]; + [result appendFormat:@" %-20s: %@\n", key.UTF8String, cert[key]]; } } return result.copy; diff --git a/Source/santad/SNTExecutionController.m b/Source/santad/SNTExecutionController.m index 796fe1798..466aba2cb 100644 --- a/Source/santad/SNTExecutionController.m +++ b/Source/santad/SNTExecutionController.m @@ -117,9 +117,11 @@ - (void)validateBinaryWithMessage:(santa_message_t)message { // Get codesigning info about the file. NSError *csError; - MOLCodesignChecker *csInfo = [[MOLCodesignChecker alloc] initWithBinaryPath:binInfo.path - error:&csError]; - // Ignore codesigning if there are any errors with the signature. + MOLCodesignChecker *csInfo = + [[MOLCodesignChecker alloc] initWithBinaryPath:binInfo.path + fileDescriptor:binInfo.fileHandle.fileDescriptor + error:&csError]; + // Ignore codesigning if there are any errors with the signature. if (csError) csInfo = nil; // Actually make the decision. diff --git a/Tests/LogicTests/SNTExecutionControllerTest.m b/Tests/LogicTests/SNTExecutionControllerTest.m index cb22a7423..1c61d2576 100644 --- a/Tests/LogicTests/SNTExecutionControllerTest.m +++ b/Tests/LogicTests/SNTExecutionControllerTest.m @@ -47,7 +47,10 @@ - (void)setUp { self.mockCodesignChecker = OCMClassMock([MOLCodesignChecker class]); OCMStub([self.mockCodesignChecker alloc]).andReturn(self.mockCodesignChecker); - OCMStub([self.mockCodesignChecker initWithBinaryPath:OCMOCK_ANY error:[OCMArg setTo:NULL]]) + + OCMStub([self.mockCodesignChecker initWithBinaryPath:OCMOCK_ANY + fileDescriptor:0 + error:[OCMArg setTo:NULL]]) .andReturn(self.mockCodesignChecker); self.mockConfigurator = OCMClassMock([SNTConfigurator class]); From e2adfdf3cf0b13cd448190f1f0e1e659d92ddb0c Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Tue, 24 Apr 2018 16:33:53 -0400 Subject: [PATCH 17/25] Add EventLog Docs (#250) --- Docs/deployment/configuration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Docs/deployment/configuration.md b/Docs/deployment/configuration.md index ea71dde2a..b280641ee 100644 --- a/Docs/deployment/configuration.md +++ b/Docs/deployment/configuration.md @@ -35,6 +35,8 @@ Two configuration methods can be used to control Santa: a local configuration pr | MachineOwnerKey | String | The key to use on MachineOwnerPlist. | | MachineIDPlist | String | The path to a plist that contains the MachineOwnerKey / value pair. | | MachineIDKey | String | The key to use on MachineIDPlist. | +| EventLogType | String | Defines how event logs are stored. Options are 1) syslog: Sent to ASL or ULS (if built with the 10.12 SDK or later). 2) filelog: Sent to a file on disk. Use EventLogPath to specify a path. Defaults to filelog | +| EventLogPath | String | If EventLogType is set to filelog, EventLogPath will provide the path to save logs. Defaults to /var/db/santa/santa.log. If you change this value ensure you also update com.google.santa.newsyslog.conf with the new path. | *overridable by the sync server: run `santactl status` to check the current running config From ea5a6c343817e8205a5e841f8394b62eaaa2f9fd Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Wed, 25 Apr 2018 16:16:56 -0400 Subject: [PATCH 18/25] downstream --> upstream changes (#251) --- Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m | 4 ++-- Source/santactl/Commands/sync/SNTCommandSyncManager.m | 2 +- Source/santactl/Resources/santactl-Info.plist | 2 +- Source/santad/Resources/santad-Info.plist | 2 +- Tests/LogicTests/SNTCommandFileInfoTest.m | 3 ++- Tests/LogicTests/SNTEventTableTest.m | 3 ++- Tests/LogicTests/SNTExecutionControllerTest.m | 5 +++-- Tests/LogicTests/SNTXPCConnectionTest.m | 2 +- 8 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m b/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m index 10c975c23..abe902760 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m @@ -16,8 +16,8 @@ #include "SNTLogging.h" -#import "MOLCertificate.h" -#import "MOLCodesignChecker.h" +#import + #import "NSData+Zlib.h" #import "SNTCommandSyncConstants.h" #import "SNTCommandSyncState.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncManager.m b/Source/santactl/Commands/sync/SNTCommandSyncManager.m index 7f7a36bc1..0e3cb6059 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncManager.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncManager.m @@ -16,7 +16,7 @@ @import SystemConfiguration; -#import +#import #import #import "SNTConfigurator.h" diff --git a/Source/santactl/Resources/santactl-Info.plist b/Source/santactl/Resources/santactl-Info.plist index 2875b9d75..12eadf04d 100644 --- a/Source/santactl/Resources/santactl-Info.plist +++ b/Source/santactl/Resources/santactl-Info.plist @@ -7,7 +7,7 @@ NSHumanReadableCopyright Google, Inc. CFBundleIdentifier - com.google.${PRODUCT_NAME:rfc1034identifier} + com.google.santactl CFBundleName ${PRODUCT_NAME} CFBundleShortVersionString diff --git a/Source/santad/Resources/santad-Info.plist b/Source/santad/Resources/santad-Info.plist index 72b6d5d9c..aa473d467 100644 --- a/Source/santad/Resources/santad-Info.plist +++ b/Source/santad/Resources/santad-Info.plist @@ -7,7 +7,7 @@ NSHumanReadableCopyright Google, Inc. CFBundleIdentifier - com.google.${PRODUCT_NAME:rfc1034identifier} + com.google.santad CFBundleName ${PRODUCT_NAME} CFBundleVersion diff --git a/Tests/LogicTests/SNTCommandFileInfoTest.m b/Tests/LogicTests/SNTCommandFileInfoTest.m index fe253ca8c..954b379ce 100644 --- a/Tests/LogicTests/SNTCommandFileInfoTest.m +++ b/Tests/LogicTests/SNTCommandFileInfoTest.m @@ -16,7 +16,8 @@ #import -#import "MOLCodesignChecker.h" +#import + #import "SNTFileInfo.h" #import "SNTXPCConnection.h" diff --git a/Tests/LogicTests/SNTEventTableTest.m b/Tests/LogicTests/SNTEventTableTest.m index b1373c594..a3307c15e 100644 --- a/Tests/LogicTests/SNTEventTableTest.m +++ b/Tests/LogicTests/SNTEventTableTest.m @@ -14,7 +14,8 @@ @import XCTest; -#import "MOLCodesignChecker.h" +#import + #import "SNTEventTable.h" #import "SNTFileInfo.h" #import "SNTStoredEvent.h" diff --git a/Tests/LogicTests/SNTExecutionControllerTest.m b/Tests/LogicTests/SNTExecutionControllerTest.m index 1c61d2576..c32a94c0b 100644 --- a/Tests/LogicTests/SNTExecutionControllerTest.m +++ b/Tests/LogicTests/SNTExecutionControllerTest.m @@ -18,8 +18,9 @@ #import "SNTExecutionController.h" -#import "MOLCertificate.h" -#import "MOLCodesignChecker.h" +#import +#import + #import "SNTConfigurator.h" #import "SNTDriverManager.h" #import "SNTEventTable.h" diff --git a/Tests/LogicTests/SNTXPCConnectionTest.m b/Tests/LogicTests/SNTXPCConnectionTest.m index 82f49f391..581170748 100644 --- a/Tests/LogicTests/SNTXPCConnectionTest.m +++ b/Tests/LogicTests/SNTXPCConnectionTest.m @@ -14,9 +14,9 @@ @import XCTest; +#import #import -#import "MOLCodesignChecker.h" #import "SNTXPCConnection.h" @interface SNTXPCConnectionTest : XCTestCase From 59cc038ab266d62323ec1cc0a663d6027bac126d Mon Sep 17 00:00:00 2001 From: Russell Hancox Date: Thu, 26 Apr 2018 17:19:19 -0400 Subject: [PATCH 19/25] All: stop using @import for reasons. (#252) --- Source/SantaGUI/SNTAboutWindowController.h | 2 +- Source/SantaGUI/SNTAccessibleTextField.h | 2 +- Source/SantaGUI/SNTAppDelegate.h | 2 +- Source/SantaGUI/SNTMessageWindow.h | 2 +- Source/SantaGUI/SNTMessageWindowController.h | 2 +- Source/SantaGUI/SNTMessageWindowController.m | 2 +- Source/SantaGUI/SNTNotificationManager.h | 2 +- Source/SantaGUI/main.m | 2 +- Source/common/SNTBlockMessage.h | 4 ++-- Source/common/SNTCommonEnums.h | 2 +- Source/common/SNTConfigurator.h | 2 +- Source/common/SNTDropRootPrivs.h | 2 +- Source/common/SNTFileInfo.h | 2 +- Source/common/SNTLogging.h | 2 +- Source/common/SNTRule.h | 2 +- Source/common/SNTStoredEvent.h | 2 +- Source/common/SNTSystemInfo.h | 2 +- Source/common/SNTXPCBundleServiceInterface.h | 2 +- Source/common/SNTXPCConnection.h | 2 +- Source/common/SNTXPCControlInterface.h | 2 +- Source/common/SNTXPCNotifierInterface.h | 2 +- Source/common/SNTXPCSyncdInterface.h | 2 +- Source/santabs/SNTBundleService.h | 2 +- Source/santabs/main.m | 2 +- Source/santactl/Commands/SNTCommandCheckCache.m | 2 +- Source/santactl/Commands/SNTCommandFileInfo.m | 2 +- Source/santactl/Commands/SNTCommandFlushCache.m | 2 +- Source/santactl/Commands/SNTCommandRule.m | 2 +- Source/santactl/Commands/SNTCommandStatus.m | 2 +- Source/santactl/Commands/SNTCommandVersion.m | 4 ++-- Source/santactl/Commands/sync/NSData+Zlib.h | 2 +- Source/santactl/Commands/sync/SNTCommandSync.m | 2 +- Source/santactl/Commands/sync/SNTCommandSyncConstants.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncEventUpload.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncLogUpload.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncManager.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncManager.m | 2 +- Source/santactl/Commands/sync/SNTCommandSyncPostflight.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncPreflight.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncStage.h | 2 +- Source/santactl/Commands/sync/SNTCommandSyncState.h | 2 +- Source/santactl/SNTCommand.h | 2 +- Source/santactl/SNTCommandController.h | 2 +- Source/santactl/main.m | 2 +- Source/santad/DataLayer/SNTDatabaseTable.h | 2 +- Source/santad/DataLayer/SNTEventTable.h | 2 +- Source/santad/DataLayer/SNTEventTable.m | 4 ++-- Source/santad/DataLayer/SNTRuleTable.h | 2 +- Source/santad/Logs/SNTEventLog.h | 2 +- Source/santad/Logs/SNTEventLog.m | 2 ++ Source/santad/SNTApplication.h | 2 +- Source/santad/SNTApplication.m | 2 +- Source/santad/SNTCachedDecision.h | 2 +- Source/santad/SNTDaemonControlController.h | 2 +- Source/santad/SNTDatabaseController.h | 2 +- Source/santad/SNTDriverManager.h | 2 +- Source/santad/SNTDriverManager.m | 2 +- Source/santad/SNTExecutionController.h | 2 +- Source/santad/SNTNotificationQueue.h | 2 +- Source/santad/SNTPolicyProcessor.h | 2 +- Source/santad/SNTSyncdQueue.h | 2 +- Source/santad/main.m | 2 +- Tests/KernelTests/main.mm | 4 ++-- Tests/LogicTests/SNTCommandFileInfoTest.m | 2 +- Tests/LogicTests/SNTCommandSyncTest.m | 2 +- Tests/LogicTests/SNTEventTableTest.m | 2 +- Tests/LogicTests/SNTExecutionControllerTest.m | 2 +- Tests/LogicTests/SNTFileInfoTest.m | 2 +- Tests/LogicTests/SNTRuleTableTest.m | 2 +- Tests/LogicTests/SNTXPCConnectionTest.m | 2 +- 71 files changed, 76 insertions(+), 74 deletions(-) diff --git a/Source/SantaGUI/SNTAboutWindowController.h b/Source/SantaGUI/SNTAboutWindowController.h index 20c2fb772..a6d8e2e96 100644 --- a/Source/SantaGUI/SNTAboutWindowController.h +++ b/Source/SantaGUI/SNTAboutWindowController.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Cocoa; +#import @interface SNTAboutWindowController : NSWindowController diff --git a/Source/SantaGUI/SNTAccessibleTextField.h b/Source/SantaGUI/SNTAccessibleTextField.h index fbc952bc1..3dc471f77 100644 --- a/Source/SantaGUI/SNTAccessibleTextField.h +++ b/Source/SantaGUI/SNTAccessibleTextField.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Cocoa; +#import /** An NSTextField subclass that provides an accessiblity label equal to: diff --git a/Source/SantaGUI/SNTAppDelegate.h b/Source/SantaGUI/SNTAppDelegate.h index d8b1f7683..67fb8bc23 100644 --- a/Source/SantaGUI/SNTAppDelegate.h +++ b/Source/SantaGUI/SNTAppDelegate.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Cocoa; +#import /// /// Initiates and manages the connection to santad diff --git a/Source/SantaGUI/SNTMessageWindow.h b/Source/SantaGUI/SNTMessageWindow.h index f24e69239..f1ff20a2e 100644 --- a/Source/SantaGUI/SNTMessageWindow.h +++ b/Source/SantaGUI/SNTMessageWindow.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Cocoa; +#import /// /// An NSPanel that can become key/main and can fade in/out. diff --git a/Source/SantaGUI/SNTMessageWindowController.h b/Source/SantaGUI/SNTMessageWindowController.h index 580c97674..a13e86d97 100644 --- a/Source/SantaGUI/SNTMessageWindowController.h +++ b/Source/SantaGUI/SNTMessageWindowController.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Cocoa; +#import @class SNTStoredEvent; diff --git a/Source/SantaGUI/SNTMessageWindowController.m b/Source/SantaGUI/SNTMessageWindowController.m index 5e6078b5f..eb88d1157 100644 --- a/Source/SantaGUI/SNTMessageWindowController.m +++ b/Source/SantaGUI/SNTMessageWindowController.m @@ -14,7 +14,7 @@ #import "SNTMessageWindowController.h" -@import SecurityInterface.SFCertificatePanel; +#import #import diff --git a/Source/SantaGUI/SNTNotificationManager.h b/Source/SantaGUI/SNTNotificationManager.h index d33adc97b..64390cfba 100644 --- a/Source/SantaGUI/SNTNotificationManager.h +++ b/Source/SantaGUI/SNTNotificationManager.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Cocoa; +#import #import "SNTMessageWindowController.h" #import "SNTXPCNotifierInterface.h" diff --git a/Source/SantaGUI/main.m b/Source/SantaGUI/main.m index 5948cf438..e37ccf15f 100644 --- a/Source/SantaGUI/main.m +++ b/Source/SantaGUI/main.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Cocoa; +#import #import "SNTAppDelegate.h" diff --git a/Source/common/SNTBlockMessage.h b/Source/common/SNTBlockMessage.h index a2a0aa119..6847ea3ab 100644 --- a/Source/common/SNTBlockMessage.h +++ b/Source/common/SNTBlockMessage.h @@ -13,9 +13,9 @@ /// limitations under the License. #ifdef SANTAGUI -@import Cocoa; +#import #else -@import Foundation; +#import #endif @class SNTStoredEvent; diff --git a/Source/common/SNTCommonEnums.h b/Source/common/SNTCommonEnums.h index 3f17bdcf3..7c07b9604 100644 --- a/Source/common/SNTCommonEnums.h +++ b/Source/common/SNTCommonEnums.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import /// /// These enums are used in various places throughout the Santa client code. diff --git a/Source/common/SNTConfigurator.h b/Source/common/SNTConfigurator.h index 33c574d59..acb01a9a6 100644 --- a/Source/common/SNTConfigurator.h +++ b/Source/common/SNTConfigurator.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" diff --git a/Source/common/SNTDropRootPrivs.h b/Source/common/SNTDropRootPrivs.h index 38c0d4c6a..3f97a1a16 100644 --- a/Source/common/SNTDropRootPrivs.h +++ b/Source/common/SNTDropRootPrivs.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import /// /// Simple function to check and drop root privileges. diff --git a/Source/common/SNTFileInfo.h b/Source/common/SNTFileInfo.h index 2099782b7..49b6e09ca 100644 --- a/Source/common/SNTFileInfo.h +++ b/Source/common/SNTFileInfo.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import @class MOLCodesignChecker; diff --git a/Source/common/SNTLogging.h b/Source/common/SNTLogging.h index ae79d252c..4a886f034 100644 --- a/Source/common/SNTLogging.h +++ b/Source/common/SNTLogging.h @@ -34,7 +34,7 @@ #else // KERNEL -@import Foundation; +#import typedef enum : NSUInteger { LOG_LEVEL_ERROR, diff --git a/Source/common/SNTRule.h b/Source/common/SNTRule.h index 2a74b5782..bc97a6a2b 100644 --- a/Source/common/SNTRule.h +++ b/Source/common/SNTRule.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" diff --git a/Source/common/SNTStoredEvent.h b/Source/common/SNTStoredEvent.h index 0ac8dc665..7687e5361 100644 --- a/Source/common/SNTStoredEvent.h +++ b/Source/common/SNTStoredEvent.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" diff --git a/Source/common/SNTSystemInfo.h b/Source/common/SNTSystemInfo.h index 0a8c23917..0ed45820b 100644 --- a/Source/common/SNTSystemInfo.h +++ b/Source/common/SNTSystemInfo.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import /// /// Simple class for fetching system information diff --git a/Source/common/SNTXPCBundleServiceInterface.h b/Source/common/SNTXPCBundleServiceInterface.h index 780596759..34c483daf 100644 --- a/Source/common/SNTXPCBundleServiceInterface.h +++ b/Source/common/SNTXPCBundleServiceInterface.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import @class SNTStoredEvent; diff --git a/Source/common/SNTXPCConnection.h b/Source/common/SNTXPCConnection.h index 598912fd7..363c96577 100644 --- a/Source/common/SNTXPCConnection.h +++ b/Source/common/SNTXPCConnection.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import /** A wrapper around NSXPCListener and NSXPCConnection to provide client multiplexing, signature diff --git a/Source/common/SNTXPCControlInterface.h b/Source/common/SNTXPCControlInterface.h index da5c060d1..4225c54a0 100644 --- a/Source/common/SNTXPCControlInterface.h +++ b/Source/common/SNTXPCControlInterface.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import diff --git a/Source/common/SNTXPCNotifierInterface.h b/Source/common/SNTXPCNotifierInterface.h index 995fa7c58..5c43c536a 100644 --- a/Source/common/SNTXPCNotifierInterface.h +++ b/Source/common/SNTXPCNotifierInterface.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" #import "SNTXPCBundleServiceInterface.h" diff --git a/Source/common/SNTXPCSyncdInterface.h b/Source/common/SNTXPCSyncdInterface.h index 963d126f3..3041e400f 100644 --- a/Source/common/SNTXPCSyncdInterface.h +++ b/Source/common/SNTXPCSyncdInterface.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" diff --git a/Source/santabs/SNTBundleService.h b/Source/santabs/SNTBundleService.h index 38f603cbc..bdff0a35d 100644 --- a/Source/santabs/SNTBundleService.h +++ b/Source/santabs/SNTBundleService.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTXPCBundleServiceInterface.h" diff --git a/Source/santabs/main.m b/Source/santabs/main.m index 7a5c96713..0d2bc73dd 100644 --- a/Source/santabs/main.m +++ b/Source/santabs/main.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTBundleService.h" #import "SNTXPCBundleServiceInterface.h" diff --git a/Source/santactl/Commands/SNTCommandCheckCache.m b/Source/santactl/Commands/SNTCommandCheckCache.m index 5b5d2594f..5911305e4 100644 --- a/Source/santactl/Commands/SNTCommandCheckCache.m +++ b/Source/santactl/Commands/SNTCommandCheckCache.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommand.h" #import "SNTCommandController.h" diff --git a/Source/santactl/Commands/SNTCommandFileInfo.m b/Source/santactl/Commands/SNTCommandFileInfo.m index ab92c7798..0458c6f46 100644 --- a/Source/santactl/Commands/SNTCommandFileInfo.m +++ b/Source/santactl/Commands/SNTCommandFileInfo.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommand.h" #import "SNTCommandController.h" diff --git a/Source/santactl/Commands/SNTCommandFlushCache.m b/Source/santactl/Commands/SNTCommandFlushCache.m index 9e896d5e4..852e6d53d 100644 --- a/Source/santactl/Commands/SNTCommandFlushCache.m +++ b/Source/santactl/Commands/SNTCommandFlushCache.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommand.h" #import "SNTCommandController.h" diff --git a/Source/santactl/Commands/SNTCommandRule.m b/Source/santactl/Commands/SNTCommandRule.m index 5c2ba6187..6a37a64ef 100644 --- a/Source/santactl/Commands/SNTCommandRule.m +++ b/Source/santactl/Commands/SNTCommandRule.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommand.h" #import "SNTCommandController.h" diff --git a/Source/santactl/Commands/SNTCommandStatus.m b/Source/santactl/Commands/SNTCommandStatus.m index 4967ffb79..c4dcd48f5 100644 --- a/Source/santactl/Commands/SNTCommandStatus.m +++ b/Source/santactl/Commands/SNTCommandStatus.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommand.h" #import "SNTCommandController.h" diff --git a/Source/santactl/Commands/SNTCommandVersion.m b/Source/santactl/Commands/SNTCommandVersion.m index 8b2af53e7..97b45ade7 100644 --- a/Source/santactl/Commands/SNTCommandVersion.m +++ b/Source/santactl/Commands/SNTCommandVersion.m @@ -12,8 +12,8 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; -@import IOKit.kext; +#import +#import #import "SNTCommand.h" #import "SNTCommandController.h" diff --git a/Source/santactl/Commands/sync/NSData+Zlib.h b/Source/santactl/Commands/sync/NSData+Zlib.h index 0fb6322c8..99f1455b3 100644 --- a/Source/santactl/Commands/sync/NSData+Zlib.h +++ b/Source/santactl/Commands/sync/NSData+Zlib.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import /// Category on NSData providing the option of getting zlib or gzip compressed data. @interface NSData (Zlib) diff --git a/Source/santactl/Commands/sync/SNTCommandSync.m b/Source/santactl/Commands/sync/SNTCommandSync.m index 90f43190d..0e1e7d43c 100644 --- a/Source/santactl/Commands/sync/SNTCommandSync.m +++ b/Source/santactl/Commands/sync/SNTCommandSync.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommand.h" #import "SNTCommandController.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncConstants.h b/Source/santactl/Commands/sync/SNTCommandSyncConstants.h index 37d5ec3ba..336a2d14a 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncConstants.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncConstants.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import extern NSString *const kXSRFToken; diff --git a/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.h b/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.h index f404e744c..1f06cdc80 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommandSyncStage.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncLogUpload.h b/Source/santactl/Commands/sync/SNTCommandSyncLogUpload.h index 657c23124..d5b103674 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncLogUpload.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncLogUpload.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommandSyncStage.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncManager.h b/Source/santactl/Commands/sync/SNTCommandSyncManager.h index 3ade0697e..c2fd81772 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncManager.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncManager.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTXPCSyncdInterface.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncManager.m b/Source/santactl/Commands/sync/SNTCommandSyncManager.m index 0e3cb6059..830b3f02c 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncManager.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncManager.m @@ -14,7 +14,7 @@ #import "SNTCommandSyncManager.h" -@import SystemConfiguration; +#import #import #import diff --git a/Source/santactl/Commands/sync/SNTCommandSyncPostflight.h b/Source/santactl/Commands/sync/SNTCommandSyncPostflight.h index c5ac9dfb4..c9a26b057 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncPostflight.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncPostflight.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommandSyncStage.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncPreflight.h b/Source/santactl/Commands/sync/SNTCommandSyncPreflight.h index 1372d26a0..91c1909a0 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncPreflight.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncPreflight.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommandSyncStage.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.h b/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.h index b78d33590..8b668ac85 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommandSyncStage.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncStage.h b/Source/santactl/Commands/sync/SNTCommandSyncStage.h index 5b523c7d3..8a55fcf78 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncStage.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncStage.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import @class SNTCommandSyncState; @class SNTXPCConnection; diff --git a/Source/santactl/Commands/sync/SNTCommandSyncState.h b/Source/santactl/Commands/sync/SNTCommandSyncState.h index 9e56e581e..2af657509 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncState.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncState.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" diff --git a/Source/santactl/SNTCommand.h b/Source/santactl/SNTCommand.h index 4853ba1a9..3d74c4b96 100644 --- a/Source/santactl/SNTCommand.h +++ b/Source/santactl/SNTCommand.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import @class SNTXPCConnection; diff --git a/Source/santactl/SNTCommandController.h b/Source/santactl/SNTCommandController.h index b74ecb902..0e33dd5ea 100644 --- a/Source/santactl/SNTCommandController.h +++ b/Source/santactl/SNTCommandController.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommand.h" diff --git a/Source/santactl/main.m b/Source/santactl/main.m index 02b10d869..cf380cab1 100644 --- a/Source/santactl/main.m +++ b/Source/santactl/main.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommandController.h" diff --git a/Source/santad/DataLayer/SNTDatabaseTable.h b/Source/santad/DataLayer/SNTDatabaseTable.h index 27d1943ce..80520f8b6 100644 --- a/Source/santad/DataLayer/SNTDatabaseTable.h +++ b/Source/santad/DataLayer/SNTDatabaseTable.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import // This is imported in the header rather than implementation to save // classes that use this one from also having to import FMDB stuff. diff --git a/Source/santad/DataLayer/SNTEventTable.h b/Source/santad/DataLayer/SNTEventTable.h index b260d006b..c2175b792 100644 --- a/Source/santad/DataLayer/SNTEventTable.h +++ b/Source/santad/DataLayer/SNTEventTable.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTDatabaseTable.h" diff --git a/Source/santad/DataLayer/SNTEventTable.m b/Source/santad/DataLayer/SNTEventTable.m index d3a1dd7e7..e7e6203be 100644 --- a/Source/santad/DataLayer/SNTEventTable.m +++ b/Source/santad/DataLayer/SNTEventTable.m @@ -54,7 +54,7 @@ - (uint32_t)initializeDatabase:(FMDatabase *)db fromVersion:(uint32_t)version { } NSData *eventData; - NSNumber *idx = [rs objectForColumnName:@"idx"]; + NSNumber *idx = [rs objectForColumn:@"idx"]; @try { eventData = [NSKeyedArchiver archivedDataWithRootObject:se]; [db executeUpdate:@"UPDATE events SET eventdata=? WHERE idx=?", eventData, idx]; @@ -141,7 +141,7 @@ - (NSArray *)pendingEvents { if (obj) { [pendingEvents addObject:obj]; } else { - [db executeUpdate:@"DELETE FROM events WHERE idx=?", [rs objectForColumnName:@"idx"]]; + [db executeUpdate:@"DELETE FROM events WHERE idx=?", [rs objectForColumn:@"idx"]]; } } diff --git a/Source/santad/DataLayer/SNTRuleTable.h b/Source/santad/DataLayer/SNTRuleTable.h index 5e73a5524..57884bdc0 100644 --- a/Source/santad/DataLayer/SNTRuleTable.h +++ b/Source/santad/DataLayer/SNTRuleTable.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" #import "SNTDatabaseTable.h" diff --git a/Source/santad/Logs/SNTEventLog.h b/Source/santad/Logs/SNTEventLog.h index 5f36ce6fd..5ae7126fe 100644 --- a/Source/santad/Logs/SNTEventLog.h +++ b/Source/santad/Logs/SNTEventLog.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTKernelCommon.h" diff --git a/Source/santad/Logs/SNTEventLog.m b/Source/santad/Logs/SNTEventLog.m index cc60c307a..15007a64f 100644 --- a/Source/santad/Logs/SNTEventLog.m +++ b/Source/santad/Logs/SNTEventLog.m @@ -114,6 +114,8 @@ - (NSString *)sanitizeCString:(const char *)str ofLength:(NSUInteger)length { char *buf = NULL; BOOL shouldFree = NO; + if (length < 1) return @""; + // Loop through the string one character at a time, looking for the characters // we want to remove. for (const char *p = str; (c = *p) != 0; ++p) { diff --git a/Source/santad/SNTApplication.h b/Source/santad/SNTApplication.h index b33519368..b02bfdc14 100644 --- a/Source/santad/SNTApplication.h +++ b/Source/santad/SNTApplication.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import /// /// The main controller class for santad diff --git a/Source/santad/SNTApplication.m b/Source/santad/SNTApplication.m index 90c001188..975bc3214 100644 --- a/Source/santad/SNTApplication.m +++ b/Source/santad/SNTApplication.m @@ -14,7 +14,7 @@ #import "SNTApplication.h" -@import DiskArbitration; +#import #import "SNTCommonEnums.h" #import "SNTConfigurator.h" diff --git a/Source/santad/SNTCachedDecision.h b/Source/santad/SNTCachedDecision.h index 37a013f6c..a31ce7e9a 100644 --- a/Source/santad/SNTCachedDecision.h +++ b/Source/santad/SNTCachedDecision.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" diff --git a/Source/santad/SNTDaemonControlController.h b/Source/santad/SNTDaemonControlController.h index 7e68e9c42..2950bcbd9 100644 --- a/Source/santad/SNTDaemonControlController.h +++ b/Source/santad/SNTDaemonControlController.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTXPCControlInterface.h" diff --git a/Source/santad/SNTDatabaseController.h b/Source/santad/SNTDatabaseController.h index d42bae51b..417d2a27a 100644 --- a/Source/santad/SNTDatabaseController.h +++ b/Source/santad/SNTDatabaseController.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import // This is imported in the header rather than implementation to saves // classes that use this one from also having to import FMDB stuff. diff --git a/Source/santad/SNTDriverManager.h b/Source/santad/SNTDriverManager.h index 52bd55577..cc6e71bb7 100644 --- a/Source/santad/SNTDriverManager.h +++ b/Source/santad/SNTDriverManager.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #include "SNTKernelCommon.h" diff --git a/Source/santad/SNTDriverManager.m b/Source/santad/SNTDriverManager.m index b84f79555..4680b5394 100644 --- a/Source/santad/SNTDriverManager.m +++ b/Source/santad/SNTDriverManager.m @@ -14,7 +14,7 @@ #import "SNTDriverManager.h" -@import IOKit.kext; +#import #include diff --git a/Source/santad/SNTExecutionController.h b/Source/santad/SNTExecutionController.h index f14324fb9..b1f5e1b87 100644 --- a/Source/santad/SNTExecutionController.h +++ b/Source/santad/SNTExecutionController.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" #include "SNTKernelCommon.h" diff --git a/Source/santad/SNTNotificationQueue.h b/Source/santad/SNTNotificationQueue.h index 379fbf58a..4b6c165df 100644 --- a/Source/santad/SNTNotificationQueue.h +++ b/Source/santad/SNTNotificationQueue.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import @class SNTStoredEvent; @class SNTXPCConnection; diff --git a/Source/santad/SNTPolicyProcessor.h b/Source/santad/SNTPolicyProcessor.h index 0f21ebdbb..8ce6592da 100644 --- a/Source/santad/SNTPolicyProcessor.h +++ b/Source/santad/SNTPolicyProcessor.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" #import "SNTKernelCommon.h" diff --git a/Source/santad/SNTSyncdQueue.h b/Source/santad/SNTSyncdQueue.h index c89b3003d..b91864962 100644 --- a/Source/santad/SNTSyncdQueue.h +++ b/Source/santad/SNTSyncdQueue.h @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #import "SNTCommonEnums.h" diff --git a/Source/santad/main.m b/Source/santad/main.m index f4c629e53..17c245845 100644 --- a/Source/santad/main.m +++ b/Source/santad/main.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; +#import #include "SNTLogging.h" diff --git a/Tests/KernelTests/main.mm b/Tests/KernelTests/main.mm index 729ab5c60..fb745e13a 100644 --- a/Tests/KernelTests/main.mm +++ b/Tests/KernelTests/main.mm @@ -12,8 +12,8 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import Foundation; -@import IOKit; +#import +#import #import diff --git a/Tests/LogicTests/SNTCommandFileInfoTest.m b/Tests/LogicTests/SNTCommandFileInfoTest.m index 954b379ce..de95441c7 100644 --- a/Tests/LogicTests/SNTCommandFileInfoTest.m +++ b/Tests/LogicTests/SNTCommandFileInfoTest.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import XCTest; +#import #import diff --git a/Tests/LogicTests/SNTCommandSyncTest.m b/Tests/LogicTests/SNTCommandSyncTest.m index 1b62eb236..77265b315 100644 --- a/Tests/LogicTests/SNTCommandSyncTest.m +++ b/Tests/LogicTests/SNTCommandSyncTest.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import XCTest; +#import #import diff --git a/Tests/LogicTests/SNTEventTableTest.m b/Tests/LogicTests/SNTEventTableTest.m index a3307c15e..eb309f500 100644 --- a/Tests/LogicTests/SNTEventTableTest.m +++ b/Tests/LogicTests/SNTEventTableTest.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import XCTest; +#import #import diff --git a/Tests/LogicTests/SNTExecutionControllerTest.m b/Tests/LogicTests/SNTExecutionControllerTest.m index c32a94c0b..ef6c20cd9 100644 --- a/Tests/LogicTests/SNTExecutionControllerTest.m +++ b/Tests/LogicTests/SNTExecutionControllerTest.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import XCTest; +#import #import diff --git a/Tests/LogicTests/SNTFileInfoTest.m b/Tests/LogicTests/SNTFileInfoTest.m index a285a5b95..d169f6d15 100644 --- a/Tests/LogicTests/SNTFileInfoTest.m +++ b/Tests/LogicTests/SNTFileInfoTest.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import XCTest; +#import #import "SNTFileInfo.h" diff --git a/Tests/LogicTests/SNTRuleTableTest.m b/Tests/LogicTests/SNTRuleTableTest.m index d46edb73c..cca771c73 100644 --- a/Tests/LogicTests/SNTRuleTableTest.m +++ b/Tests/LogicTests/SNTRuleTableTest.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import XCTest; +#import #import "SNTRule.h" #import "SNTRuleTable.h" diff --git a/Tests/LogicTests/SNTXPCConnectionTest.m b/Tests/LogicTests/SNTXPCConnectionTest.m index 581170748..8c2f6a638 100644 --- a/Tests/LogicTests/SNTXPCConnectionTest.m +++ b/Tests/LogicTests/SNTXPCConnectionTest.m @@ -12,7 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. -@import XCTest; +#import #import #import From 06b688fef42458ab5b9a46d6f6a9b7d7aa2b6372 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Thu, 26 Apr 2018 17:23:32 -0400 Subject: [PATCH 20/25] Update .travis.yml (#253) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d7d9f6cb8..cba8dfff4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ cache: - bundler - cocoapods sudo: false -osx_image: xcode7 +osx_image: xcode9.3 before_install: - gem install cocoapods xcpretty From 273ae5f21ad458e15e63585bc0785df37a1b8014 Mon Sep 17 00:00:00 2001 From: Russell Hancox Date: Fri, 27 Apr 2018 10:51:53 -0400 Subject: [PATCH 21/25] santad: Missed an import (#254) --- Source/santad/SNTDriverManager.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/santad/SNTDriverManager.m b/Source/santad/SNTDriverManager.m index 4680b5394..8c4239943 100644 --- a/Source/santad/SNTDriverManager.m +++ b/Source/santad/SNTDriverManager.m @@ -14,6 +14,7 @@ #import "SNTDriverManager.h" +#import #import #include From e8630132d70290846e5f806312af4cb77984827d Mon Sep 17 00:00:00 2001 From: Russell Hancox Date: Fri, 27 Apr 2018 12:58:54 -0400 Subject: [PATCH 22/25] Project: make building on case-sensitive volumes work (#255) --- Source/common/SNTFileInfo.m | 2 +- Source/santad/DataLayer/SNTDatabaseTable.h | 2 +- Source/santad/SNTDatabaseController.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/common/SNTFileInfo.m b/Source/common/SNTFileInfo.m index b87c9ebc3..b70a4b068 100644 --- a/Source/common/SNTFileInfo.m +++ b/Source/common/SNTFileInfo.m @@ -24,7 +24,7 @@ #include #include -#import +#import // Simple class to hold the data of a mach_header and the offset within the file // in which that header was found. diff --git a/Source/santad/DataLayer/SNTDatabaseTable.h b/Source/santad/DataLayer/SNTDatabaseTable.h index 80520f8b6..65dcef383 100644 --- a/Source/santad/DataLayer/SNTDatabaseTable.h +++ b/Source/santad/DataLayer/SNTDatabaseTable.h @@ -16,7 +16,7 @@ // This is imported in the header rather than implementation to save // classes that use this one from also having to import FMDB stuff. -#import +#import @interface SNTDatabaseTable : NSObject diff --git a/Source/santad/SNTDatabaseController.h b/Source/santad/SNTDatabaseController.h index 417d2a27a..7b376dd6a 100644 --- a/Source/santad/SNTDatabaseController.h +++ b/Source/santad/SNTDatabaseController.h @@ -16,7 +16,7 @@ // This is imported in the header rather than implementation to saves // classes that use this one from also having to import FMDB stuff. -#import +#import @class SNTConfigTable; @class SNTEventTable; From 798b0fab1539b104b79154b3f6164dec6e06f131 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Mon, 7 May 2018 13:57:58 -0400 Subject: [PATCH 23/25] fileinfo: whitelist bundle extensions when performing an ancestor search (#257) * fileinfo: whitelist bundle extensions when performing an ancestor search * fix tests * conform to russell's every whim --- Santa.xcodeproj/project.pbxproj | 4 ++ Source/common/SNTFileInfo.m | 33 +++++++++-- .../DirectoryBundle/Contents/Info.plist | 52 ++++++++++++++++++ .../Contents/MacOS/DirectoryBundle | Bin 0 -> 9056 bytes .../BundleExample.app/Contents/Info.plist | 52 ++++++++++++++++++ .../Contents/MacOS/BundleExample | Bin 0 -> 9056 bytes Tests/LogicTests/SNTFileInfoTest.m | 20 +++++++ 7 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 Tests/LogicTests/Resources/DirectoryBundle/Contents/Info.plist create mode 100755 Tests/LogicTests/Resources/DirectoryBundle/Contents/MacOS/DirectoryBundle create mode 100644 Tests/LogicTests/Resources/DirectoryBundle/Contents/Resources/BundleExample.app/Contents/Info.plist create mode 100755 Tests/LogicTests/Resources/DirectoryBundle/Contents/Resources/BundleExample.app/Contents/MacOS/BundleExample diff --git a/Santa.xcodeproj/project.pbxproj b/Santa.xcodeproj/project.pbxproj index aa301f2a2..64f7ddd10 100644 --- a/Santa.xcodeproj/project.pbxproj +++ b/Santa.xcodeproj/project.pbxproj @@ -185,6 +185,7 @@ C7C721B61E2408C30051FAA6 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; }; C7DA62F71E241938009BDF2C /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; }; C7DA62F91E241A02009BDF2C /* SNTCommandBundleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = C7DA62F81E241A02009BDF2C /* SNTCommandBundleInfo.m */; }; + C7EAF71820A0A20B00745126 /* DirectoryBundle in Resources */ = {isa = PBXBuildFile; fileRef = C7EAF71720A0A20B00745126 /* DirectoryBundle */; }; C7FB56F61DBFB480004E14EF /* SNTXPCSyncdInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56F51DBFB480004E14EF /* SNTXPCSyncdInterface.m */; }; C7FB56F71DBFB480004E14EF /* SNTXPCSyncdInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56F51DBFB480004E14EF /* SNTXPCSyncdInterface.m */; }; C7FB57001DBFC213004E14EF /* SNTSyncdQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56FF1DBFC213004E14EF /* SNTSyncdQueue.m */; }; @@ -451,6 +452,7 @@ C7C721AF1E23FF300051FAA6 /* SNTXPCBundleServiceInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCBundleServiceInterface.h; sourceTree = ""; }; C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCBundleServiceInterface.m; sourceTree = ""; }; C7DA62F81E241A02009BDF2C /* SNTCommandBundleInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandBundleInfo.m; sourceTree = ""; }; + C7EAF71720A0A20B00745126 /* DirectoryBundle */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DirectoryBundle; sourceTree = ""; }; C7FB56F41DBFB480004E14EF /* SNTXPCSyncdInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCSyncdInterface.h; sourceTree = ""; }; C7FB56F51DBFB480004E14EF /* SNTXPCSyncdInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCSyncdInterface.m; sourceTree = ""; }; C7FB56FE1DBFC213004E14EF /* SNTSyncdQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTSyncdQueue.h; sourceTree = ""; }; @@ -549,6 +551,7 @@ 0D260DB018B68E12002A0B55 /* Resources */ = { isa = PBXGroup; children = ( + C7EAF71720A0A20B00745126 /* DirectoryBundle */, C74D6CC51EEB3B9B00BB5A33 /* BundleExample.app */, 0D536ED51B8E7A2E0039A26D /* bad_pagezero */, 0D2CD4601A81C7B100C9C910 /* dn.plist */, @@ -1107,6 +1110,7 @@ 0D2CD4611A81C7B100C9C910 /* dn.plist in Resources */, 0DEA5F7B1CF64C9200704398 /* sync_ruledownload_batch2.json in Resources */, 0DEA5F6C1CF6254900704398 /* sync_preflight_lockdown.json in Resources */, + C7EAF71820A0A20B00745126 /* DirectoryBundle in Resources */, 0D536ED81B8E7A2E0039A26D /* missing_pagezero in Resources */, 0D202D201CE4E90E00A88F16 /* sync_preflight_basic.json in Resources */, ); diff --git a/Source/common/SNTFileInfo.m b/Source/common/SNTFileInfo.m index b70a4b068..3987ba2f3 100644 --- a/Source/common/SNTFileInfo.m +++ b/Source/common/SNTFileInfo.m @@ -317,6 +317,26 @@ - (BOOL)isMissingPageZero { #pragma mark Bundle Information +/// +/// Directories with a "Contents/Info.plist" entry can be mistaken as a bundle. To be considered an +/// ancestor, the bundle must have a valid extension. +/// +- (NSSet *)allowedAncestorExtensions { + static NSSet *set; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + set = [NSSet setWithArray:@[ + @"app", + @"bundle", + @"framework", + @"kext", + @"xctest", + @"xpc", + ]]; + }); + return set; +} + /// /// Try and determine the bundle that the represented executable is contained within, if any. /// @@ -327,18 +347,21 @@ - (BOOL)isMissingPageZero { /// /// This method walks up the path until a bundle is found, if any. /// -/// @param ancestor YES this will return the highest NSBundle found in the tree. No will return the -/// the lowest. +/// @param ancestor YES this will return the highest NSBundle, with a valid extension, found in the +/// tree. NO will return the the lowest NSBundle, without validating the extension. /// --(NSBundle *)findBundleWithAncestor:(BOOL)ancestor { +- (NSBundle *)findBundleWithAncestor:(BOOL)ancestor { NSBundle *bundle; NSMutableArray *pathComponents = [[self.path pathComponents] mutableCopy]; // Ignore the root path "/", for some reason this is considered a bundle. while (pathComponents.count > 1) { NSBundle *bndl = [NSBundle bundleWithPath:[NSString pathWithComponents:pathComponents]]; - if (bndl && [bndl objectForInfoDictionaryKey:@"CFBundleIdentifier"]) { - bundle = bndl; + if ([bndl objectForInfoDictionaryKey:@"CFBundleIdentifier"]) { + if (!ancestor || + [[self allowedAncestorExtensions] containsObject:bndl.bundlePath.pathExtension]) { + bundle = bndl; + } if (!ancestor) break; } [pathComponents removeLastObject]; diff --git a/Tests/LogicTests/Resources/DirectoryBundle/Contents/Info.plist b/Tests/LogicTests/Resources/DirectoryBundle/Contents/Info.plist new file mode 100644 index 000000000..e938a94fa --- /dev/null +++ b/Tests/LogicTests/Resources/DirectoryBundle/Contents/Info.plist @@ -0,0 +1,52 @@ + + + + + BuildMachineOSBuild + 16F73 + CFBundleDevelopmentRegion + en + CFBundleExecutable + DirectoryBundle + CFBundleIdentifier + com.google.santa.DirectoryBundle + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + DirectoryBundle + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 7D1014 + DTPlatformVersion + GM + DTSDKBuild + 15E60 + DTSDKName + macosx10.11 + DTXcode + 0731 + DTXcodeBuild + 7D1014 + LSMinimumSystemVersion + 10.12 + NSHumanReadableCopyright + Copyright © 2018 Google. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Tests/LogicTests/Resources/DirectoryBundle/Contents/MacOS/DirectoryBundle b/Tests/LogicTests/Resources/DirectoryBundle/Contents/MacOS/DirectoryBundle new file mode 100755 index 0000000000000000000000000000000000000000..f4202ea1e11b98503858cce55dda9d12bc8bcaa0 GIT binary patch literal 9056 zcmeHNUuYaf7@upRhBTT>^r68&Y)c|l(%q`HwC3e5xr-N!Y1*V(1)1*N&gC|@e~$f= zT*N}O1U$5mr=m|5@yVy+lj2K3!QzYJlc0hRDp3@~mx_qz_s!0xyVoRr?ZbRzcIG$V ze7~LfzS(24-+uMaAOGD$NUn#F^?ihp`=PAgO~?jOphd_ClnN9|=ZnvlUoM|Hg}qtH zW#NtpdA@~#lrEOfEoO&s`+T;K2n=&0cZq@{C=FRF#8xcbd`AaiF`#-z=n?mdHm`cg zdKyw1gpm`_%P-uh`TvrO?<_;zRBZSDlQgN z8i-#eu1S1TafLm%9UDqrn+9u+;n}nq`Y_L(`4Sr3A84Nl`ag{+we`LD@?ekiJ0J)U zr|pw{m+(_st)&CeJ-@?(PZ0))(|id}Qd8;~%T;PQ`VzxXbn{gNU!O2Qe7iWr&*|*U z+;ip9O!AB=U2y=6a$Zah*U96=dkHxNkN;6@D}>;^`=BmBok&F?WFEjfP~$k96Z-IL zz_|5(JO~6pxF6a$4u$hTjbrYbImpZqdW)& z=kfd(H(o#a)WjR@Pu~4>>6O4Tzhhe&ChrbhP!TX$tf;yZx zA-}=T$aqd$SPMetXtS2#>;9TH?duL(_54PlO?#1R>Y?SiYAxy2USNIzJ%Kir(gPdv zpMY|c|0h7Xn`?vh;SN!YDy-5nK*^=sF4zAh%qwdbPf?vrTcTYZ%J%(oxSq>okM&G> zKHGauMJ+o9_#YDc2k%#4Emn;}-LM&L>S0||)s(+r0LY_IFh19nIPQ-LjQdH7^nmn$ z^nmn$^nmn$^uV3qfwPtN&y|b6EA0#aR@%{@TTjBIDwm%A0ju_nO1r#um23?mdh5d0 z7M@z4xK_FNx$??qov|x`I%Dti>j!Y1z4Y(~RK$?MZT*?gctDV>_0f(%xuyWs*)MNip!5S(E(<}ePfJbT`2qFUKa9R+pJbIDQ26Yir%+`G3tL*#!La^AK8 literal 0 HcmV?d00001 diff --git a/Tests/LogicTests/Resources/DirectoryBundle/Contents/Resources/BundleExample.app/Contents/Info.plist b/Tests/LogicTests/Resources/DirectoryBundle/Contents/Resources/BundleExample.app/Contents/Info.plist new file mode 100644 index 000000000..d9c402f17 --- /dev/null +++ b/Tests/LogicTests/Resources/DirectoryBundle/Contents/Resources/BundleExample.app/Contents/Info.plist @@ -0,0 +1,52 @@ + + + + + BuildMachineOSBuild + 16F73 + CFBundleDevelopmentRegion + en + CFBundleExecutable + BundleExample + CFBundleIdentifier + com.google.santa.BundleExample + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + BundleExample + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 7D1014 + DTPlatformVersion + GM + DTSDKBuild + 15E60 + DTSDKName + macosx10.11 + DTXcode + 0731 + DTXcodeBuild + 7D1014 + LSMinimumSystemVersion + 10.12 + NSHumanReadableCopyright + Copyright © 2017 Google. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Tests/LogicTests/Resources/DirectoryBundle/Contents/Resources/BundleExample.app/Contents/MacOS/BundleExample b/Tests/LogicTests/Resources/DirectoryBundle/Contents/Resources/BundleExample.app/Contents/MacOS/BundleExample new file mode 100755 index 0000000000000000000000000000000000000000..f4202ea1e11b98503858cce55dda9d12bc8bcaa0 GIT binary patch literal 9056 zcmeHNUuYaf7@upRhBTT>^r68&Y)c|l(%q`HwC3e5xr-N!Y1*V(1)1*N&gC|@e~$f= zT*N}O1U$5mr=m|5@yVy+lj2K3!QzYJlc0hRDp3@~mx_qz_s!0xyVoRr?ZbRzcIG$V ze7~LfzS(24-+uMaAOGD$NUn#F^?ihp`=PAgO~?jOphd_ClnN9|=ZnvlUoM|Hg}qtH zW#NtpdA@~#lrEOfEoO&s`+T;K2n=&0cZq@{C=FRF#8xcbd`AaiF`#-z=n?mdHm`cg zdKyw1gpm`_%P-uh`TvrO?<_;zRBZSDlQgN z8i-#eu1S1TafLm%9UDqrn+9u+;n}nq`Y_L(`4Sr3A84Nl`ag{+we`LD@?ekiJ0J)U zr|pw{m+(_st)&CeJ-@?(PZ0))(|id}Qd8;~%T;PQ`VzxXbn{gNU!O2Qe7iWr&*|*U z+;ip9O!AB=U2y=6a$Zah*U96=dkHxNkN;6@D}>;^`=BmBok&F?WFEjfP~$k96Z-IL zz_|5(JO~6pxF6a$4u$hTjbrYbImpZqdW)& z=kfd(H(o#a)WjR@Pu~4>>6O4Tzhhe&ChrbhP!TX$tf;yZx zA-}=T$aqd$SPMetXtS2#>;9TH?duL(_54PlO?#1R>Y?SiYAxy2USNIzJ%Kir(gPdv zpMY|c|0h7Xn`?vh;SN!YDy-5nK*^=sF4zAh%qwdbPf?vrTcTYZ%J%(oxSq>okM&G> zKHGauMJ+o9_#YDc2k%#4Emn;}-LM&L>S0||)s(+r0LY_IFh19nIPQ-LjQdH7^nmn$ z^nmn$^nmn$^uV3qfwPtN&y|b6EA0#aR@%{@TTjBIDwm%A0ju_nO1r#um23?mdh5d0 z7M@z4xK_FNx$??qov|x`I%Dti>j!Y1z4Y(~RK$?MZT*?gctDV>_0f(%xuyWs*)MNip!5S(E(<}ePfJbT`2qFUKa9R+pJbIDQ26Yir%+`G3tL*#!La^AK8 literal 0 HcmV?d00001 diff --git a/Tests/LogicTests/SNTFileInfoTest.m b/Tests/LogicTests/SNTFileInfoTest.m index d169f6d15..766754103 100644 --- a/Tests/LogicTests/SNTFileInfoTest.m +++ b/Tests/LogicTests/SNTFileInfoTest.m @@ -165,6 +165,26 @@ - (void)testBundleIsAncestor { XCTAssertEqualObjects([sut bundlePath], path); } +- (void)testDirectoryBundleIsNotAncestor { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"DirectoryBundle" + ofType:@""]; + NSString *directoryBundle = @"/tmp/DirectoryBundle"; + NSFileManager *fm = [NSFileManager defaultManager]; + [fm removeItemAtPath:directoryBundle error:NULL]; + [fm copyItemAtPath:path toPath:directoryBundle error:NULL]; + path = [directoryBundle stringByAppendingString:@"/Contents/Resources/BundleExample.app"]; + SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path]; + sut.useAncestorBundle = YES; + + XCTAssertNotNil([sut bundle]); + + XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.santa.BundleExample"); + XCTAssertEqualObjects([sut bundleName], @"BundleExample"); + XCTAssertEqualObjects([sut bundleVersion], @"1"); + XCTAssertEqualObjects([sut bundleShortVersionString], @"1.0"); + XCTAssertEqualObjects([sut bundlePath], path); +} + - (void)testBundleCacheReset { NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"BundleExample" ofType:@"app"]; From b70442e483887ed2368003dbe5f736931401d535 Mon Sep 17 00:00:00 2001 From: Tom Burgin Date: Wed, 9 May 2018 11:40:35 -0400 Subject: [PATCH 24/25] Project: Use MOLXPCConnection (#258) * Project: Use MOLXPCConnection * review fixes --- Podfile | 5 + Podfile.lock | 6 +- Santa.xcodeproj/project.pbxproj | 18 -- Source/SantaGUI/SNTAppDelegate.m | 26 ++- Source/SantaGUI/SNTNotificationManager.m | 12 +- Source/common/SNTXPCConnection.h | 135 ----------- Source/common/SNTXPCConnection.m | 210 ------------------ Source/common/SNTXPCControlInterface.h | 6 +- Source/common/SNTXPCControlInterface.m | 7 +- Source/santabs/SNTBundleService.m | 10 +- Source/santabs/main.m | 7 +- .../santactl/Commands/SNTCommandBundleInfo.m | 3 +- .../santactl/Commands/SNTCommandCheckCache.m | 3 +- Source/santactl/Commands/SNTCommandFileInfo.m | 4 +- .../santactl/Commands/SNTCommandFlushCache.m | 3 +- Source/santactl/Commands/SNTCommandRule.m | 4 +- Source/santactl/Commands/SNTCommandStatus.m | 3 +- Source/santactl/Commands/SNTCommandVersion.m | 3 +- .../santactl/Commands/sync/SNTCommandSync.m | 11 +- .../Commands/sync/SNTCommandSyncEventUpload.m | 2 +- .../Commands/sync/SNTCommandSyncManager.h | 4 +- .../Commands/sync/SNTCommandSyncManager.m | 6 +- .../Commands/sync/SNTCommandSyncPostflight.m | 3 +- .../Commands/sync/SNTCommandSyncPreflight.m | 3 +- .../sync/SNTCommandSyncRuleDownload.m | 3 +- .../Commands/sync/SNTCommandSyncStage.h | 4 +- .../Commands/sync/SNTCommandSyncStage.m | 5 +- .../Commands/sync/SNTCommandSyncState.h | 4 +- Source/santactl/SNTCommand.h | 8 +- Source/santactl/SNTCommand.m | 4 +- Source/santactl/SNTCommandController.h | 2 +- Source/santactl/SNTCommandController.m | 9 +- Source/santad/Logs/SNTEventLog.h | 1 - Source/santad/SNTApplication.m | 7 +- Source/santad/SNTDaemonControlController.m | 18 +- Source/santad/SNTNotificationQueue.h | 4 +- Source/santad/SNTNotificationQueue.m | 5 +- Source/santad/SNTSyncdQueue.h | 4 +- Source/santad/SNTSyncdQueue.m | 3 +- Tests/LogicTests/SNTCommandFileInfoTest.m | 4 +- Tests/LogicTests/SNTCommandSyncTest.m | 4 +- Tests/LogicTests/SNTXPCConnectionTest.m | 124 ----------- 42 files changed, 133 insertions(+), 574 deletions(-) delete mode 100644 Source/common/SNTXPCConnection.h delete mode 100644 Source/common/SNTXPCConnection.m delete mode 100644 Tests/LogicTests/SNTXPCConnectionTest.m diff --git a/Podfile b/Podfile index d16cc1d1f..990878658 100644 --- a/Podfile +++ b/Podfile @@ -5,16 +5,19 @@ inhibit_all_warnings! target :Santa do pod 'MOLCertificate' pod 'MOLCodesignChecker' + pod 'MOLXPCConnection' end target :santad do pod 'FMDB' pod 'MOLCertificate' pod 'MOLCodesignChecker' + pod 'MOLXPCConnection' target :santabs do pod 'FMDB' pod 'MOLCertificate' pod 'MOLCodesignChecker' + pod 'MOLXPCConnection' end end @@ -24,6 +27,7 @@ target :santactl do pod 'MOLCertificate' pod 'MOLCodesignChecker' pod 'MOLFCMClient', '~> 1.3' + pod 'MOLXPCConnection' end target :LogicTests do @@ -31,6 +35,7 @@ target :LogicTests do pod 'MOLAuthenticatingURLSession' pod 'MOLCertificate' pod 'MOLCodesignChecker' + pod 'MOLXPCConnection' pod 'OCMock' end diff --git a/Podfile.lock b/Podfile.lock index d37415248..ae3c06d65 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -9,6 +9,8 @@ PODS: - MOLCertificate (~> 1.8) - MOLFCMClient (1.7): - MOLAuthenticatingURLSession (~> 2.4) + - MOLXPCConnection (1.1): + - MOLCodesignChecker (~> 1.9) - OCMock (3.4.1) DEPENDENCIES: @@ -17,6 +19,7 @@ DEPENDENCIES: - MOLCertificate - MOLCodesignChecker - MOLFCMClient (~> 1.3) + - MOLXPCConnection - OCMock SPEC CHECKSUMS: @@ -25,8 +28,9 @@ SPEC CHECKSUMS: MOLCertificate: c999513316d511c69f290fbf313dfe8dca4ad592 MOLCodesignChecker: b0d5db9d2f9bd94e0fd093891a5d40e5ad77cbc0 MOLFCMClient: ee45348909351f232e2759c580329072ae7e02d4 + MOLXPCConnection: de9d5535928f59766a768384e411077b83ec2f9c OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3 -PODFILE CHECKSUM: acd378b3727c923d912e09812da344f7375c14fe +PODFILE CHECKSUM: ddca043a7ace9ec600c108621c56d13a50d17236 COCOAPODS: 1.4.0 diff --git a/Santa.xcodeproj/project.pbxproj b/Santa.xcodeproj/project.pbxproj index 64f7ddd10..1784751e5 100644 --- a/Santa.xcodeproj/project.pbxproj +++ b/Santa.xcodeproj/project.pbxproj @@ -47,7 +47,6 @@ 0D35BDA218FD71CE00921A21 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDA118FD71CE00921A21 /* main.m */; }; 0D35BDAC18FD7CFD00921A21 /* SNTCommandController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDAB18FD7CFD00921A21 /* SNTCommandController.m */; }; 0D35BDB518FD84F600921A21 /* SNTCommandSync.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDB418FD84F600921A21 /* SNTCommandSync.m */; }; - 0D35BDC418FDA5D100921A21 /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; }; 0D377C2A17A071B7008453DB /* SNTEventTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D377C2917A071B7008453DB /* SNTEventTable.m */; }; 0D37C10F18F6029A0069BC61 /* SNTDatabaseTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D37C10E18F6029A0069BC61 /* SNTDatabaseTable.m */; }; 0D385DC4180DE4A900418BC6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D385DC3180DE4A900418BC6 /* main.m */; }; @@ -56,7 +55,6 @@ 0D385DF1180DE51600418BC6 /* SNTAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D385DEB180DE51600418BC6 /* SNTAppDelegate.m */; }; 0D385DF2180DE51600418BC6 /* SNTMessageWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D385DED180DE51600418BC6 /* SNTMessageWindowController.m */; }; 0D385DF3180DE51600418BC6 /* SNTNotificationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D385DEF180DE51600418BC6 /* SNTNotificationManager.m */; }; - 0D3AFBE718FB32CB0087BCEE /* SNTXPCConnectionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D3AFBE618FB32CB0087BCEE /* SNTXPCConnectionTest.m */; }; 0D3AFBEB18FB48E70087BCEE /* SNTDatabaseTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D37C10E18F6029A0069BC61 /* SNTDatabaseTable.m */; }; 0D3AFBEC18FB48E70087BCEE /* SNTEventTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D377C2917A071B7008453DB /* SNTEventTable.m */; }; 0D3AFBEE18FB4C6C0087BCEE /* SNTApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */; }; @@ -75,8 +73,6 @@ 0D63DD5C1906FCB400D346C4 /* SNTDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */; }; 0D63DD5E1906FCB400D346C4 /* SNTDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */; }; 0D668E8118D1121700E29A8B /* SNTMessageWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D668E8018D1121700E29A8B /* SNTMessageWindow.m */; }; - 0D6FDC9618C93A020044685C /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; }; - 0D6FDC9718C93A020044685C /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; }; 0D7D01871774F93A005DBAB4 /* SNTDriverManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D7D01861774F93A005DBAB4 /* SNTDriverManager.m */; }; 0D827E6519DF392E006EC811 /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; }; 0D827E6719DF3C74006EC811 /* SNTCommandStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D827E6619DF3C74006EC811 /* SNTCommandStatus.m */; }; @@ -109,7 +105,6 @@ 0DC5D871192160180078A5C0 /* SNTCommandSyncLogUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D870192160180078A5C0 /* SNTCommandSyncLogUpload.m */; }; 0DC765EA1B28D9EA00BAE651 /* santad in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0D9A7F3D1759330500035EB5 /* santad */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 0DC765EB1B28D9EA00BAE651 /* santactl in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0D35BD9E18FD71CE00921A21 /* santactl */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; - 0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; }; 0DCD5FBF1909D64A006B445C /* SNTCommandFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */; }; 0DCD6042190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; }; 0DCD6043190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; }; @@ -179,7 +174,6 @@ C7C721AE1E23FCB50051FAA6 /* SNTBundleService.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721AD1E23FCB50051FAA6 /* SNTBundleService.m */; }; C7C721B11E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; }; C7C721B21E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; }; - C7C721B31E2400310051FAA6 /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; }; C7C721B41E24042B0051FAA6 /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; }; C7C721B51E2408BE0051FAA6 /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; }; C7C721B61E2408C30051FAA6 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; }; @@ -329,7 +323,6 @@ 0D385DED180DE51600418BC6 /* SNTMessageWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTMessageWindowController.m; sourceTree = ""; }; 0D385DEE180DE51600418BC6 /* SNTNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTNotificationManager.h; sourceTree = ""; }; 0D385DEF180DE51600418BC6 /* SNTNotificationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTNotificationManager.m; sourceTree = ""; }; - 0D3AFBE618FB32CB0087BCEE /* SNTXPCConnectionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCConnectionTest.m; sourceTree = ""; }; 0D3AFBF718FB4C870087BCEE /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 0D4163FF191974F1006A356A /* SNTCommandSyncState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncState.h; sourceTree = ""; }; 0D416400191974F1006A356A /* SNTCommandSyncState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandSyncState.m; sourceTree = ""; }; @@ -350,8 +343,6 @@ 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTDatabaseController.m; sourceTree = ""; }; 0D668E7F18D1121700E29A8B /* SNTMessageWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTMessageWindow.h; sourceTree = ""; }; 0D668E8018D1121700E29A8B /* SNTMessageWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTMessageWindow.m; sourceTree = ""; }; - 0D6FDC9418C93A020044685C /* SNTXPCConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCConnection.h; sourceTree = ""; }; - 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCConnection.m; sourceTree = ""; }; 0D7D01851774F93A005DBAB4 /* SNTDriverManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTDriverManager.h; sourceTree = ""; }; 0D7D01861774F93A005DBAB4 /* SNTDriverManager.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = SNTDriverManager.m; sourceTree = ""; }; 0D827E6619DF3C74006EC811 /* SNTCommandStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandStatus.m; sourceTree = ""; }; @@ -543,7 +534,6 @@ 0DD0D490194F9947005F27EB /* SNTExecutionControllerTest.m */, 0DD0D48E194F78F8005F27EB /* SNTFileInfoTest.m */, 0DB537861AFD36EB00487F92 /* SNTRuleTableTest.m */, - 0D3AFBE618FB32CB0087BCEE /* SNTXPCConnectionTest.m */, ); path = LogicTests; sourceTree = ""; @@ -747,8 +737,6 @@ 0D42D2B419D1D98A00955F08 /* SNTSystemInfo.m */, C7C721AF1E23FF300051FAA6 /* SNTXPCBundleServiceInterface.h */, C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */, - 0D6FDC9418C93A020044685C /* SNTXPCConnection.h */, - 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */, 0DCD605319115D17006B445C /* SNTXPCControlInterface.h */, 0DCD605419115D17006B445C /* SNTXPCControlInterface.m */, 0DC8C9E3180CC3BC00FCFB29 /* SNTXPCNotifierInterface.h */, @@ -1470,7 +1458,6 @@ 0D202D191CDD2EE500A88F16 /* SNTCommandSyncTest.m in Sources */, 0D3AFBF018FB4C6C0087BCEE /* SNTDriverManager.m in Sources */, 0DCD6044190ACCB8006B445C /* SNTFileInfo.m in Sources */, - 0D6FDC9718C93A020044685C /* SNTXPCConnection.m in Sources */, 0D3AFBEB18FB48E70087BCEE /* SNTDatabaseTable.m in Sources */, 0DD0D491194F9947005F27EB /* SNTExecutionControllerTest.m in Sources */, 0D3AFBEF18FB4C6C0087BCEE /* SNTExecutionController.m in Sources */, @@ -1487,7 +1474,6 @@ 0DE5B54C1C92722300C00603 /* SNTNotificationQueue.m in Sources */, 0DEA5F651CF6057D00704398 /* SNTCommandSyncEventUpload.m in Sources */, 0DB77FFB1CD7AC5A004DF060 /* SNTCommandSyncConstants.m in Sources */, - 0D3AFBE718FB32CB0087BCEE /* SNTXPCConnectionTest.m in Sources */, 0D9184B91CD2F32D0004E859 /* SNTCommandSyncStage.m in Sources */, 0DCD605719115E54006B445C /* SNTDaemonControlController.m in Sources */, 0D2E1E631CEFA6C30039B2C4 /* SantaCacheTest.mm in Sources */, @@ -1517,7 +1503,6 @@ 0DE50F6C19130358007B2B0C /* SNTStoredEvent.m in Sources */, 0D9184B81CD2F32D0004E859 /* SNTCommandSyncStage.m in Sources */, C776A1071DEE160500A56616 /* SNTCommandSyncManager.m in Sources */, - 0D35BDC418FDA5D100921A21 /* SNTXPCConnection.m in Sources */, 0DCD605C19117A90006B445C /* SNTCommandSyncPreflight.m in Sources */, 0D41640519197AD7006A356A /* SNTCommandSyncEventUpload.m in Sources */, 0D42D2B919D2042900955F08 /* SNTConfigurator.m in Sources */, @@ -1547,7 +1532,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */, 0D385DF1180DE51600418BC6 /* SNTAppDelegate.m in Sources */, 0D88680A1AC48A1200B86659 /* SNTSystemInfo.m in Sources */, 0D89310F1C931986002E8D74 /* SNTRule.m in Sources */, @@ -1598,7 +1582,6 @@ 0DC5D86D191AED220078A5C0 /* SNTRuleTable.m in Sources */, 0D7D01871774F93A005DBAB4 /* SNTDriverManager.m in Sources */, 0D8E18CD19107B56000F89B8 /* SNTDaemonControlController.m in Sources */, - 0D6FDC9618C93A020044685C /* SNTXPCConnection.m in Sources */, 0D377C2A17A071B7008453DB /* SNTEventTable.m in Sources */, 0DE50F681912716A007B2B0C /* SNTRule.m in Sources */, 0DB77FD81CCE824A004DF060 /* SNTBlockMessage.m in Sources */, @@ -1618,7 +1601,6 @@ buildActionMask = 2147483647; files = ( C7C721B21E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m in Sources */, - C7C721B31E2400310051FAA6 /* SNTXPCConnection.m in Sources */, C7C721B61E2408C30051FAA6 /* SNTLogging.m in Sources */, C7C721B41E24042B0051FAA6 /* SNTStoredEvent.m in Sources */, C7C721B51E2408BE0051FAA6 /* SNTFileInfo.m in Sources */, diff --git a/Source/SantaGUI/SNTAppDelegate.m b/Source/SantaGUI/SNTAppDelegate.m index 61edadd62..f8c5107d3 100644 --- a/Source/SantaGUI/SNTAppDelegate.m +++ b/Source/SantaGUI/SNTAppDelegate.m @@ -14,18 +14,19 @@ #import "SNTAppDelegate.h" +#import + #import "SNTAboutWindowController.h" #import "SNTConfigurator.h" #import "SNTNotificationManager.h" #import "SNTStrengthify.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @interface SNTAppDelegate () @property SNTAboutWindowController *aboutWindowController; @property SNTNotificationManager *notificationManager; -@property SNTXPCConnection *daemonListener; -@property SNTXPCConnection *bundleListener; +@property MOLXPCConnection *daemonListener; +@property MOLXPCConnection *bundleListener; @end @implementation SNTAppDelegate @@ -45,12 +46,17 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { self.daemonListener.invalidationHandler = nil; [self.daemonListener invalidate]; self.daemonListener = nil; + + self.bundleListener.invalidationHandler = nil; + [self.bundleListener invalidate]; + self.bundleListener = nil; }]; [workspaceNotifications addObserverForName:NSWorkspaceSessionDidBecomeActiveNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) { [self attemptDaemonReconnection]; + [self attemptBundleReconnection]; }]; [self createDaemonConnection]; @@ -72,7 +78,7 @@ - (void)createDaemonConnection { // Create listener for return connection from daemon. NSXPCListener *listener = [NSXPCListener anonymousListener]; - self.daemonListener = [[SNTXPCConnection alloc] initServerWithListener:listener]; + self.daemonListener = [[MOLXPCConnection alloc] initServerWithListener:listener]; self.daemonListener.exportedInterface = [SNTXPCNotifierInterface notifierInterface]; self.daemonListener.exportedObject = self.notificationManager; self.daemonListener.acceptedHandler = ^{ @@ -85,9 +91,10 @@ - (void)createDaemonConnection { [self.daemonListener resume]; // Tell daemon to connect back to the above listener. - SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; + MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; [daemonConn resume]; [[daemonConn remoteObjectProxy] setNotificationListener:listener.endpoint]; + [daemonConn invalidate]; // Now wait for the connection to come in. if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) { @@ -96,6 +103,8 @@ - (void)createDaemonConnection { } - (void)attemptDaemonReconnection { + self.daemonListener.invalidationHandler = nil; + [self.daemonListener invalidate]; [self performSelectorInBackground:@selector(createDaemonConnection) withObject:nil]; } @@ -106,7 +115,7 @@ - (void)createBundleConnection { // Create listener for return connection from the bundle service. NSXPCListener *listener = [NSXPCListener anonymousListener]; - self.bundleListener = [[SNTXPCConnection alloc] initServerWithListener:listener]; + self.bundleListener = [[MOLXPCConnection alloc] initServerWithListener:listener]; self.bundleListener.exportedInterface = [SNTXPCNotifierInterface bundleNotifierInterface]; self.bundleListener.exportedObject = self.notificationManager; self.bundleListener.acceptedHandler = ^{ @@ -119,9 +128,10 @@ - (void)createBundleConnection { [self.bundleListener resume]; // Tell santabs to connect back to the above listener. - SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; + MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; [daemonConn resume]; [[daemonConn remoteObjectProxy] setBundleNotificationListener:listener.endpoint]; + [daemonConn invalidate]; // Now wait for the connection to come in. if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) { @@ -130,6 +140,8 @@ - (void)createBundleConnection { } - (void)attemptBundleReconnection { + self.bundleListener.invalidationHandler = nil; + [self.bundleListener invalidate]; [self performSelectorInBackground:@selector(createBundleConnection) withObject:nil]; } diff --git a/Source/SantaGUI/SNTNotificationManager.m b/Source/SantaGUI/SNTNotificationManager.m index 36e394ab3..1a5b7b807 100644 --- a/Source/SantaGUI/SNTNotificationManager.m +++ b/Source/SantaGUI/SNTNotificationManager.m @@ -14,12 +14,13 @@ #import "SNTNotificationManager.h" +#import + #import "SNTBlockMessage.h" #import "SNTConfigurator.h" #import "SNTLogging.h" #import "SNTStoredEvent.h" #import "SNTStrengthify.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @interface SNTNotificationManager () @@ -31,7 +32,7 @@ @interface SNTNotificationManager () @property(readonly) NSMutableArray *pendingNotifications; /// The connection to the bundle service -@property SNTXPCConnection *bundleServiceConnection; +@property MOLXPCConnection *bundleServiceConnection; /// A semaphore to block bundle hashing until a connection is established @property dispatch_semaphore_t bundleServiceSema; @@ -192,7 +193,7 @@ - (void)updateCountsForEvent:(SNTStoredEvent *)event } - (void)setBundleServiceListener:(NSXPCListenerEndpoint *)listener { - SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener]; + MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithListener:listener]; c.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface]; [c resume]; self.bundleServiceConnection = c; @@ -203,6 +204,8 @@ - (void)setBundleServiceListener:(NSXPCListenerEndpoint *)listener { if (self.currentWindowController) { [self updateBlockNotification:self.currentWindowController.event withBundleHash:nil]; } + self.bundleServiceConnection.invalidationHandler = nil; + [self.bundleServiceConnection invalidate]; }; dispatch_semaphore_signal(self.bundleServiceSema); @@ -245,9 +248,10 @@ - (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event { } // Send the results to santad. It will decide if they need to be synced. - SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; + MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; [daemonConn resume]; [[daemonConn remoteObjectProxy] syncBundleEvent:event relatedEvents:events]; + [daemonConn invalidate]; // Update the UI with the bundle hash. Also make the openEventButton available. [self updateBlockNotification:event withBundleHash:bh]; diff --git a/Source/common/SNTXPCConnection.h b/Source/common/SNTXPCConnection.h deleted file mode 100644 index 363c96577..000000000 --- a/Source/common/SNTXPCConnection.h +++ /dev/null @@ -1,135 +0,0 @@ -/// Copyright 2015 Google Inc. All rights reserved. -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. - -#import - -/** - A wrapper around NSXPCListener and NSXPCConnection to provide client multiplexing, signature - validation of connecting clients and forced connection establishment. - - Example server started by @c launchd where the @c launchd job has a @c MachServices key: - - @code - SNTXPCConnection *conn = [[SNTXPCConnection alloc] initServerWithName:@"MyServer"]; - conn.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)]; - conn.exportedObject = myObject; - [conn resume]; - @endcode - - Example client, connecting to above server: - - @code - SNTXPCConnection *conn = [[SNTXPCConnection alloc] initClientWithName:"MyServer" - withOptions:0]; - conn.remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)]; - conn.invalidationHandler = ^{ NSLog(@"Connection invalidated") }; - [conn resume]; - @endcode - - The client can send a message to the server with: - - @code - [conn.remoteObjectProxy selectorInRemoteInterface]; - @endcode - - One advantage of the way that SNTXPCConnection works over using NSXPCConnection directly is that - from the client-side once the resume method has finished, the connection is either valid or the - invalidation handler will be called. Ordinarily, the connection doesn't actually get made until - the first message is sent across it. - - @note messages are always delivered on a background thread! -*/ -@interface SNTXPCConnection : NSObject - -/** - Initialize a new server with a given listener, provided by `[NSXPCListener anonymousListener]`. -*/ -- (nullable instancetype)initServerWithListener:(nonnull NSXPCListener *)listener; - -/** - Initializer for the 'server' side of the connection, started by launchd. - - @param name MachService name, must match the MachServices key in the launchd.plist -*/ -- (nullable instancetype)initServerWithName:(nonnull NSString *)name; - -/** - Initialize a new client to a service exported by a LaunchDaemon. - - @param name MachService name - @param privileged Use YES if the server is running as root. -*/ -- (nullable instancetype)initClientWithName:(nonnull NSString *)name privileged:(BOOL)privileged; - -/** - Initialize a new client to a service within a bundle. - - @param name service name -*/ -- (nullable instancetype)initClientWithServiceName:(nonnull NSString *)name; - -/** - Initialize a new client with a listener endpoint sent from another process. - - @param listener An NSXPCListenerEndpoint to connect to. -*/ -- (nullable instancetype)initClientWithListener:(nonnull NSXPCListenerEndpoint *)listener; - -/** - Call when the properties of the object have been set-up and you're ready for connections. - - For clients, this call can take up to 2s to complete for connection to finish establishing though - in basically all cases it will actually complete in a few milliseconds. -*/ -- (void)resume; - -/** - Invalidate the connection(s). This must be done before the object can be released. -*/ -- (void)invalidate; - -/** - The interface the remote object should conform to. (client) -*/ -@property(retain, nullable) NSXPCInterface *remoteInterface; - -/** - A proxy to the object at the other end of the connection. (client) - - @note If the connection to the server failed, this will be nil, so you can safely send messages - and rely on the invalidationHandler for handling the failure. -*/ -@property(readonly, nonatomic, nullable) id remoteObjectProxy; - -/** - The interface this object exports. (server) -*/ -@property(retain, nullable) NSXPCInterface *exportedInterface; - -/** - The object that responds to messages from the other end. (server) -*/ -@property(retain, nullable) id exportedObject; - -/** - A block to run when a/the connection is accepted and fully established. -*/ -@property(copy, nullable) void (^acceptedHandler)(void); - -/** - A block to run when a/the connection is invalidated/interrupted/rejected. -*/ -@property(copy, nullable) void (^invalidationHandler)(void); - -@end diff --git a/Source/common/SNTXPCConnection.m b/Source/common/SNTXPCConnection.m deleted file mode 100644 index 6d5041963..000000000 --- a/Source/common/SNTXPCConnection.m +++ /dev/null @@ -1,210 +0,0 @@ -/// Copyright 2015 Google Inc. All rights reserved. -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. - -#import "SNTXPCConnection.h" - -#import - -#import "SNTStrengthify.h" - -/** - Protocol used during connection establishment, @see SNTXPCConnectionInterface -*/ -@protocol SNTXPCConnectionProtocol -- (void)connectWithReply:(void (^)())reply; -@end - -/** - Recipient object used during connection establishment. Each incoming connection - has one of these objects created which accept the message in the protocol - and call the block provided during creation before replying. - - This allows the server to reset the connection's exported interface and - object to the correct values after the client has sent the establishment message. -*/ -@interface SNTXPCConnectionInterface : NSObject -@property(strong) void (^block)(void); -@end - -@implementation SNTXPCConnectionInterface -- (void)connectWithReply:(void (^)())reply { - if (self.block) self.block(); - reply(); -} -@end - -@interface SNTXPCConnection () -@property NSXPCInterface *validationInterface; - -/// The XPC listener (server only). -@property NSXPCListener *listenerObject; - -/// The current connection object (client only). -@property NSXPCConnection *currentConnection; -@end - -@implementation SNTXPCConnection - -#pragma mark Initializers - -- (instancetype)initServerWithListener:(NSXPCListener *)listener { - self = [super init]; - if (self) { - _listenerObject = listener; - _validationInterface = - [NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)]; - } - return self; -} - -- (instancetype)initServerWithName:(NSString *)name { - return [self initServerWithListener:[[NSXPCListener alloc] initWithMachServiceName:name]]; -} - -- (instancetype)initClientWithListener:(NSXPCListenerEndpoint *)listener { - self = [super init]; - if (self) { - _currentConnection = [[NSXPCConnection alloc] initWithListenerEndpoint:listener]; - if (!_currentConnection) return nil; - _validationInterface = - [NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)]; - } - return self; -} - -- (instancetype)initClientWithName:(NSString *)name privileged:(BOOL)privileged { - self = [super init]; - if (self) { - NSXPCConnectionOptions options = (privileged ? NSXPCConnectionPrivileged : 0); - _currentConnection = [[NSXPCConnection alloc] initWithMachServiceName:name options:options]; - if (!_currentConnection) return nil; - _validationInterface = - [NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)]; - } - return self; -} - -- (instancetype)initClientWithServiceName:(NSString *)name { - self = [super init]; - if (self) { - _currentConnection = [[NSXPCConnection alloc] initWithServiceName:name]; - if (!_currentConnection) return nil; - _validationInterface = - [NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)]; - } - return self; -} - -- (instancetype)init { - [self doesNotRecognizeSelector:_cmd]; - return nil; -} - -#pragma mark Connection set-up - -- (void)resume { - if (self.listenerObject) { - self.listenerObject.delegate = self; - [self.listenerObject resume]; - } else { - WEAKIFY(self); - - // Set-up the connection with the remote interface set to the validation interface, - // send a message to the listener to finish establishing the connection - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - self.currentConnection.remoteObjectInterface = self.validationInterface; - self.currentConnection.interruptionHandler = self.currentConnection.invalidationHandler = ^{ - STRONGIFY(self); - if (self.invalidationHandler) self.invalidationHandler(); - }; - [self.currentConnection resume]; - [[self.currentConnection remoteObjectProxy] connectWithReply:^{ - STRONGIFY(self); - // The connection is now established - [self.currentConnection suspend]; - self.currentConnection.remoteObjectInterface = self.remoteInterface; - [self.currentConnection resume]; - dispatch_semaphore_signal(sema); - if (self.acceptedHandler) self.acceptedHandler(); - }]; - if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC))) { - // This is unusual - as we're not inside a block - but necessary in case the caller sets an - // invalidation handler that causes this instance to be released (which is a reasonable - // approach). If establishing a connection fails, the invalidation handler will be called - // and then shortly after this bit of code will run causing a crash. - STRONGIFY(self); - - // Connection was not established in a reasonable time, invalidate. - self.currentConnection.remoteObjectInterface = nil; // ensure clients don't try to use it. - [self.currentConnection invalidate]; - } - } -} - -- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)connection { - pid_t pid = connection.processIdentifier; - MOLCodesignChecker *otherCS = [[MOLCodesignChecker alloc] initWithPID:pid]; - if (![otherCS signingInformationMatches:[[MOLCodesignChecker alloc] initWithSelf]]) { - return NO; - } - - // The client passed the code signature check, now we need to resume the listener and - // return YES so that the client can send the connectWithReply message. Once the client does - // we reset the connection's exportedInterface and exportedObject. - SNTXPCConnectionInterface *ci = [[SNTXPCConnectionInterface alloc] init]; - WEAKIFY(self); - WEAKIFY(connection); - ci.block = ^{ - STRONGIFY(self) - STRONGIFY(connection); - [connection suspend]; - connection.invalidationHandler = connection.interruptionHandler = ^{ - if (self.invalidationHandler) self.invalidationHandler(); - }; - connection.exportedInterface = self.exportedInterface; - connection.exportedObject = self.exportedObject; - [connection resume]; - - // The connection is now established. - if (self.acceptedHandler) self.acceptedHandler(); - }; - connection.exportedInterface = self.validationInterface; - connection.exportedObject = ci; - [connection resume]; - - return YES; -} - -- (id)remoteObjectProxy { - if (self.currentConnection.remoteObjectInterface && - self.currentConnection.remoteObjectInterface != self.validationInterface) { - return [self.currentConnection remoteObjectProxyWithErrorHandler:^(NSError *error) { - [self.currentConnection invalidate]; - }]; - } - return nil; -} - -#pragma mark Connection tear-down - -- (void)invalidate { - if (self.currentConnection) { - [self.currentConnection invalidate]; - self.currentConnection = nil; - } else if (self.listenerObject) { - [self.listenerObject invalidate]; - } -} - -@end diff --git a/Source/common/SNTXPCControlInterface.h b/Source/common/SNTXPCControlInterface.h index 4225c54a0..b81f43fd4 100644 --- a/Source/common/SNTXPCControlInterface.h +++ b/Source/common/SNTXPCControlInterface.h @@ -23,7 +23,7 @@ @class SNTRule; @class SNTStoredEvent; -@class SNTXPCConnection; +@class MOLXPCConnection; /// /// Protocol implemented by santad and utilized by santactl @@ -121,9 +121,9 @@ + (NSXPCInterface *)controlInterface; /// -/// Retrieve a pre-configured SNTXPCConnection for communicating with santad. +/// Retrieve a pre-configured MOLXPCConnection for communicating with santad. /// Connections just needs any handlers set and then can be resumed and used. /// -+ (SNTXPCConnection *)configuredConnection; ++ (MOLXPCConnection *)configuredConnection; @end diff --git a/Source/common/SNTXPCControlInterface.m b/Source/common/SNTXPCControlInterface.m index d3036cd7b..e577ae5df 100644 --- a/Source/common/SNTXPCControlInterface.m +++ b/Source/common/SNTXPCControlInterface.m @@ -14,9 +14,10 @@ #import "SNTXPCControlInterface.h" +#import + #import "SNTRule.h" #import "SNTStoredEvent.h" -#import "SNTXPCConnection.h" @implementation SNTXPCControlInterface @@ -50,8 +51,8 @@ + (NSXPCInterface *)controlInterface { return r; } -+ (SNTXPCConnection *)configuredConnection { - SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithName:[self serviceId] ++ (MOLXPCConnection *)configuredConnection { + MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithName:[self serviceId] privileged:YES]; c.remoteInterface = [self controlInterface]; return c; diff --git a/Source/santabs/SNTBundleService.m b/Source/santabs/SNTBundleService.m index 537f32918..07c62d9b9 100644 --- a/Source/santabs/SNTBundleService.m +++ b/Source/santabs/SNTBundleService.m @@ -18,15 +18,15 @@ #import #import +#import #import "SNTFileInfo.h" #import "SNTStoredEvent.h" -#import "SNTXPCConnection.h" #import "SNTXPCNotifierInterface.h" @interface SNTBundleService () -@property SNTXPCConnection *notifierConnection; -@property SNTXPCConnection *listener; +@property MOLXPCConnection *notifierConnection; +@property MOLXPCConnection *listener; @property(nonatomic) dispatch_queue_t queue; @end @@ -48,7 +48,7 @@ - (void)createConnection { // Create listener for return connection from SantaGUI. NSXPCListener *listener = [NSXPCListener anonymousListener]; - self.listener = [[SNTXPCConnection alloc] initServerWithListener:listener]; + self.listener = [[MOLXPCConnection alloc] initServerWithListener:listener]; self.listener.exportedInterface = [SNTXPCBundleServiceInterface bundleServiceInterface]; self.listener.exportedObject = self; self.listener.acceptedHandler = ^{ @@ -80,7 +80,7 @@ - (void)attemptReconnection { // Connect to the SantaGUI - (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener { dispatch_async(dispatch_get_main_queue(), ^{ - SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener]; + MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithListener:listener]; c.remoteInterface = [SNTXPCNotifierInterface bundleNotifierInterface]; [c resume]; self.notifierConnection = c; diff --git a/Source/santabs/main.m b/Source/santabs/main.m index 0d2bc73dd..23680427a 100644 --- a/Source/santabs/main.m +++ b/Source/santabs/main.m @@ -14,13 +14,14 @@ #import +#import + #import "SNTBundleService.h" #import "SNTXPCBundleServiceInterface.h" -#import "SNTXPCConnection.h" int main(int argc, const char *argv[]) { - SNTXPCConnection *c = - [[SNTXPCConnection alloc] initServerWithListener:[NSXPCListener serviceListener]]; + MOLXPCConnection *c = + [[MOLXPCConnection alloc] initServerWithListener:[NSXPCListener serviceListener]]; c.exportedInterface = [SNTXPCBundleServiceInterface bundleServiceInterface]; c.exportedObject = [[SNTBundleService alloc] init]; [c resume]; diff --git a/Source/santactl/Commands/SNTCommandBundleInfo.m b/Source/santactl/Commands/SNTCommandBundleInfo.m index e4c9ecb8f..5fec1d302 100644 --- a/Source/santactl/Commands/SNTCommandBundleInfo.m +++ b/Source/santactl/Commands/SNTCommandBundleInfo.m @@ -15,10 +15,11 @@ #import "SNTCommand.h" #import "SNTCommandController.h" +#import + #import "SNTFileInfo.h" #import "SNTLogging.h" #import "SNTStoredEvent.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @interface SNTCommandBundleInfo : SNTCommand diff --git a/Source/santactl/Commands/SNTCommandCheckCache.m b/Source/santactl/Commands/SNTCommandCheckCache.m index 5911305e4..f2f333ea8 100644 --- a/Source/santactl/Commands/SNTCommandCheckCache.m +++ b/Source/santactl/Commands/SNTCommandCheckCache.m @@ -17,8 +17,9 @@ #import "SNTCommand.h" #import "SNTCommandController.h" +#import + #import "SNTLogging.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" #include diff --git a/Source/santactl/Commands/SNTCommandFileInfo.m b/Source/santactl/Commands/SNTCommandFileInfo.m index 0458c6f46..2ba55c860 100644 --- a/Source/santactl/Commands/SNTCommandFileInfo.m +++ b/Source/santactl/Commands/SNTCommandFileInfo.m @@ -20,12 +20,12 @@ #import #import #import +#import #import "SNTCachedDecision.h" #import "SNTFileInfo.h" #import "SNTLogging.h" #import "SNTRule.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" // file info keys @@ -192,7 +192,7 @@ + (NSString *)longHelpText { kValidUntil ]; } -- (instancetype)initWithDaemonConnection:(SNTXPCConnection *)daemonConn { +- (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn { self = [super initWithDaemonConnection:daemonConn]; if (self) { _dateFormatter = [[NSDateFormatter alloc] init]; diff --git a/Source/santactl/Commands/SNTCommandFlushCache.m b/Source/santactl/Commands/SNTCommandFlushCache.m index 852e6d53d..f34fa90f5 100644 --- a/Source/santactl/Commands/SNTCommandFlushCache.m +++ b/Source/santactl/Commands/SNTCommandFlushCache.m @@ -17,8 +17,9 @@ #import "SNTCommand.h" #import "SNTCommandController.h" +#import + #import "SNTLogging.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @interface SNTCommandFlushCache : SNTCommand diff --git a/Source/santactl/Commands/SNTCommandRule.m b/Source/santactl/Commands/SNTCommandRule.m index 6a37a64ef..2e4dc0c03 100644 --- a/Source/santactl/Commands/SNTCommandRule.m +++ b/Source/santactl/Commands/SNTCommandRule.m @@ -19,13 +19,13 @@ #import #import +#import #import "SNTConfigurator.h" #import "SNTDropRootPrivs.h" #import "SNTFileInfo.h" #include "SNTLogging.h" #import "SNTRule.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @interface SNTCommandRule : SNTCommand @@ -164,7 +164,7 @@ - (void)runWithArguments:(NSArray *)arguments { }]; } -- (void)printStateOfRule:(SNTRule *)rule daemonConnection:(SNTXPCConnection *)daemonConn { +- (void)printStateOfRule:(SNTRule *)rule daemonConnection:(MOLXPCConnection *)daemonConn { NSString *fileSHA256 = (rule.type == SNTRuleTypeBinary) ? rule.shasum : nil; NSString *certificateSHA256 = (rule.type == SNTRuleTypeCertificate) ? rule.shasum : nil; dispatch_group_t group = dispatch_group_create(); diff --git a/Source/santactl/Commands/SNTCommandStatus.m b/Source/santactl/Commands/SNTCommandStatus.m index c4dcd48f5..3f154a301 100644 --- a/Source/santactl/Commands/SNTCommandStatus.m +++ b/Source/santactl/Commands/SNTCommandStatus.m @@ -17,8 +17,9 @@ #import "SNTCommand.h" #import "SNTCommandController.h" +#import + #import "SNTConfigurator.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @interface SNTCommandStatus : SNTCommand diff --git a/Source/santactl/Commands/SNTCommandVersion.m b/Source/santactl/Commands/SNTCommandVersion.m index 97b45ade7..7e2b06568 100644 --- a/Source/santactl/Commands/SNTCommandVersion.m +++ b/Source/santactl/Commands/SNTCommandVersion.m @@ -18,10 +18,11 @@ #import "SNTCommand.h" #import "SNTCommandController.h" +#import + #import "SNTCommonEnums.h" #import "SNTFileInfo.h" #import "SNTKernelCommon.h" -#import "SNTXPCConnection.h" @interface SNTCommandVersion : SNTCommand @end diff --git a/Source/santactl/Commands/sync/SNTCommandSync.m b/Source/santactl/Commands/sync/SNTCommandSync.m index 0e1e7d43c..a4f98bee8 100644 --- a/Source/santactl/Commands/sync/SNTCommandSync.m +++ b/Source/santactl/Commands/sync/SNTCommandSync.m @@ -17,15 +17,16 @@ #import "SNTCommand.h" #import "SNTCommandController.h" +#import + #import "SNTCommandSyncManager.h" #import "SNTConfigurator.h" #import "SNTDropRootPrivs.h" #import "SNTLogging.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @interface SNTCommandSync : SNTCommand -@property SNTXPCConnection *listener; +@property MOLXPCConnection *listener; @property SNTCommandSyncManager *syncManager; @end @@ -84,12 +85,12 @@ - (void)runWithArguments:(NSArray *)arguments { #pragma mark daemon methods -- (void)syncdWithDaemonConnection:(SNTXPCConnection *)daemonConn { +- (void)syncdWithDaemonConnection:(MOLXPCConnection *)daemonConn { dispatch_semaphore_t sema = dispatch_semaphore_create(0); // Create listener for return connection from daemon. NSXPCListener *listener = [NSXPCListener anonymousListener]; - self.listener = [[SNTXPCConnection alloc] initServerWithListener:listener]; + self.listener = [[MOLXPCConnection alloc] initServerWithListener:listener]; self.listener.exportedInterface = [SNTXPCSyncdInterface syncdInterface]; self.listener.exportedObject = self.syncManager; self.listener.acceptedHandler = ^{ @@ -108,6 +109,8 @@ - (void)syncdWithDaemonConnection:(SNTXPCConnection *)daemonConn { // Now wait for the connection to come in. if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) { + self.listener.invalidationHandler = nil; + [self.listener invalidate]; [self performSelectorInBackground:@selector(syncdWithDaemonConnection:) withObject:daemonConn]; } diff --git a/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m b/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m index abe902760..67dec2ca6 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncEventUpload.m @@ -17,13 +17,13 @@ #include "SNTLogging.h" #import +#import #import "NSData+Zlib.h" #import "SNTCommandSyncConstants.h" #import "SNTCommandSyncState.h" #import "SNTFileInfo.h" #import "SNTStoredEvent.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @implementation SNTCommandSyncEventUpload diff --git a/Source/santactl/Commands/sync/SNTCommandSyncManager.h b/Source/santactl/Commands/sync/SNTCommandSyncManager.h index c2fd81772..d80b6607f 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncManager.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncManager.h @@ -16,7 +16,7 @@ #import "SNTXPCSyncdInterface.h" -@class SNTXPCConnection; +@class MOLXPCConnection; /// /// Handles push notifications and periodic syncing with a sync server. @@ -37,7 +37,7 @@ /// @param daemon Set to YES if periodic syncing should occur. /// Set to NO if a single sync should be performed. NO is default. /// -- (instancetype)initWithDaemonConnection:(SNTXPCConnection *)daemonConn +- (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn isDaemon:(BOOL)daemon NS_DESIGNATED_INITIALIZER; /// diff --git a/Source/santactl/Commands/sync/SNTCommandSyncManager.m b/Source/santactl/Commands/sync/SNTCommandSyncManager.m index 830b3f02c..5e07bfc00 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncManager.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncManager.m @@ -18,6 +18,7 @@ #import #import +#import #import "SNTConfigurator.h" #import "SNTCommandSyncConstants.h" @@ -31,7 +32,6 @@ #import "SNTLogging.h" #import "SNTStoredEvent.h" #import "SNTStrengthify.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" #import "SNTXPCSyncdInterface.h" @@ -63,7 +63,7 @@ @interface SNTCommandSyncManager () { @property MOLFCMClient *FCMClient; -@property(nonatomic) SNTXPCConnection *daemonConn; +@property(nonatomic) MOLXPCConnection *daemonConn; @property BOOL targetedRuleSync; @@ -89,7 +89,7 @@ @implementation SNTCommandSyncManager #pragma mark init -- (instancetype)initWithDaemonConnection:(SNTXPCConnection *)daemonConn isDaemon:(BOOL)daemon { +- (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn isDaemon:(BOOL)daemon { self = [super init]; if (self) { _daemonConn = daemonConn; diff --git a/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m b/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m index 5595c0d83..238a6bd5a 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncPostflight.m @@ -16,9 +16,10 @@ #include "SNTLogging.h" +#import + #import "SNTCommandSyncConstants.h" #import "SNTCommandSyncState.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @implementation SNTCommandSyncPostflight diff --git a/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m b/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m index e2dab076a..f18657ec6 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncPreflight.m @@ -17,11 +17,12 @@ #include "SNTKernelCommon.h" #include "SNTLogging.h" +#import + #import "SNTCommandSyncConstants.h" #import "SNTCommandSyncState.h" #import "SNTConfigurator.h" #import "SNTSystemInfo.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" @implementation SNTCommandSyncPreflight diff --git a/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.m b/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.m index ff334f5c8..a50211972 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncRuleDownload.m @@ -14,10 +14,11 @@ #import "SNTCommandSyncRuleDownload.h" +#import + #import "SNTCommandSyncConstants.h" #import "SNTCommandSyncState.h" #import "SNTRule.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" #include "SNTLogging.h" diff --git a/Source/santactl/Commands/sync/SNTCommandSyncStage.h b/Source/santactl/Commands/sync/SNTCommandSyncStage.h index 8a55fcf78..8fb4dbba5 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncStage.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncStage.h @@ -15,13 +15,13 @@ #import @class SNTCommandSyncState; -@class SNTXPCConnection; +@class MOLXPCConnection; @interface SNTCommandSyncStage : NSObject @property(readonly, nonnull) NSURLSession *urlSession; @property(readonly, nonnull) SNTCommandSyncState *syncState; -@property(readonly, nonnull) SNTXPCConnection *daemonConn; +@property(readonly, nonnull) MOLXPCConnection *daemonConn; /** Initialize this stage. Designated initializer. diff --git a/Source/santactl/Commands/sync/SNTCommandSyncStage.m b/Source/santactl/Commands/sync/SNTCommandSyncStage.m index cbb87a528..927b84983 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncStage.m +++ b/Source/santactl/Commands/sync/SNTCommandSyncStage.m @@ -14,18 +14,19 @@ #import "SNTCommandSyncStage.h" +#import + #import "NSData+Zlib.h" #import "SNTCommandSyncConstants.h" #import "SNTCommandSyncState.h" #import "SNTLogging.h" #import "SNTXPCControlInterface.h" -#import "SNTXPCConnection.h" @interface SNTCommandSyncStage () @property(readwrite) NSURLSession *urlSession; @property(readwrite) SNTCommandSyncState *syncState; -@property(readwrite) SNTXPCConnection *daemonConn; +@property(readwrite) MOLXPCConnection *daemonConn; @property BOOL xsrfFetched; @end diff --git a/Source/santactl/Commands/sync/SNTCommandSyncState.h b/Source/santactl/Commands/sync/SNTCommandSyncState.h index 2af657509..2abf84c43 100644 --- a/Source/santactl/Commands/sync/SNTCommandSyncState.h +++ b/Source/santactl/Commands/sync/SNTCommandSyncState.h @@ -17,7 +17,7 @@ #import "SNTCommonEnums.h" @class SNTCommandSyncManager; -@class SNTXPCConnection; +@class MOLXPCConnection; /// An instance of this class is passed to each stage of the sync process for storing data /// that might be needed in later stages. @@ -27,7 +27,7 @@ @property NSURLSession *session; /// Connection to the daemon control interface. -@property SNTXPCConnection *daemonConn; +@property MOLXPCConnection *daemonConn; /// The base API URL. @property NSURL *syncBaseURL; diff --git a/Source/santactl/SNTCommand.h b/Source/santactl/SNTCommand.h index 3d74c4b96..a2db5dcc2 100644 --- a/Source/santactl/SNTCommand.h +++ b/Source/santactl/SNTCommand.h @@ -14,7 +14,7 @@ #import -@class SNTXPCConnection; +@class MOLXPCConnection; @protocol SNTCommandProtocol @@ -50,16 +50,16 @@ /// /// @note This method (or one of the methods it calls) is responsible for calling exit(). /// -+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn; ++ (void)runWithArguments:(NSArray *)arguments daemonConnection:(MOLXPCConnection *)daemonConn; @end @interface SNTCommand : NSObject -@property(nonatomic,readonly) SNTXPCConnection *daemonConn; +@property(nonatomic,readonly) MOLXPCConnection *daemonConn; /// Designated initializer -- (instancetype)initWithDaemonConnection:(SNTXPCConnection *)daemonConn; +- (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn; - (void)runWithArguments:(NSArray *)arguments; diff --git a/Source/santactl/SNTCommand.m b/Source/santactl/SNTCommand.m index 881fc6f14..211cf62fa 100644 --- a/Source/santactl/SNTCommand.m +++ b/Source/santactl/SNTCommand.m @@ -16,12 +16,12 @@ @implementation SNTCommand -+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn { ++ (void)runWithArguments:(NSArray *)arguments daemonConnection:(MOLXPCConnection *)daemonConn { id cmd = [[self alloc] initWithDaemonConnection:daemonConn]; [cmd runWithArguments:arguments]; } -- (instancetype)initWithDaemonConnection:(SNTXPCConnection *)daemonConn { +- (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn { self = [super init]; if (self) { _daemonConn = daemonConn; diff --git a/Source/santactl/SNTCommandController.h b/Source/santactl/SNTCommandController.h index 0e33dd5ea..33abdb664 100644 --- a/Source/santactl/SNTCommandController.h +++ b/Source/santactl/SNTCommandController.h @@ -16,7 +16,7 @@ #import "SNTCommand.h" -@class SNTXPCConnection; +@class MOLXPCConnection; /// /// Responsible for maintaining the list of available commands by name, printing their help text diff --git a/Source/santactl/SNTCommandController.m b/Source/santactl/SNTCommandController.m index 87f86cbc9..4d4b4f12f 100644 --- a/Source/santactl/SNTCommandController.m +++ b/Source/santactl/SNTCommandController.m @@ -14,7 +14,8 @@ #import "SNTCommandController.h" -#import "SNTXPCConnection.h" +#import + #import "SNTXPCControlInterface.h" @implementation SNTCommandController @@ -69,8 +70,8 @@ + (NSString *)helpForCommandWithName:(NSString *)commandName { return nil; } -+ (SNTXPCConnection *)connectToDaemonRequired:(BOOL)required { - SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; ++ (MOLXPCConnection *)connectToDaemonRequired:(BOOL)required { + MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection]; if (required) { daemonConn.invalidationHandler = ^{ @@ -94,7 +95,7 @@ + (void)runCommandWithName:(NSString *)commandName arguments:(NSArray *)argument exit(2); } - SNTXPCConnection *daemonConn = [self connectToDaemonRequired:[command requiresDaemonConn]]; + MOLXPCConnection *daemonConn = [self connectToDaemonRequired:[command requiresDaemonConn]]; [command runWithArguments:arguments daemonConnection:daemonConn]; // The command is responsible for quitting. diff --git a/Source/santad/Logs/SNTEventLog.h b/Source/santad/Logs/SNTEventLog.h index 5ae7126fe..178f5d8f0 100644 --- a/Source/santad/Logs/SNTEventLog.h +++ b/Source/santad/Logs/SNTEventLog.h @@ -40,7 +40,6 @@ - (NSString *)diskImageForDevice:(NSString *)devPath; - (NSString *)nameForUID:(uid_t)uid; - (NSString *)nameForGID:(gid_t)gid; -- (NSString *)sanitizeCString:(const char *)str ofLength:(NSUInteger)length; - (NSString *)sanitizeString:(NSString *)inStr; - (NSString *)serialForDevice:(NSString *)devPath; - (NSString *)originalPathForTranslocation:(santa_message_t)message; diff --git a/Source/santad/SNTApplication.m b/Source/santad/SNTApplication.m index 975bc3214..cc51ac518 100644 --- a/Source/santad/SNTApplication.m +++ b/Source/santad/SNTApplication.m @@ -16,6 +16,8 @@ #import +#import + #import "SNTCommonEnums.h" #import "SNTConfigurator.h" #import "SNTDaemonControlController.h" @@ -30,7 +32,6 @@ #import "SNTRuleTable.h" #import "SNTSyncdQueue.h" #import "SNTSyslogEventLog.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" #import "SNTXPCNotifierInterface.h" @@ -39,7 +40,7 @@ @interface SNTApplication () @property SNTDriverManager *driverManager; @property SNTEventLog *eventLog; @property SNTExecutionController *execController; -@property SNTXPCConnection *controlConnection; +@property MOLXPCConnection *controlConnection; @property SNTNotificationQueue *notQueue; @property pid_t syncdPID; @end @@ -115,7 +116,7 @@ - (instancetype)init { eventLog:_eventLog]; _controlConnection = - [[SNTXPCConnection alloc] initServerWithName:[SNTXPCControlInterface serviceId]]; + [[MOLXPCConnection alloc] initServerWithName:[SNTXPCControlInterface serviceId]]; _controlConnection.exportedInterface = [SNTXPCControlInterface controlInterface]; _controlConnection.exportedObject = dc; [_controlConnection resume]; diff --git a/Source/santad/SNTDaemonControlController.m b/Source/santad/SNTDaemonControlController.m index 96eae6958..a57d1bc50 100644 --- a/Source/santad/SNTDaemonControlController.m +++ b/Source/santad/SNTDaemonControlController.m @@ -14,6 +14,8 @@ #import "SNTDaemonControlController.h" +#import + #import "SNTCachedDecision.h" #import "SNTCommonEnums.h" #import "SNTConfigurator.h" @@ -30,7 +32,6 @@ #import "SNTStrengthify.h" #import "SNTSyncdQueue.h" #import "SNTXPCBundleServiceInterface.h" -#import "SNTXPCConnection.h" #import "SNTXPCNotifierInterface.h" #import "SNTXPCSyncdInterface.h" @@ -214,14 +215,16 @@ - (void)setBundlesEnabled:(BOOL)bundlesEnabled reply:(void (^)())reply { #pragma mark GUI Ops - (void)setNotificationListener:(NSXPCListenerEndpoint *)listener { - SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener]; + // This will leak the underlying NSXPCConnection when "fast user switching" occurs. + // It is not worth the trouble to fix. Maybe future self will feel differently. + MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithListener:listener]; c.remoteInterface = [SNTXPCNotifierInterface notifierInterface]; [c resume]; self.notQueue.notifierConnection = c; } - (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener { - SNTXPCConnection *bs = [[SNTXPCConnection alloc] initClientWithServiceName:@"com.google.santabs"]; + MOLXPCConnection *bs = [[MOLXPCConnection alloc] initClientWithServiceName:@"com.google.santabs"]; bs.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface]; [bs resume]; [[bs remoteObjectProxy] setBundleNotificationListener:listener]; @@ -233,12 +236,13 @@ - (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener { - (void)setSyncdListener:(NSXPCListenerEndpoint *)listener { // Only allow one active syncd connection if (self.syncdQueue.syncdConnection) return; - SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener]; + MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithListener:listener]; c.remoteInterface = [SNTXPCSyncdInterface syncdInterface]; c.invalidationHandler = ^{ [self.syncdQueue stopSyncingEvents]; + [self.syncdQueue.syncdConnection invalidate]; self.syncdQueue.syncdConnection = nil; - self.syncdQueue.invalidationHandler(); + if (self.syncdQueue.invalidationHandler) self.syncdQueue.invalidationHandler(); }; c.acceptedHandler = ^{ [self.syncdQueue startSyncingEvents]; @@ -275,8 +279,8 @@ - (void)postRuleSyncNotificationWithCustomMessage:(NSString *)message reply:(voi /// - (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event reply:(SNTBundleHashBlock)reply { - SNTXPCConnection *bs = - [[SNTXPCConnection alloc] initClientWithServiceName:[SNTXPCBundleServiceInterface serviceId]]; + MOLXPCConnection *bs = + [[MOLXPCConnection alloc] initClientWithServiceName:[SNTXPCBundleServiceInterface serviceId]]; bs.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface]; [bs resume]; [[bs remoteObjectProxy] hashBundleBinariesForEvent:event reply:reply]; diff --git a/Source/santad/SNTNotificationQueue.h b/Source/santad/SNTNotificationQueue.h index 4b6c165df..5b5c0cde5 100644 --- a/Source/santad/SNTNotificationQueue.h +++ b/Source/santad/SNTNotificationQueue.h @@ -15,11 +15,11 @@ #import @class SNTStoredEvent; -@class SNTXPCConnection; +@class MOLXPCConnection; @interface SNTNotificationQueue : NSObject -@property(nonatomic) SNTXPCConnection *notifierConnection; +@property(nonatomic) MOLXPCConnection *notifierConnection; - (void)addEvent:(SNTStoredEvent *)event customMessage:(NSString *)message; diff --git a/Source/santad/SNTNotificationQueue.m b/Source/santad/SNTNotificationQueue.m index c791296c9..f762c97fc 100644 --- a/Source/santad/SNTNotificationQueue.m +++ b/Source/santad/SNTNotificationQueue.m @@ -14,9 +14,10 @@ #import "SNTNotificationQueue.h" +#import + #import "SNTLogging.h" #import "SNTStoredEvent.h" -#import "SNTXPCConnection.h" #import "SNTXPCNotifierInterface.h" static const int kMaximumNotifications = 10; @@ -69,7 +70,7 @@ - (void)flushQueue { } } -- (void)setNotifierConnection:(SNTXPCConnection *)notifierConnection { +- (void)setNotifierConnection:(MOLXPCConnection *)notifierConnection { _notifierConnection = notifierConnection; [self flushQueue]; } diff --git a/Source/santad/SNTSyncdQueue.h b/Source/santad/SNTSyncdQueue.h index b91864962..db0eaee75 100644 --- a/Source/santad/SNTSyncdQueue.h +++ b/Source/santad/SNTSyncdQueue.h @@ -17,11 +17,11 @@ #import "SNTCommonEnums.h" @class SNTStoredEvent; -@class SNTXPCConnection; +@class MOLXPCConnection; @interface SNTSyncdQueue : NSObject -@property(nonatomic) SNTXPCConnection *syncdConnection; +@property(nonatomic) MOLXPCConnection *syncdConnection; @property(copy) void (^invalidationHandler)(); @property(copy) void (^acceptedHandler)(); diff --git a/Source/santad/SNTSyncdQueue.m b/Source/santad/SNTSyncdQueue.m index da711ab23..e48aaf673 100644 --- a/Source/santad/SNTSyncdQueue.m +++ b/Source/santad/SNTSyncdQueue.m @@ -14,9 +14,10 @@ #import "SNTSyncdQueue.h" +#import + #import "SNTLogging.h" #import "SNTStoredEvent.h" -#import "SNTXPCConnection.h" #import "SNTXPCSyncdInterface.h" @interface SNTSyncdQueue () diff --git a/Tests/LogicTests/SNTCommandFileInfoTest.m b/Tests/LogicTests/SNTCommandFileInfoTest.m index de95441c7..046733aff 100644 --- a/Tests/LogicTests/SNTCommandFileInfoTest.m +++ b/Tests/LogicTests/SNTCommandFileInfoTest.m @@ -17,9 +17,9 @@ #import #import +#import #import "SNTFileInfo.h" -#import "SNTXPCConnection.h" @interface SNTCommandFileInfo : NSObject @@ -32,7 +32,7 @@ @interface SNTCommandFileInfo : NSObject + (NSArray *)fileInfoKeys; + (NSArray *)signingChainKeys; - (SNTAttributeBlock)codeSigned; -- (instancetype)initWithDaemonConnection:(SNTXPCConnection *)daemonConn; +- (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn; - (NSArray *)parseArguments:(NSArray *)arguments; @end diff --git a/Tests/LogicTests/SNTCommandSyncTest.m b/Tests/LogicTests/SNTCommandSyncTest.m index 77265b315..a539b12d6 100644 --- a/Tests/LogicTests/SNTCommandSyncTest.m +++ b/Tests/LogicTests/SNTCommandSyncTest.m @@ -15,6 +15,7 @@ #import #import +#import #import "SNTCommandSyncConstants.h" #import "SNTCommandSyncEventUpload.h" @@ -26,7 +27,6 @@ #import "SNTCommonEnums.h" #import "SNTRule.h" #import "SNTStoredEvent.h" -#import "SNTXPCConnection.h" #import "SNTXPCControlInterface.h" // Prevent Zlib compression during testing @@ -50,7 +50,7 @@ - (void)setUp { [super setUp]; self.syncState = [[SNTCommandSyncState alloc] init]; - self.syncState.daemonConn = OCMClassMock([SNTXPCConnection class]); + self.syncState.daemonConn = OCMClassMock([MOLXPCConnection class]); self.daemonConnRop = OCMProtocolMock(@protocol(SNTDaemonControlXPC)); OCMStub([self.syncState.daemonConn remoteObjectProxy]).andReturn(self.daemonConnRop); diff --git a/Tests/LogicTests/SNTXPCConnectionTest.m b/Tests/LogicTests/SNTXPCConnectionTest.m deleted file mode 100644 index 8c2f6a638..000000000 --- a/Tests/LogicTests/SNTXPCConnectionTest.m +++ /dev/null @@ -1,124 +0,0 @@ -/// Copyright 2015 Google Inc. All rights reserved. -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. - -#import - -#import -#import - -#import "SNTXPCConnection.h" - -@interface SNTXPCConnectionTest : XCTestCase -@end - -@implementation SNTXPCConnectionTest - -- (void)testPlainInit { - XCTAssertThrows([[SNTXPCConnection alloc] init]); -} - -- (void)testInitClient { - id mockConnection = OCMClassMock([NSXPCConnection class]); - OCMStub([mockConnection alloc]).andReturn(mockConnection); - OCMExpect([mockConnection initWithMachServiceName:@"Client" - options:0]).andReturn(mockConnection); - - SNTXPCConnection *sut = [[SNTXPCConnection alloc] initClientWithName:@"Client" privileged:NO]; - XCTAssertNotNil(sut); - - OCMExpect([mockConnection initWithMachServiceName:@"Client" - options:NSXPCConnectionPrivileged]).andReturn( - mockConnection); - sut = [[SNTXPCConnection alloc] initClientWithName:@"Client" privileged:YES]; - XCTAssertNotNil(sut); - - OCMVerifyAll(mockConnection); - [mockConnection stopMocking]; -} - -- (void)testInitServer { - id mockListener = OCMClassMock([NSXPCListener class]); - OCMStub([mockListener alloc]).andReturn(mockListener); - OCMExpect([mockListener initWithMachServiceName:@"TestServer"]).andReturn(mockListener); - SNTXPCConnection *sut = [[SNTXPCConnection alloc] initServerWithName:@"TestServer"]; - XCTAssertNotNil(sut); - OCMVerifyAll(mockListener); - [mockListener stopMocking]; -} - -- (void)testConnectionRejection { - pid_t pid = [[NSProcessInfo processInfo] processIdentifier]; - id mockCodesignChecker = OCMClassMock([MOLCodesignChecker class]); - OCMStub([mockCodesignChecker alloc]).andReturn(mockCodesignChecker); - OCMExpect([mockCodesignChecker initWithPID:pid]).andReturn(mockCodesignChecker); - OCMExpect([mockCodesignChecker signingInformationMatches:OCMOCK_ANY]).andReturn(NO); - - NSXPCListener *listener = [NSXPCListener anonymousListener]; - - SNTXPCConnection *sutServer = [[SNTXPCConnection alloc] initServerWithListener:listener]; - [sutServer resume]; - - __block XCTestExpectation *exp1 = [self expectationWithDescription:@"Client Invalidated"]; - SNTXPCConnection *sutClient = [[SNTXPCConnection alloc] initClientWithListener:listener.endpoint]; - sutClient.invalidationHandler = ^{ - [exp1 fulfill]; - exp1 = nil; // precent multiple fulfill violation - }; - [sutClient resume]; - - [self waitForExpectationsWithTimeout:3.0 handler:NULL]; - - [mockCodesignChecker stopMocking]; -} - -- (void)testConnectionAcceptance { - NSXPCListener *listener = [NSXPCListener anonymousListener]; - - XCTestExpectation *exp1 = [self expectationWithDescription:@"Server Accepted"]; - SNTXPCConnection *sutServer = [[SNTXPCConnection alloc] initServerWithListener:listener]; - sutServer.acceptedHandler = ^{ - [exp1 fulfill]; - }; - [sutServer resume]; - - XCTestExpectation *exp2 = [self expectationWithDescription:@"Client Accepted"]; - SNTXPCConnection *sutClient = [[SNTXPCConnection alloc] initClientWithListener:listener.endpoint]; - sutClient.acceptedHandler = ^{ - [exp2 fulfill]; - }; - [sutClient resume]; - - [self waitForExpectationsWithTimeout:2.0 handler:NULL]; -} - -- (void)testConnectionInterruption { - NSXPCListener *listener = [NSXPCListener anonymousListener]; - SNTXPCConnection *sutServer = [[SNTXPCConnection alloc] initServerWithListener:listener]; - [sutServer resume]; - - __block XCTestExpectation *exp1 = [self expectationWithDescription:@"Client Invalidated"]; - SNTXPCConnection *sutClient = [[SNTXPCConnection alloc] initClientWithListener:listener.endpoint]; - sutClient.invalidationHandler = ^{ - [exp1 fulfill]; - exp1 = nil; // prevent multiple fulfill violation - }; - [sutClient resume]; - - [sutServer invalidate]; - sutServer = nil; - - [self waitForExpectationsWithTimeout:1.0 handler:NULL]; -} - -@end From 2b1ddf9a4ed757bc693b5bdc769fb911f6185617 Mon Sep 17 00:00:00 2001 From: Matthew Suozzo Date: Wed, 9 May 2018 21:53:51 -0400 Subject: [PATCH 25/25] Fix typo in sync help text (#259) --- Source/santactl/Commands/sync/SNTCommandSync.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/santactl/Commands/sync/SNTCommandSync.m b/Source/santactl/Commands/sync/SNTCommandSync.m index a4f98bee8..2d54511f5 100644 --- a/Source/santactl/Commands/sync/SNTCommandSync.m +++ b/Source/santactl/Commands/sync/SNTCommandSync.m @@ -49,7 +49,7 @@ + (NSString *)shortHelpText { } + (NSString *)longHelpText { - return (@"If Santa is configured to synchronize with a a server, " + return (@"If Santa is configured to synchronize with a server, " @"this is the command used for syncing.\n\n" @"Options:\n" @" --clean: Perform a clean sync, erasing all existing rules and requesting a"