mirror of
https://github.com/google/santa.git
synced 2026-01-16 01:38:14 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99ee0af178 | ||
|
|
bf6f78df09 | ||
|
|
c05806916b | ||
|
|
e48ce0cfe3 | ||
|
|
eabca469b9 | ||
|
|
f6dc36e812 | ||
|
|
ac7cbdfd16 |
@@ -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.
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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";
|
||||
@@ -112,6 +113,7 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
|
||||
kWhitelistRegexKey : re,
|
||||
kBlacklistRegexKey : re,
|
||||
kEnablePageZeroProtectionKey : number,
|
||||
kEnableBadSignatureProtectionKey: number,
|
||||
kMoreInfoURLKey : string,
|
||||
kEventDetailURLKey : string,
|
||||
kEventDetailTextKey : string,
|
||||
@@ -381,6 +383,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]];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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]];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -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.1"
|
||||
|
||||
Reference in New Issue
Block a user