mirror of
https://github.com/google/santa.git
synced 2026-01-15 01:08:12 -05:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cafef66933 | ||
|
|
0c4e9d4b06 | ||
|
|
ac07f5d54b | ||
|
|
d116f7b01e | ||
|
|
63ca34bc54 | ||
|
|
c894029c33 | ||
|
|
de2bdd6653 | ||
|
|
2d066ad671 | ||
|
|
24854d4ad7 | ||
|
|
99ee0af178 | ||
|
|
bf6f78df09 | ||
|
|
c05806916b | ||
|
|
e48ce0cfe3 | ||
|
|
eabca469b9 | ||
|
|
f6dc36e812 | ||
|
|
ac7cbdfd16 |
@@ -8,6 +8,7 @@ addons:
|
||||
homebrew:
|
||||
taps: bazelbuild/tap
|
||||
packages: bazelbuild/tap/bazel
|
||||
update: true
|
||||
|
||||
script:
|
||||
- bazel build :release --show_progress_rate_limit=30.0 -c opt --apple_generate_dsym --color=no --verbose_failures --sandbox_debug
|
||||
|
||||
4
BUILD
4
BUILD
@@ -130,6 +130,10 @@ genrule(
|
||||
mkdir -p $(@D)/dsym
|
||||
cp -LR $$(dirname $$(dirname $${SRC})) $(@D)/dsym/Santa.app.dSYM
|
||||
;;
|
||||
*com.google.santa.daemon.systemextension.dSYM*Info.plist)
|
||||
mkdir -p $(@D)/dsym
|
||||
cp -LR $$(dirname $$(dirname $${SRC})) $(@D)/dsym/com.google.santa.daemon.systemextension.dSYM
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ PODS:
|
||||
- MOLAuthenticatingURLSession (~> 2.4)
|
||||
- MOLXPCConnection (1.2):
|
||||
- MOLCodesignChecker (~> 1.9)
|
||||
- OCMock (3.4.3)
|
||||
- OCMock (3.5)
|
||||
|
||||
DEPENDENCIES:
|
||||
- FMDB
|
||||
@@ -39,7 +39,7 @@ SPEC CHECKSUMS:
|
||||
MOLCodesignChecker: b0d5db9d2f9bd94e0fd093891a5d40e5ad77cbc0
|
||||
MOLFCMClient: 2bfbacd45cc11e1ca3c077e97b80401c4e4a54f1
|
||||
MOLXPCConnection: c27af5cb1c43b18319698b0e568a8ddc2fc1e306
|
||||
OCMock: 43565190abc78977ad44a61c0d20d7f0784d35ab
|
||||
OCMock: 4ab4577fc941af31f4a0398f6e7e230cf21fc72a
|
||||
|
||||
PODFILE CHECKSUM: d03767a9915896232523962c98d9ff7294aec2b7
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</p>
|
||||
|
||||
Santa is a binary whitelisting/blacklisting system for macOS. It consists of a
|
||||
kernel extension that monitors for executions, a userland daemon that makes
|
||||
kernel extension (or a system extension on macOS 10.15+) that monitors for executions, a userland daemon that makes
|
||||
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.
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
0D9F577C2342650F005D9AA8 /* SNTPrefixTree.cc in Sources */ = {isa = PBXBuildFile; fileRef = C7658B022322B84F00F36578 /* SNTPrefixTree.cc */; };
|
||||
59502195B2982225D3706DCE /* libPods-santabundleservice.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A55D73A235850B9FA991865 /* libPods-santabundleservice.a */; };
|
||||
AD3736AF78C41A962C26D429 /* libPods-Santa.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C3E743944A9D77423AA1534 /* libPods-Santa.a */; };
|
||||
B5AE6BB811766CA492133559 /* libPods-santad.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3700D40B536CA7F626B76156 /* libPods-santad.a */; };
|
||||
C71E472F22F0F97B00921CD9 /* com.google.santa.daemon in CopyFiles */ = {isa = PBXBuildFile; fileRef = C779C4E622F0F51400EE2541 /* com.google.santa.daemon */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
C71E473122F0FAA100921CD9 /* com.google.santa.daemon.systemextension in CopyFiles */ = {isa = PBXBuildFile; fileRef = C7A8308022F0F81F00F856AC /* com.google.santa.daemon.systemextension */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
C72ED2B62324962400255555 /* SNTEndpointSecurityManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = C72ED2B52324962400255555 /* SNTEndpointSecurityManager.mm */; };
|
||||
@@ -110,6 +109,7 @@
|
||||
C7F5C1AF233E72CF00A3F7FD /* SNTBundleService.m in Sources */ = {isa = PBXBuildFile; fileRef = C7658AF22322B84F00F36578 /* SNTBundleService.m */; };
|
||||
C7F5C1B0233E735E00A3F7FD /* santabundleservice in CopyFiles */ = {isa = PBXBuildFile; fileRef = C7F5C1A7233E72BC00A3F7FD /* santabundleservice */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
D28CA4C618C62392319BB642 /* libPods-santactl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B7714ABC7F247685608DACE7 /* libPods-santactl.a */; };
|
||||
D698C8C9E47554577ED4939F /* libPods-com.google.santa.daemon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C05F6AD95EB704B20828BDA1 /* libPods-com.google.santa.daemon.a */; };
|
||||
F5F5D1EF2AF051FEA97A3A59 /* libPods-sysx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 91FF0B4E62F1E90A88478993 /* libPods-sysx.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -189,12 +189,13 @@
|
||||
18183794C94BAEAD167B12EC /* Pods-santad.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad.debug.xcconfig"; path = "Target Support Files/Pods-santad/Pods-santad.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
24CDFD218D8B35E34895AA6A /* libPods-santaxpcproxy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santaxpcproxy.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2A55D73A235850B9FA991865 /* libPods-santabundleservice.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santabundleservice.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3700D40B536CA7F626B76156 /* libPods-santad.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santad.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4C3E743944A9D77423AA1534 /* libPods-Santa.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Santa.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4E28DBA012524ABF55F8300C /* Pods-com.google.santa.daemon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-com.google.santa.daemon.debug.xcconfig"; path = "Target Support Files/Pods-com.google.santa.daemon/Pods-com.google.santa.daemon.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
7AF15DF785BAA0EAB0BE340D /* Pods-santad.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad.release.xcconfig"; path = "Target Support Files/Pods-santad/Pods-santad.release.xcconfig"; sourceTree = "<group>"; };
|
||||
91FF0B4E62F1E90A88478993 /* libPods-sysx.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-sysx.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B7714ABC7F247685608DACE7 /* libPods-santactl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santactl.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C05543B3701F50CA798B4B11 /* Pods-sysx.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-sysx.release.xcconfig"; path = "Target Support Files/Pods-sysx/Pods-sysx.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C05F6AD95EB704B20828BDA1 /* libPods-com.google.santa.daemon.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-com.google.santa.daemon.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C72ED2B3232495CC00255555 /* SNTEventProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTEventProvider.h; sourceTree = "<group>"; };
|
||||
C72ED2B42324962400255555 /* SNTEndpointSecurityManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTEndpointSecurityManager.h; sourceTree = "<group>"; };
|
||||
C72ED2B52324962400255555 /* SNTEndpointSecurityManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SNTEndpointSecurityManager.mm; sourceTree = "<group>"; };
|
||||
@@ -369,6 +370,7 @@
|
||||
D7360306D7CFDD179D003266 /* Pods-sysx.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-sysx.debug.xcconfig"; path = "Target Support Files/Pods-sysx/Pods-sysx.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D979E8ECE019FB93D1D381E7 /* Pods-santaxpcproxy.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santaxpcproxy.release.xcconfig"; path = "Target Support Files/Pods-santaxpcproxy/Pods-santaxpcproxy.release.xcconfig"; sourceTree = "<group>"; };
|
||||
E6D38874F31422095E853E99 /* Pods-Santa.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Santa.debug.xcconfig"; path = "Target Support Files/Pods-Santa/Pods-Santa.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
E734E4FECEAA502AFF104E71 /* Pods-com.google.santa.daemon.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-com.google.santa.daemon.release.xcconfig"; path = "Target Support Files/Pods-com.google.santa.daemon/Pods-com.google.santa.daemon.release.xcconfig"; sourceTree = "<group>"; };
|
||||
EDF64F091E796EC4013F5499 /* Pods-santaxpcproxy.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santaxpcproxy.debug.xcconfig"; path = "Target Support Files/Pods-santaxpcproxy/Pods-santaxpcproxy.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
FE1F7C320CAEA468FAAC05B0 /* Pods-santabundleservice.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santabundleservice.release.xcconfig"; path = "Target Support Files/Pods-santabundleservice/Pods-santabundleservice.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -396,7 +398,7 @@
|
||||
files = (
|
||||
C72ED2BC232584C100255555 /* libbsm.tbd in Frameworks */,
|
||||
C72ED2B82324A2FA00255555 /* libEndpointSecurity.tbd in Frameworks */,
|
||||
B5AE6BB811766CA492133559 /* libPods-santad.a in Frameworks */,
|
||||
D698C8C9E47554577ED4939F /* libPods-com.google.santa.daemon.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -767,11 +769,11 @@
|
||||
C72ED2B9232584AA00255555 /* libauditd.tbd */,
|
||||
C72ED2B72324A2FA00255555 /* libEndpointSecurity.tbd */,
|
||||
4C3E743944A9D77423AA1534 /* libPods-Santa.a */,
|
||||
3700D40B536CA7F626B76156 /* libPods-santad.a */,
|
||||
91FF0B4E62F1E90A88478993 /* libPods-sysx.a */,
|
||||
24CDFD218D8B35E34895AA6A /* libPods-santaxpcproxy.a */,
|
||||
2A55D73A235850B9FA991865 /* libPods-santabundleservice.a */,
|
||||
B7714ABC7F247685608DACE7 /* libPods-santactl.a */,
|
||||
C05F6AD95EB704B20828BDA1 /* libPods-com.google.santa.daemon.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -791,6 +793,8 @@
|
||||
FE1F7C320CAEA468FAAC05B0 /* Pods-santabundleservice.release.xcconfig */,
|
||||
052CCA75535669B953A31D6D /* Pods-santactl.debug.xcconfig */,
|
||||
0A60226B8B4F01BE817BAAA3 /* Pods-santactl.release.xcconfig */,
|
||||
4E28DBA012524ABF55F8300C /* Pods-com.google.santa.daemon.debug.xcconfig */,
|
||||
E734E4FECEAA502AFF104E71 /* Pods-com.google.santa.daemon.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@@ -1036,7 +1040,7 @@
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-santad-checkManifestLockResult.txt",
|
||||
"$(DERIVED_FILE_DIR)/Pods-com.google.santa.daemon-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
@@ -1445,7 +1449,7 @@
|
||||
};
|
||||
C779C4EB22F0F51400EE2541 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 18183794C94BAEAD167B12EC /* Pods-santad.debug.xcconfig */;
|
||||
baseConfigurationReference = 4E28DBA012524ABF55F8300C /* Pods-com.google.santa.daemon.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = Source/santad/com.google.santa.daemon.systemextension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
@@ -1464,7 +1468,7 @@
|
||||
};
|
||||
C779C4EC22F0F51400EE2541 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AF15DF785BAA0EAB0BE340D /* Pods-santad.release.xcconfig */;
|
||||
baseConfigurationReference = E734E4FECEAA502AFF104E71 /* Pods-com.google.santa.daemon.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = Source/santad/com.google.santa.daemon.systemextension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
|
||||
@@ -149,6 +149,7 @@ objc_library(
|
||||
srcs = ["SNTXPCControlInterface.m"],
|
||||
hdrs = ["SNTXPCControlInterface.h"],
|
||||
deps = [
|
||||
":SNTConfigurator",
|
||||
":SNTStoredEvent",
|
||||
":SNTXPCUnprivilegedControlInterface",
|
||||
"@MOLXPCConnection",
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#import "Source/common/SNTCommonEnums.h"
|
||||
#import "Source/common/SNTKernelCommon.h"
|
||||
|
||||
@class MOLCertificate;
|
||||
|
||||
///
|
||||
/// Store information about executions from decision making for later logging.
|
||||
///
|
||||
@@ -26,8 +28,11 @@
|
||||
@property SNTEventState decision;
|
||||
@property NSString *decisionExtra;
|
||||
@property NSString *sha256;
|
||||
|
||||
@property NSString *certSHA256;
|
||||
@property NSString *certCommonName;
|
||||
@property NSArray<MOLCertificate *> *certChain;
|
||||
|
||||
@property NSString *quarantineURL;
|
||||
|
||||
@property NSString *customMsg;
|
||||
|
||||
@@ -130,6 +130,14 @@
|
||||
///
|
||||
@property(readonly, nonatomic) BOOL enablePageZeroProtection;
|
||||
|
||||
///
|
||||
/// Enable bad signature protection, defaults to NO.
|
||||
/// When enabled, a binary that is signed but has a bad signature (cert revoked, binary
|
||||
/// tampered with, etc.) will be blocked regardless of client-mode unless a binary whitelist
|
||||
/// rule exists.
|
||||
///
|
||||
@property(readonly, nonatomic) BOOL enableBadSignatureProtection;
|
||||
|
||||
///
|
||||
/// Defines how event logs are stored. Options are:
|
||||
/// SNTEventLogTypeSyslog: Sent to ASL or ULS (if built with the 10.12 SDK or later).
|
||||
@@ -156,6 +164,15 @@
|
||||
///
|
||||
@property(readonly, nonatomic) BOOL enableMachineIDDecoration;
|
||||
|
||||
///
|
||||
/// Use the bundled SystemExtension on macOS 10.15+, defaults to YES.
|
||||
/// Disable to continue using the bundled KEXT.
|
||||
/// This is a one way switch, if this is ever true on macOS 10.15+ the KEXT will be deleted.
|
||||
/// This gives admins control over the timing of switching to the SystemExtension. The intended use case is to have an MDM deliver
|
||||
/// the requisite SystemExtension and TCC profiles before attempting to load.
|
||||
///
|
||||
@property(readonly, nonatomic) BOOL enableSystemExtension;
|
||||
|
||||
#pragma mark - GUI Settings
|
||||
|
||||
///
|
||||
|
||||
@@ -66,6 +66,7 @@ static NSString *const kModeNotificationMonitor = @"ModeNotificationMonitor";
|
||||
static NSString *const kModeNotificationLockdown = @"ModeNotificationLockdown";
|
||||
|
||||
static NSString *const kEnablePageZeroProtectionKey = @"EnablePageZeroProtection";
|
||||
static NSString *const kEnableBadSignatureProtectionKey = @"EnableBadSignatureProtection";
|
||||
|
||||
static NSString *const kFileChangesRegexKey = @"FileChangesRegex";
|
||||
static NSString *const kFileChangesPrefixFiltersKey = @"FileChangesPrefixFilters";
|
||||
@@ -75,6 +76,8 @@ static NSString *const kEventLogPath = @"EventLogPath";
|
||||
|
||||
static NSString *const kEnableMachineIDDecoration = @"EnableMachineIDDecoration";
|
||||
|
||||
static NSString *const kEnableSystemExtension = @"EnableSystemExtension";
|
||||
|
||||
// The keys managed by a sync server or mobileconfig.
|
||||
static NSString *const kClientModeKey = @"ClientMode";
|
||||
static NSString *const kEnableTransitiveWhitelistingKey = @"EnableTransitiveWhitelisting";
|
||||
@@ -112,6 +115,7 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
|
||||
kWhitelistRegexKey : re,
|
||||
kBlacklistRegexKey : re,
|
||||
kEnablePageZeroProtectionKey : number,
|
||||
kEnableBadSignatureProtectionKey: number,
|
||||
kMoreInfoURLKey : string,
|
||||
kEventDetailURLKey : string,
|
||||
kEventDetailTextKey : string,
|
||||
@@ -135,6 +139,7 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
|
||||
kEventLogType : string,
|
||||
kEventLogPath : string,
|
||||
kEnableMachineIDDecoration : number,
|
||||
kEnableSystemExtension : number,
|
||||
};
|
||||
_defaults = [NSUserDefaults standardUserDefaults];
|
||||
[_defaults addSuiteNamed:@"com.google.santa"];
|
||||
@@ -301,6 +306,10 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
|
||||
return [self syncAndConfigStateSet];
|
||||
}
|
||||
|
||||
+ (NSSet *)keyPathsForValuesAffectingEnableSystemExtension {
|
||||
return [self configStateSet];
|
||||
}
|
||||
|
||||
#pragma mark Public Interface
|
||||
|
||||
- (SNTClientMode)clientMode {
|
||||
@@ -381,6 +390,11 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
|
||||
return number ? [number boolValue] : YES;
|
||||
}
|
||||
|
||||
- (BOOL)enableBadSignatureProtection {
|
||||
NSNumber *number = self.configState[kEnableBadSignatureProtectionKey];
|
||||
return number ? [number boolValue] : NO;
|
||||
}
|
||||
|
||||
- (NSURL *)moreInfoURL {
|
||||
return [NSURL URLWithString:self.configState[kMoreInfoURLKey]];
|
||||
}
|
||||
@@ -501,6 +515,17 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
|
||||
return number ? [number boolValue] : NO;
|
||||
}
|
||||
|
||||
- (BOOL)enableSystemExtension {
|
||||
if (@available(macOS 10.15, *)) {
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
if (![fm fileExistsAtPath:@"/Library/Extensions/santa-driver.kext"]) return YES;
|
||||
NSNumber *number = self.configState[kEnableSystemExtension];
|
||||
return number ? [number boolValue] : YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Private
|
||||
|
||||
///
|
||||
|
||||
@@ -143,67 +143,71 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
|
||||
- (void)hashSHA1:(NSString **)sha1 SHA256:(NSString **)sha256 {
|
||||
const int MAX_CHUNK_SIZE = 256 * 1024; // 256 KB
|
||||
const size_t chunkSize = _fileSize > MAX_CHUNK_SIZE ? MAX_CHUNK_SIZE : _fileSize;
|
||||
char chunk[chunkSize];
|
||||
char *chunk = malloc(chunkSize);
|
||||
|
||||
CC_SHA1_CTX c1;
|
||||
CC_SHA256_CTX c256;
|
||||
@try {
|
||||
CC_SHA1_CTX c1;
|
||||
CC_SHA256_CTX c256;
|
||||
|
||||
if (sha1) CC_SHA1_Init(&c1);
|
||||
if (sha256) CC_SHA256_Init(&c256);
|
||||
if (sha1) CC_SHA1_Init(&c1);
|
||||
if (sha256) CC_SHA256_Init(&c256);
|
||||
|
||||
int fd = self.fileHandle.fileDescriptor;
|
||||
int fd = self.fileHandle.fileDescriptor;
|
||||
|
||||
fcntl(fd, F_RDAHEAD, 1);
|
||||
struct radvisory radv;
|
||||
radv.ra_offset = 0;
|
||||
const int MAX_ADVISORY_READ = 10 * 1024 * 1024;
|
||||
radv.ra_count = (int)_fileSize < MAX_ADVISORY_READ ? (int)_fileSize : MAX_ADVISORY_READ;
|
||||
fcntl(fd, F_RDADVISE, &radv);
|
||||
ssize_t bytesRead;
|
||||
fcntl(fd, F_RDAHEAD, 1);
|
||||
struct radvisory radv;
|
||||
radv.ra_offset = 0;
|
||||
const int MAX_ADVISORY_READ = 10 * 1024 * 1024;
|
||||
radv.ra_count = (int)_fileSize < MAX_ADVISORY_READ ? (int)_fileSize : MAX_ADVISORY_READ;
|
||||
fcntl(fd, F_RDADVISE, &radv);
|
||||
ssize_t bytesRead;
|
||||
|
||||
for (uint64_t offset = 0; offset < _fileSize;) {
|
||||
bytesRead = pread(fd, chunk, chunkSize, offset);
|
||||
if (bytesRead > 0) {
|
||||
if (sha1) CC_SHA1_Update(&c1, chunk, (CC_LONG)bytesRead);
|
||||
if (sha256) CC_SHA256_Update(&c256, chunk, (CC_LONG)bytesRead);
|
||||
offset += bytesRead;
|
||||
} else if (bytesRead == -1 && errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
for (uint64_t offset = 0; offset < _fileSize;) {
|
||||
bytesRead = pread(fd, chunk, chunkSize, offset);
|
||||
if (bytesRead > 0) {
|
||||
if (sha1) CC_SHA1_Update(&c1, chunk, (CC_LONG)bytesRead);
|
||||
if (sha256) CC_SHA256_Update(&c256, chunk, (CC_LONG)bytesRead);
|
||||
offset += bytesRead;
|
||||
} else if (bytesRead == -1 && errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We turn off Read Ahead that we turned on
|
||||
fcntl(fd, F_RDAHEAD, 0);
|
||||
if (sha1) {
|
||||
unsigned char digest[CC_SHA1_DIGEST_LENGTH];
|
||||
CC_SHA1_Final(digest, &c1);
|
||||
NSString *const SHA1FormatString =
|
||||
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x";
|
||||
*sha1 = [[NSString alloc]
|
||||
initWithFormat:SHA1FormatString, digest[0], digest[1], digest[2],
|
||||
digest[3], digest[4], digest[5], digest[6], digest[7],
|
||||
digest[8], digest[9], digest[10], digest[11], digest[12],
|
||||
digest[13], digest[14], digest[15], digest[16],
|
||||
digest[17], digest[18], digest[19]];
|
||||
}
|
||||
if (sha256) {
|
||||
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
|
||||
CC_SHA256_Final(digest, &c256);
|
||||
NSString *const SHA256FormatString =
|
||||
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x";
|
||||
// We turn off Read Ahead that we turned on
|
||||
fcntl(fd, F_RDAHEAD, 0);
|
||||
if (sha1) {
|
||||
unsigned char digest[CC_SHA1_DIGEST_LENGTH];
|
||||
CC_SHA1_Final(digest, &c1);
|
||||
NSString *const SHA1FormatString =
|
||||
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x";
|
||||
*sha1 = [[NSString alloc]
|
||||
initWithFormat:SHA1FormatString, digest[0], digest[1], digest[2],
|
||||
digest[3], digest[4], digest[5], digest[6], digest[7],
|
||||
digest[8], digest[9], digest[10], digest[11], digest[12],
|
||||
digest[13], digest[14], digest[15], digest[16],
|
||||
digest[17], digest[18], digest[19]];
|
||||
}
|
||||
if (sha256) {
|
||||
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
|
||||
CC_SHA256_Final(digest, &c256);
|
||||
NSString *const SHA256FormatString =
|
||||
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x";
|
||||
|
||||
*sha256 = [[NSString alloc]
|
||||
initWithFormat:SHA256FormatString, digest[0], digest[1], digest[2],
|
||||
digest[3], digest[4], digest[5], digest[6], digest[7],
|
||||
digest[8], digest[9], digest[10], digest[11], digest[12],
|
||||
digest[13], digest[14], digest[15], digest[16],
|
||||
digest[17], digest[18], digest[19], digest[20],
|
||||
digest[21], digest[22], digest[23], digest[24],
|
||||
digest[25], digest[26], digest[27], digest[28],
|
||||
digest[29], digest[30], digest[31]];
|
||||
*sha256 = [[NSString alloc]
|
||||
initWithFormat:SHA256FormatString, digest[0], digest[1], digest[2],
|
||||
digest[3], digest[4], digest[5], digest[6], digest[7],
|
||||
digest[8], digest[9], digest[10], digest[11], digest[12],
|
||||
digest[13], digest[14], digest[15], digest[16],
|
||||
digest[17], digest[18], digest[19], digest[20],
|
||||
digest[21], digest[22], digest[23], digest[24],
|
||||
digest[25], digest[26], digest[27], digest[28],
|
||||
digest[29], digest[30], digest[31]];
|
||||
}
|
||||
} @finally {
|
||||
free(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,20 +39,14 @@ void logMessage(LogLevel level, FILE *destination, NSString *format, ...) {
|
||||
dispatch_once(&pred, ^{
|
||||
binaryName = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if ([binaryName isEqualToString:@"com.google.santa.daemon"]) {
|
||||
useSyslog = YES;
|
||||
pthread_key_create(&syslogKey, syslogClientDestructor);
|
||||
}
|
||||
}
|
||||
|
||||
// If debug logging is enabled, the process must be restarted.
|
||||
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--debug"]) {
|
||||
logLevel = LOG_LEVEL_DEBUG;
|
||||
}
|
||||
|
||||
// If requested, redirect output to syslog.
|
||||
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--syslog"]) {
|
||||
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--syslog"] ||
|
||||
[binaryName isEqualToString:@"com.google.santa.daemon"]) {
|
||||
useSyslog = YES;
|
||||
pthread_key_create(&syslogKey, syslogClientDestructor);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#import <MOLCodesignChecker/MOLCodesignChecker.h>
|
||||
#import <MOLXPCConnection/MOLXPCConnection.h>
|
||||
|
||||
#import "Source/common/SNTCommonEnums.h"
|
||||
#import "Source/common/SNTConfigurator.h"
|
||||
#import "Source/common/SNTRule.h"
|
||||
#import "Source/common/SNTStoredEvent.h"
|
||||
|
||||
@@ -25,7 +27,7 @@ NSString *const kBundleID = @"com.google.santa.daemon";
|
||||
@implementation SNTXPCControlInterface
|
||||
|
||||
+ (NSString *)serviceID {
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if ([[SNTConfigurator configurator] enableSystemExtension]) {
|
||||
MOLCodesignChecker *cs = [[MOLCodesignChecker alloc] initWithSelf];
|
||||
// "teamid.com.google.santa.daemon.xpc"
|
||||
NSString *t = cs.signingInformation[@"teamid"];
|
||||
|
||||
@@ -37,13 +37,7 @@
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
if (@available(macOS 10.15, *)) {
|
||||
LOGI(@"Requesting SystemExtension activation");
|
||||
NSString *e = [SNTXPCControlInterface systemExtensionID];
|
||||
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
|
||||
OSSystemExtensionRequest *req = [OSSystemExtensionRequest activationRequestForExtension:e
|
||||
queue:q];
|
||||
req.delegate = self;
|
||||
[[OSSystemExtensionManager sharedManager] submitRequest:req];
|
||||
[self loadSystemExtension];
|
||||
}
|
||||
|
||||
[self setupMenu];
|
||||
@@ -75,6 +69,20 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)loadSystemExtension API_AVAILABLE(macos(10.15)) {
|
||||
if (![[SNTConfigurator configurator] enableSystemExtension]) {
|
||||
LOGI(@"EnableSystemExtension is disabled");
|
||||
return;
|
||||
}
|
||||
LOGI(@"Requesting SystemExtension activation");
|
||||
NSString *e = [SNTXPCControlInterface systemExtensionID];
|
||||
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
|
||||
OSSystemExtensionRequest *req = [OSSystemExtensionRequest activationRequestForExtension:e
|
||||
queue:q];
|
||||
req.delegate = self;
|
||||
[[OSSystemExtensionManager sharedManager] submitRequest:req];
|
||||
}
|
||||
|
||||
#pragma mark Connection handling
|
||||
|
||||
- (void)createDaemonConnection {
|
||||
@@ -142,12 +150,7 @@
|
||||
withExtension:(OSSystemExtensionProperties *)new
|
||||
API_AVAILABLE(macos(10.15)) {
|
||||
LOGI(@"SystemExtension \"%@\" request for replacement", request.identifier);
|
||||
#ifdef DEBUG
|
||||
return OSSystemExtensionReplacementActionReplace;
|
||||
#else
|
||||
return [old.bundleVersion isEqualToString:new.bundleVersion]
|
||||
? OSSystemExtensionReplacementActionCancel : OSSystemExtensionReplacementActionReplace;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)requestNeedsUserApproval:(OSSystemExtensionRequest *)request API_AVAILABLE(macos(10.15)) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <SystemExtensions/SystemExtensions.h>
|
||||
|
||||
#import "Source/common/SNTConfigurator.h"
|
||||
#import "Source/common/SNTXPCControlInterface.h"
|
||||
#import "Source/santa/SNTAppDelegate.h"
|
||||
|
||||
@@ -66,6 +67,10 @@ int main(int argc, const char *argv[]) {
|
||||
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
|
||||
OSSystemExtensionRequest *req;
|
||||
if (sysxOperation.intValue == 1) {
|
||||
if (![[SNTConfigurator configurator] enableSystemExtension]) {
|
||||
NSLog(@"EnableSystemExtension is disabled");
|
||||
exit(1);
|
||||
}
|
||||
NSLog(@"Requesting SystemExtension activation");
|
||||
req = [OSSystemExtensionRequest activationRequestForExtension:e queue:q];
|
||||
} else if (sysxOperation.intValue == 2) {
|
||||
|
||||
@@ -84,10 +84,11 @@ REGISTER_COMMAND_NAME(@"status")
|
||||
|
||||
BOOL fileLogging = ([[SNTConfigurator configurator] fileChangesRegex] != nil);
|
||||
|
||||
SNTConfigurator *configurator = [SNTConfigurator configurator];
|
||||
|
||||
// Kext status
|
||||
__block uint64_t rootCacheCount = -1, nonRootCacheCount = -1;
|
||||
if (@available(macOS 10.15, *)) {
|
||||
} else {
|
||||
if (![configurator enableSystemExtension]) {
|
||||
dispatch_group_enter(group);
|
||||
[[self.daemonConn remoteObjectProxy] cacheCounts:^(uint64_t rootCache, uint64_t nonRootCache) {
|
||||
rootCacheCount = rootCache;
|
||||
@@ -205,8 +206,7 @@ REGISTER_COMMAND_NAME(@"status")
|
||||
@"transitive_whitelisting" : @(transitiveWhitelistingEnabled),
|
||||
},
|
||||
} mutableCopy];
|
||||
if (@available(macOS 10.15, *)) {
|
||||
} else {
|
||||
if (![configurator enableSystemExtension]) {
|
||||
stats[@"kernel"] = @{
|
||||
@"root_cache_count" : @(rootCacheCount),
|
||||
@"non_root_cache_count": @(nonRootCacheCount),
|
||||
@@ -224,8 +224,7 @@ REGISTER_COMMAND_NAME(@"status")
|
||||
printf(" %-25s | %s\n", "File Logging", (fileLogging ? "Yes" : "No"));
|
||||
printf(" %-25s | %lld (Peak: %.2f%%)\n", "Watchdog CPU Events", cpuEvents, cpuPeak);
|
||||
printf(" %-25s | %lld (Peak: %.2fMB)\n", "Watchdog RAM Events", ramEvents, ramPeak);
|
||||
if (@available(macOS 10.15, *)) {
|
||||
} else {
|
||||
if (![configurator enableSystemExtension]) {
|
||||
printf(">>> Kernel Info\n");
|
||||
printf(" %-25s | %lld\n", "Root cache count", rootCacheCount);
|
||||
printf(" %-25s | %lld\n", "Non-root cache count", nonRootCacheCount);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#import <MOLXPCConnection/MOLXPCConnection.h>
|
||||
|
||||
#import "Source/common/SNTCommonEnums.h"
|
||||
#import "Source/common/SNTConfigurator.h"
|
||||
#import "Source/common/SNTFileInfo.h"
|
||||
#import "Source/common/SNTKernelCommon.h"
|
||||
#import "Source/santactl/SNTCommand.h"
|
||||
@@ -70,7 +71,7 @@ REGISTER_COMMAND_NAME(@"version")
|
||||
}
|
||||
|
||||
- (NSString *)santaKextVersion {
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if ([[SNTConfigurator configurator] enableSystemExtension]) {
|
||||
return @"un-needed (SystemExtension being used)";
|
||||
}
|
||||
|
||||
|
||||
@@ -52,14 +52,16 @@
|
||||
if (event.idx) [eventIds addObject:event.idx];
|
||||
if (uploadEvents.count >= self.syncState.eventBatchSize) break;
|
||||
}
|
||||
|
||||
if (!self.syncState.cleanSync) {
|
||||
NSDictionary *r = [self performRequest:[self requestWithDictionary:@{ kEvents: uploadEvents }]];
|
||||
if (!r) return NO;
|
||||
|
||||
NSDictionary *r = [self performRequest:[self requestWithDictionary:@{ kEvents: uploadEvents }]];
|
||||
if (!r) return NO;
|
||||
// A list of bundle hashes that require their related binary events to be uploaded.
|
||||
self.syncState.bundleBinaryRequests = r[kEventUploadBundleBinaries];
|
||||
|
||||
// A list of bundle hashes that require their related binary events to be uploaded.
|
||||
self.syncState.bundleBinaryRequests = r[kEventUploadBundleBinaries];
|
||||
|
||||
LOGI(@"Uploaded %lu events", uploadEvents.count);
|
||||
LOGI(@"Uploaded %lu events", uploadEvents.count);
|
||||
}
|
||||
|
||||
// Remove event IDs. For Bundle Events the ID is 0 so nothing happens.
|
||||
[[self.daemonConn remoteObjectProxy] databaseRemoveEventsWithIDs:[eventIds allObjects]];
|
||||
|
||||
@@ -310,6 +310,8 @@ static void driverAppearedHandler(void *info, io_iterator_t iterator) {
|
||||
}
|
||||
|
||||
- (void)fileModificationPrefixFilterAdd:(NSArray *)filters {
|
||||
while (!self.connectionEstablished) usleep(100000); // 100ms
|
||||
|
||||
uint64_t n = 0;
|
||||
uint32_t n_len = 1;
|
||||
|
||||
@@ -334,6 +336,8 @@ static void driverAppearedHandler(void *info, io_iterator_t iterator) {
|
||||
LOGE(@"Prefix filter tree is full!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOGI(@"Added prefix filter: %s", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,9 +231,10 @@
|
||||
NSMutableArray *args = [NSMutableArray arrayWithCapacity:argCount];
|
||||
for (int i = 0; i < argCount; ++i) {
|
||||
es_string_token_t arg = es_exec_arg(&(m->event.exec), i);
|
||||
[args addObject:[[NSString alloc] initWithBytes:arg.data
|
||||
length:arg.length
|
||||
encoding:NSUTF8StringEncoding]];
|
||||
NSString *argStr = [[NSString alloc] initWithBytes:arg.data
|
||||
length:arg.length
|
||||
encoding:NSUTF8StringEncoding];
|
||||
if (argStr.length) [args addObject:argStr];
|
||||
}
|
||||
sm.args_array = (void *)CFBridgingRetain(args);
|
||||
callback = self.logCallback;
|
||||
|
||||
@@ -54,8 +54,11 @@
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
SNTConfigurator *configurator = [SNTConfigurator configurator];
|
||||
|
||||
// Choose an event logger.
|
||||
// Locate and connect to driver / SystemExtension
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if ([configurator enableSystemExtension]) {
|
||||
LOGI(@"Using EndpointSecurity as event provider.");
|
||||
_eventProvider = [[SNTEndpointSecurityManager alloc] init];
|
||||
} else {
|
||||
@@ -80,8 +83,7 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Choose an event logger.
|
||||
SNTConfigurator *configurator = [SNTConfigurator configurator];
|
||||
|
||||
switch ([configurator eventLogType]) {
|
||||
case SNTEventLogTypeSyslog:
|
||||
_eventLog = [[SNTSyslogEventLog alloc] init];
|
||||
@@ -91,12 +93,14 @@
|
||||
break;
|
||||
}
|
||||
|
||||
// The filter is reset when santad disconnects from the driver.
|
||||
// Add the default filters.
|
||||
[_eventProvider fileModificationPrefixFilterAdd:@[ @"/.", @"/dev/" ]];
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
|
||||
// The filter is reset when santad disconnects from the driver.
|
||||
// Add the default filters.
|
||||
[self.eventProvider fileModificationPrefixFilterAdd:@[ @"/.", @"/dev/" ]];
|
||||
|
||||
// TODO(bur): Add KVO handling for fileChangesPrefixFilters.
|
||||
[_eventProvider fileModificationPrefixFilterAdd:[configurator fileChangesPrefixFilters]];
|
||||
// TODO(bur): Add KVO handling for fileChangesPrefixFilters.
|
||||
[self.eventProvider fileModificationPrefixFilterAdd:[configurator fileChangesPrefixFilters]];
|
||||
});
|
||||
|
||||
self.notQueue = [[SNTNotificationQueue alloc] init];
|
||||
SNTSyncdQueue *syncdQueue = [[SNTSyncdQueue alloc] init];
|
||||
@@ -124,6 +128,12 @@
|
||||
forKeyPath:NSStringFromSelector(@selector(blacklistPathRegex))
|
||||
options:bits
|
||||
context:NULL];
|
||||
if (![configurator enableSystemExtension]) {
|
||||
[configurator addObserver:self
|
||||
forKeyPath:NSStringFromSelector(@selector(enableSystemExtension))
|
||||
options:bits
|
||||
context:NULL];
|
||||
}
|
||||
|
||||
// Establish XPC listener for Santa and santactl connections
|
||||
SNTDaemonControlController *dc =
|
||||
@@ -310,6 +320,19 @@ void diskDisappearedCallback(DADiskRef disk, void *context) {
|
||||
LOGI(@"Changed [white|black]list regex, flushing cache");
|
||||
[self.eventProvider flushCacheNonRootOnly:NO];
|
||||
}
|
||||
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(enableSystemExtension))]) {
|
||||
BOOL new = [change[newKey] isKindOfClass:[NSNumber class]] ? [change[newKey] boolValue] : NO;
|
||||
BOOL old = [change[oldKey] isKindOfClass:[NSNumber class]] ? [change[oldKey] boolValue] : NO;
|
||||
if (old == NO && new == YES) {
|
||||
LOGI(@"EnableSystemExtension changed NO -> YES");
|
||||
NSTask *t = [[NSTask alloc] init];
|
||||
t.launchPath = [@(kSantaAppPath) stringByAppendingString:@"/Contents/MacOS/Santa"];
|
||||
t.arguments = @[ @"--load-system-extension" ];
|
||||
[t launch];
|
||||
[t waitUntilExit];
|
||||
LOGI(@"The penultimate exit.");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,8 +153,7 @@ double watchdogRAMPeak = 0;
|
||||
certificateSHA256:(NSString *)certificateSHA256
|
||||
reply:(void (^)(SNTEventState))reply {
|
||||
reply([self.policyProcessor decisionForFilePath:filePath
|
||||
fileSHA256:fileSHA256
|
||||
certificateSHA256:certificateSHA256].decision);
|
||||
fileSHA256:fileSHA256].decision);
|
||||
}
|
||||
|
||||
#pragma mark Config Ops
|
||||
|
||||
@@ -115,50 +115,29 @@ static size_t kLargeBinarySize = 30 * 1024 * 1024;
|
||||
[self.eventProvider postAction:ACTION_RESPOND_ACK forMessage:message];
|
||||
}
|
||||
|
||||
// If the binary is a critical system binary, don't check its signature.
|
||||
// The binary was validated by santad at startup.
|
||||
SNTCachedDecision *cd = self.ruleTable.criticalSystemBinaries[binInfo.SHA256];
|
||||
MOLCodesignChecker *csInfo; // Needed further down in this scope.
|
||||
if (!cd) {
|
||||
// Get codesigning info about the file but only if it's a Mach-O.
|
||||
if (binInfo.isMachO) {
|
||||
NSError *csError;
|
||||
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 (and refresh rule access timestamp).
|
||||
cd = [self.policyProcessor decisionForFileInfo:binInfo
|
||||
fileSHA256:nil
|
||||
certificateSHA256:csInfo.leafCertificate.SHA256];
|
||||
cd.certCommonName = csInfo.leafCertificate.commonName;
|
||||
}
|
||||
|
||||
SNTCachedDecision *cd = [self.policyProcessor decisionForFileInfo:binInfo];
|
||||
cd.vnodeId = message.vnode_id;
|
||||
|
||||
// Formulate an initial action from the decision.
|
||||
santa_action_t action =
|
||||
(SNTEventStateAllow & cd.decision) ? ACTION_RESPOND_ALLOW : ACTION_RESPOND_DENY;
|
||||
|
||||
// Upgrade the action to ACTION_RESPOND_ALLOW_COMPILER when appropriate, because we want the
|
||||
// kernel to track this information in its decision cache.
|
||||
if (cd.decision == SNTEventStateAllowCompiler) {
|
||||
action = ACTION_RESPOND_ALLOW_COMPILER;
|
||||
}
|
||||
|
||||
// Save decision details for logging the execution later. For transitive rules, we also use
|
||||
// the shasum stored in the decision details to update the rule's timestamp whenever an
|
||||
// ACTION_NOTIFY_EXEC message related to the transitive rule is received.
|
||||
NSString *ttyPath;
|
||||
if (action == ACTION_RESPOND_ALLOW || action == ACTION_RESPOND_ALLOW_COMPILER) {
|
||||
if (action == ACTION_RESPOND_ALLOW) {
|
||||
[_eventLog cacheDecision:cd];
|
||||
} else {
|
||||
ttyPath = [self ttyPathForPID:message.ppid];
|
||||
}
|
||||
|
||||
// Upgrade the action to ACTION_RESPOND_ALLOW_COMPILER when appropriate, because we want the
|
||||
// kernel to track this information in its decision cache.
|
||||
if (cd.decision == SNTEventStateAllowCompiler) {
|
||||
action = ACTION_RESPOND_ALLOW_COMPILER;
|
||||
}
|
||||
|
||||
// Send the decision to the kernel.
|
||||
[self.eventProvider postAction:action forMessage:message];
|
||||
|
||||
@@ -174,7 +153,7 @@ static size_t kLargeBinarySize = 30 * 1024 * 1024;
|
||||
se.filePath = binInfo.path;
|
||||
se.decision = cd.decision;
|
||||
|
||||
se.signingChain = csInfo.certificates;
|
||||
se.signingChain = cd.certChain;
|
||||
se.pid = @(message.pid);
|
||||
se.ppid = @(message.ppid);
|
||||
se.parentName = @(message.pname);
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
OCMStub([self.mockCodesignChecker alloc]).andReturn(self.mockCodesignChecker);
|
||||
|
||||
OCMStub([self.mockCodesignChecker initWithBinaryPath:OCMOCK_ANY
|
||||
fileDescriptor:0
|
||||
error:[OCMArg setTo:NULL]])
|
||||
.andReturn(self.mockCodesignChecker);
|
||||
|
||||
@@ -61,6 +60,8 @@
|
||||
OCMStub([self.mockFileInfo alloc]).andReturn(self.mockFileInfo);
|
||||
OCMStub([self.mockFileInfo initWithPath:OCMOCK_ANY
|
||||
error:[OCMArg setTo:nil]]).andReturn(self.mockFileInfo);
|
||||
OCMStub([self.mockFileInfo codesignCheckerWithError:[OCMArg setTo:nil]])
|
||||
.andReturn(self.mockCodesignChecker);
|
||||
|
||||
self.mockRuleDatabase = OCMClassMock([SNTRuleTable class]);
|
||||
self.mockEventDatabase = OCMClassMock([SNTEventTable class]);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#import "Source/common/SNTCommonEnums.h"
|
||||
#import "Source/common/SNTKernelCommon.h"
|
||||
|
||||
@class MOLCodesignChecker;
|
||||
@class SNTCachedDecision;
|
||||
@class SNTFileInfo;
|
||||
@class SNTRuleTable;
|
||||
@@ -38,15 +39,12 @@
|
||||
/// @param fileInfo A SNTFileInfo object.
|
||||
/// @param fileSHA256 The pre-calculated SHA256 hash for the file, can be nil. If nil the hash will
|
||||
/// be calculated by this method from the filePath.
|
||||
/// @param certificateSHA256 A SHA256 hash of the signing certificate, can be nil.
|
||||
/// @note If fileSHA256 and certificateSHA256 are both passed in, the most specific rule will be
|
||||
/// returned. Binary rules take precedence over cert rules.
|
||||
/// @note This method can also be used to generate a SNTCachedDecision object without any
|
||||
/// artifacts on disk. Simply pass nil to fileInfo and pass in the desired SHA256s.
|
||||
///
|
||||
- (nonnull SNTCachedDecision *)decisionForFileInfo:(nullable SNTFileInfo *)fileInfo
|
||||
fileSHA256:(nullable NSString *)fileSHA256
|
||||
certificateSHA256:(nullable NSString *)certificateSHA256;
|
||||
- (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileInfo
|
||||
fileSHA256:(nullable NSString *)fileSHA256;
|
||||
|
||||
/// Convenience initializer with a nil hash.
|
||||
- (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileInfo;
|
||||
|
||||
///
|
||||
/// A wrapper for decisionForFileInfo:fileSHA256:certificateSHA256:. This method is slower as it
|
||||
@@ -54,8 +52,7 @@
|
||||
/// SNTFileInfo is not SecureCoding compliant. If the SHA256 hash of the file has already been
|
||||
/// calculated, use the fileSHA256 parameter to save a second calculation of the hash.
|
||||
///
|
||||
- (nonnull SNTCachedDecision *)decisionForFilePath:(nullable NSString *)filePath
|
||||
fileSHA256:(nullable NSString *)fileSHA256
|
||||
certificateSHA256:(nullable NSString *)certificateSHA256;
|
||||
- (nonnull SNTCachedDecision *)decisionForFilePath:(nonnull NSString *)filePath
|
||||
fileSHA256:(nullable NSString *)fileSHA256;
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#import "Source/santad/SNTPolicyProcessor.h"
|
||||
|
||||
#import <MOLCodesignChecker/MOLCodesignChecker.h>
|
||||
|
||||
#include "Source/common/SNTLogging.h"
|
||||
|
||||
#import "Source/common/SNTCachedDecision.h"
|
||||
@@ -36,13 +38,29 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (SNTCachedDecision *)decisionForFileInfo:(SNTFileInfo *)fileInfo
|
||||
fileSHA256:(NSString *)fileSHA256
|
||||
certificateSHA256:(NSString *)certificateSHA256 {
|
||||
|
||||
- (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileInfo
|
||||
fileSHA256:(nullable NSString *)fileSHA256 {
|
||||
SNTCachedDecision *cd = [[SNTCachedDecision alloc] init];
|
||||
cd.sha256 = fileSHA256 ?: fileInfo.SHA256;
|
||||
cd.certSHA256 = certificateSHA256;
|
||||
|
||||
// If the binary is a critical system binary, don't check its signature.
|
||||
// The binary was validated at startup when the rule table was initialized.
|
||||
SNTCachedDecision *systemCd = self.ruleTable.criticalSystemBinaries[cd.sha256];
|
||||
if (systemCd) return systemCd;
|
||||
|
||||
// Grab the code signature, if there's an error don't try to capture
|
||||
// any of the signature details.
|
||||
NSError *csInfoError;
|
||||
MOLCodesignChecker *csInfo = [fileInfo codesignCheckerWithError:&csInfoError];
|
||||
if (csInfoError) {
|
||||
csInfo = nil;
|
||||
cd.decisionExtra =
|
||||
[NSString stringWithFormat:@"Signature ignored due to error: %ld", (long)csInfoError.code];
|
||||
}
|
||||
|
||||
cd.certSHA256 = csInfo.leafCertificate.SHA256;
|
||||
cd.certCommonName = csInfo.leafCertificate.commonName;
|
||||
cd.certChain = csInfo.certificates;
|
||||
cd.quarantineURL = fileInfo.quarantineDataURL;
|
||||
|
||||
SNTRule *rule = [self.ruleTable ruleForBinarySHA256:cd.sha256
|
||||
@@ -67,7 +85,7 @@
|
||||
if ([[SNTConfigurator configurator] enableTransitiveWhitelisting]) {
|
||||
cd.decision = SNTEventStateAllowCompiler;
|
||||
} else {
|
||||
cd.decision = SNTEventStateAllow;
|
||||
cd.decision = SNTEventStateAllowBinary;
|
||||
}
|
||||
return cd;
|
||||
case SNTRuleStateWhitelistTransitive:
|
||||
@@ -90,6 +108,7 @@
|
||||
return cd;
|
||||
case SNTRuleStateSilentBlacklist:
|
||||
cd.silentBlock = YES;
|
||||
// intentional fallthrough
|
||||
case SNTRuleStateBlacklist:
|
||||
cd.customMsg = rule.customMsg;
|
||||
cd.decision = SNTEventStateBlockCertificate;
|
||||
@@ -102,6 +121,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
if ([[SNTConfigurator configurator] enableBadSignatureProtection] &&
|
||||
csInfoError && csInfoError.code != errSecCSUnsigned) {
|
||||
cd.decisionExtra =
|
||||
[NSString stringWithFormat:@"Blocked due to signature error: %ld", (long)csInfoError.code];
|
||||
cd.decision = SNTEventStateBlockCertificate;
|
||||
return cd;
|
||||
}
|
||||
|
||||
NSString *msg = [self fileIsScopeBlacklisted:fileInfo];
|
||||
if (msg) {
|
||||
cd.decisionExtra = msg;
|
||||
@@ -129,18 +156,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (SNTCachedDecision *)decisionForFilePath:(NSString *)filePath
|
||||
fileSHA256:(NSString *)fileSHA256
|
||||
certificateSHA256:(NSString *)certificateSHA256 {
|
||||
- (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileInfo {
|
||||
return [self decisionForFileInfo:fileInfo fileSHA256:nil];
|
||||
}
|
||||
|
||||
- (nonnull SNTCachedDecision *)decisionForFilePath:(nonnull NSString *)filePath
|
||||
fileSHA256:(nullable NSString *)fileSHA256 {
|
||||
SNTFileInfo *fileInfo;
|
||||
if (filePath) {
|
||||
NSError *error;
|
||||
fileInfo = [[SNTFileInfo alloc] initWithPath:filePath error:&error];
|
||||
if (!fileInfo) LOGW(@"Failed to read file %@: %@", filePath, error.localizedDescription);
|
||||
}
|
||||
return [self decisionForFileInfo:fileInfo
|
||||
fileSHA256:fileSHA256
|
||||
certificateSHA256:certificateSHA256];
|
||||
NSError *error;
|
||||
fileInfo = [[SNTFileInfo alloc] initWithPath:filePath error:&error];
|
||||
if (!fileInfo) LOGW(@"Failed to read file %@: %@", filePath, error.localizedDescription);
|
||||
return [self decisionForFileInfo:fileInfo fileSHA256:fileSHA256];
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "Source/common/SNTCommonEnums.h"
|
||||
#import "Source/common/SNTConfigurator.h"
|
||||
#import "Source/common/SNTLogging.h"
|
||||
#import "Source/santad/EventProviders/SNTDriverManager.h"
|
||||
#import "Source/santad/SNTApplication.h"
|
||||
@@ -119,7 +120,7 @@ int main(int argc, const char *argv[]) {
|
||||
LOGI(@"Started, version %@", infoDict[@"CFBundleVersion"]);
|
||||
|
||||
// Handle the case of macOS < 10.15 updating to >= 10.15.
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if ([[SNTConfigurator configurator] enableSystemExtension]) {
|
||||
if ([pi.arguments.firstObject isEqualToString:@(kSantaDPath)]) cleanup();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl",
|
||||
git_repository(
|
||||
name = "build_bazel_rules_apple",
|
||||
remote = "https://github.com/bazelbuild/rules_apple.git",
|
||||
commit = "97951dce38d",
|
||||
tag = "0.19.0",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_apple//apple:repositories.bzl", "apple_rules_dependencies")
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""The version for all Santa components."""
|
||||
|
||||
SANTA_VERSION = "1.0.2"
|
||||
SANTA_VERSION = "1.7"
|
||||
|
||||
Reference in New Issue
Block a user