Skip to content

Commit

Permalink
Add transitive whitelisting to Santa (google#224)
Browse files Browse the repository at this point in the history
Add transitive whitelisting.

Binaries may be identified with WHITELIST_COMPILER rules.  Any executable they output will then be marked locally with a transitive whitelist rule and allowed to run if the TransitiveWhitelistingEnabled config key is true.
  • Loading branch information
nguyen-phillip authored and dskfh committed Jul 17, 2020
1 parent 11adb17 commit 6b3d21c
Show file tree
Hide file tree
Showing 37 changed files with 1,153 additions and 69 deletions.
8 changes: 8 additions & 0 deletions Santa.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@
59D56CF2D9C5BD9B7E3CC56D /* libPods-santad-santabs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14B98F4051188ECB7D024331 /* libPods-santad-santabs.a */; };
81133DB01F3A76F700917FF9 /* SNTCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 81133DAF1F3A75CE00917FF9 /* SNTCommand.m */; };
81133DB11F3A77C600917FF9 /* SNTCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 81133DAF1F3A75CE00917FF9 /* SNTCommand.m */; };
81A00E7F1FD74F8E00A84676 /* SNTCompilerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */; };
81A00E801FD74F9100A84676 /* SNTCompilerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */; };
B352A545B76783D568A6D0C5 /* libPods-Santa.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90E9D568200AB9B642E06272 /* libPods-Santa.a */; };
C714F8B11D8044D400700EDF /* SNTCommandFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */; };
C714F8B21D8044FE00700EDF /* SNTCommandController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDAB18FD7CFD00921A21 /* SNTCommandController.m */; };
Expand Down Expand Up @@ -425,6 +427,8 @@
7D949AA996AEAC326A4F6596 /* libPods-LogicTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LogicTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
81133DAE1F3A75CE00917FF9 /* SNTCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommand.h; sourceTree = "<group>"; };
81133DAF1F3A75CE00917FF9 /* SNTCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommand.m; sourceTree = "<group>"; };
81A00E7D1FD74EFF00A84676 /* SNTCompilerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCompilerController.h; sourceTree = "<group>"; };
81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCompilerController.m; sourceTree = "<group>"; };
8EF10E4B8C86CED022C72F1B /* Pods-santactl.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santactl.debug.xcconfig"; path = "Pods/Target Support Files/Pods-santactl/Pods-santactl.debug.xcconfig"; sourceTree = "<group>"; };
90E9D568200AB9B642E06272 /* libPods-Santa.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Santa.a"; sourceTree = BUILT_PRODUCTS_DIR; };
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 = "<group>"; };
Expand Down Expand Up @@ -768,6 +772,8 @@
0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */,
0DE71A731B95F7F900518526 /* SNTCachedDecision.h */,
0DE71A741B95F7F900518526 /* SNTCachedDecision.m */,
81A00E7D1FD74EFF00A84676 /* SNTCompilerController.h */,
81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */,
0D8E18CB19107B56000F89B8 /* SNTDaemonControlController.h */,
0D8E18CC19107B56000F89B8 /* SNTDaemonControlController.m */,
0D63DD5A1906FCB400D346C4 /* SNTDatabaseController.h */,
Expand Down Expand Up @@ -1380,6 +1386,7 @@
0D41DAD41A7C28C800A890FE /* SNTEventTableTest.m in Sources */,
0D3AFBEE18FB4C6C0087BCEE /* SNTApplication.m in Sources */,
0DD0D48F194F78F8005F27EB /* SNTFileInfoTest.m in Sources */,
81A00E801FD74F9100A84676 /* SNTCompilerController.m in Sources */,
0DC5D86E191AED220078A5C0 /* SNTRuleTable.m in Sources */,
0DD0D492194F9BEF005F27EB /* SNTLogging.m in Sources */,
0DE71A761B95F7F900518526 /* SNTCachedDecision.m in Sources */,
Expand Down Expand Up @@ -1490,6 +1497,7 @@
0D377C2A17A071B7008453DB /* SNTEventTable.m in Sources */,
0DE50F681912716A007B2B0C /* SNTRule.m in Sources */,
0DB77FD81CCE824A004DF060 /* SNTBlockMessage.m in Sources */,
81A00E7F1FD74F8E00A84676 /* SNTCompilerController.m in Sources */,
0D37C10F18F6029A0069BC61 /* SNTDatabaseTable.m in Sources */,
C748E8A720696595006CFD1B /* SNTFileEventLog.m in Sources */,
C748E8A3206964E1006CFD1B /* SNTEventLog.m in Sources */,
Expand Down
6 changes: 6 additions & 0 deletions Source/common/SNTCommonEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ typedef NS_ENUM(NSInteger, SNTRuleState) {
SNTRuleStateBlacklist = 2,
SNTRuleStateSilentBlacklist = 3,
SNTRuleStateRemove = 4,

SNTRuleStateWhitelistCompiler = 5,
SNTRuleStateWhitelistTransitive = 6,
};

typedef NS_ENUM(NSInteger, SNTClientMode) {
Expand All @@ -58,6 +61,9 @@ typedef NS_ENUM(NSInteger, SNTEventState) {
SNTEventStateAllowBinary = 1 << 25,
SNTEventStateAllowCertificate = 1 << 26,
SNTEventStateAllowScope = 1 << 27,
SNTEventStateAllowCompiler = 1 << 28,
SNTEventStateAllowTransitive = 1 << 29,
SNTEventStateAllowPendingTransitive = 1 << 30,

// Block and Allow masks
SNTEventStateBlock = 0xFF << 16,
Expand Down
9 changes: 9 additions & 0 deletions Source/common/SNTConfigurator.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@
///
@property BOOL bundlesEnabled;

#pragma mark Transitive Whitelisting Settings

///
/// If YES, binaries marked with SNTRuleStateWhitelistCompiler rules are allowed to transitively
/// whitelist any executables that they produce. If NO, SNTRuleStateWhitelistCompiler rules are
/// interpreted as if they were simply SNTRuleStateWhitelist rules. Defaults to NO.
///
@property BOOL transitiveWhitelistingEnabled;

#pragma mark Server Auth Settings

///
Expand Down
15 changes: 15 additions & 0 deletions Source/common/SNTConfigurator.m
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ @implementation SNTConfigurator

// The keys managed by a sync server or mobileconfig.
static NSString *const kClientModeKey = @"ClientMode";
static NSString *const kTransitiveWhitelistingEnabledKey = @"TransitiveWhitelistingEnabled";
static NSString *const kWhitelistRegexKey = @"WhitelistRegex";
static NSString *const kBlacklistRegexKey = @"BlacklistRegex";

Expand All @@ -94,6 +95,7 @@ - (instancetype)init {
Class data = [NSData class];
_syncServerKeyTypes = @{
kClientModeKey : number,
kTransitiveWhitelistingEnabledKey : number,
kWhitelistRegexKey : re,
kBlacklistRegexKey : re,
kFullSyncLastSuccess : date,
Expand All @@ -102,6 +104,7 @@ - (instancetype)init {
};
_forcedConfigKeyTypes = @{
kClientModeKey : number,
kTransitiveWhitelistingEnabledKey : number,
kFileChangesRegexKey : re,
kWhitelistRegexKey : re,
kBlacklistRegexKey : re,
Expand Down Expand Up @@ -287,6 +290,10 @@ + (NSSet *)keyPathsForValuesAffectingEnableMachineIDDecoration {
return [self configStateSet];
}

+ (NSSet *)keyPathsForValuesAffectingTransitiveWhitelistingEnabled {
return [self configStateSet];
}

#pragma mark Public Interface

- (SNTClientMode)clientMode {
Expand All @@ -311,6 +318,14 @@ - (void)setSyncServerClientMode:(SNTClientMode)newMode {
}
}

- (BOOL)transitiveWhitelistingEnabled {
return [self.configState[kTransitiveWhitelistingEnabledKey] boolValue];
}

- (void)setTransitiveWhitelistingEnabled:(BOOL)enabled {
[self updateSyncStateForKey:kTransitiveWhitelistingEnabledKey value:@(enabled)];
}

- (NSRegularExpression *)whitelistPathRegex {
return self.syncState[kWhitelistRegexKey] ?: self.configState[kWhitelistRegexKey];
}
Expand Down
14 changes: 12 additions & 2 deletions Source/common/SNTKernelCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@
enum SantaDriverMethods {
kSantaUserClientOpen,
kSantaUserClientAllowBinary,
kSantaUserClientAllowCompiler,
kSantaUserClientDenyBinary,
kSantaUserClientAcknowledgeBinary,
kSantaUserClientClearCache,
kSantaUserClientRemoveCacheEntry,
kSantaUserClientCacheCount,
kSantaUserClientCheckCache,
kSantaUserClientCacheBucketCount,
Expand All @@ -47,7 +49,7 @@ enum SantaDriverMethods {

typedef enum {
QUEUETYPE_DECISION,
QUEUETYPE_LOG
QUEUETYPE_LOG,
} santa_queuetype_t;

// Enum defining actions that can be passed down the IODataQueue and in
Expand All @@ -64,6 +66,10 @@ typedef enum {
ACTION_RESPOND_DENY = 21,
ACTION_RESPOND_TOOLONG = 22,
ACTION_RESPOND_ACK = 23,
ACTION_RESPOND_ALLOW_COMPILER = 24,
// The following response is stored only in the kernel decision cache.
// It is removed by SNTCompilerController
ACTION_RESPOND_ALLOW_PENDING_TRANSITIVE = 25,

// NOTIFY
ACTION_NOTIFY_EXEC = 30,
Expand All @@ -72,13 +78,17 @@ typedef enum {
ACTION_NOTIFY_LINK = 33,
ACTION_NOTIFY_EXCHANGE = 34,
ACTION_NOTIFY_DELETE = 35,
ACTION_NOTIFY_WHITELIST = 36,

// ERROR
ACTION_ERROR = 99,
} santa_action_t;

#define RESPONSE_VALID(x) \
(x == ACTION_RESPOND_ALLOW || x == ACTION_RESPOND_DENY)
(x == ACTION_RESPOND_ALLOW || \
x == ACTION_RESPOND_DENY || \
x == ACTION_RESPOND_ALLOW_COMPILER || \
x == ACTION_RESPOND_ALLOW_PENDING_TRANSITIVE)

// Struct to manage vnode IDs
typedef struct santa_vnode_id_t {
Expand Down
20 changes: 20 additions & 0 deletions Source/common/SNTRule.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,32 @@
///
@property(copy) NSString *customMsg;

///
/// The time when this rule was last retrieved from the rules database, if rule is transitive.
/// Stored as number of seconds since 00:00:00 UTC on 1 January 2001.
///
@property(readonly) NSUInteger timestamp;

///
/// Designated initializer.
///
- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg
timestamp:(NSUInteger)timestamp;

///
/// Initialize with a default timestamp: current time if rule state is transitive, 0 otherwise.
///
- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg;

///
/// Sets timestamp of rule to the current time.
///
- (void)resetTimestamp;

@end
37 changes: 34 additions & 3 deletions Source/common/SNTRule.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,45 @@

#import "SNTRule.h"

@interface SNTRule()
@property(readwrite) NSUInteger timestamp;
@end

@implementation SNTRule

- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg {
customMsg:(NSString *)customMsg
timestamp:(NSUInteger)timestamp {
self = [super init];
if (self) {
_shasum = shasum;
_state = state;
_type = type;
_customMsg = customMsg;
_timestamp = timestamp;
}
return self;
}

- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg {
self = [self initWithShasum:shasum
state:state
type:type
customMsg:customMsg
timestamp:0];
// Initialize timestamp to current time if rule is transitive.
if (self && state == SNTRuleStateWhitelistTransitive) {
[self resetTimestamp];
}
return self;
}


#pragma mark NSSecureCoding

#pragma clang diagnostic push
Expand All @@ -46,6 +69,7 @@ - (void)encodeWithCoder:(NSCoder *)coder {
ENCODE(@(self.state), @"state");
ENCODE(@(self.type), @"type");
ENCODE(self.customMsg, @"custommsg");
ENCODE(@(self.timestamp), @"timestamp");
}

- (instancetype)initWithCoder:(NSCoder *)decoder {
Expand All @@ -55,6 +79,7 @@ - (instancetype)initWithCoder:(NSCoder *)decoder {
_state = [DECODE(NSNumber, @"state") intValue];
_type = [DECODE(NSNumber, @"type") intValue];
_customMsg = DECODE(NSString, @"custommsg");
_timestamp = [DECODE(NSNumber, @"timestamp") unsignedIntegerValue];
}
return self;
}
Expand All @@ -80,8 +105,14 @@ - (NSUInteger)hash {
}

- (NSString *)description {
return [NSString stringWithFormat:@"SNTRule: SHA-256: %@, State: %ld, Type: %ld",
self.shasum, self.state, self.type];
return [NSString stringWithFormat:@"SNTRule: SHA-256: %@, State: %ld, Type: %ld, Timestamp: %lu",
self.shasum, self.state, self.type, (unsigned long)self.timestamp];
}

# pragma mark Last-access Timestamp

- (void)resetTimestamp {
self.timestamp = (NSUInteger)[[NSDate date] timeIntervalSinceReferenceDate];
}

@end
1 change: 1 addition & 0 deletions Source/common/SNTXPCControlInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
- (void)setWhitelistPathRegex:(NSString *)pattern reply:(void (^)(void))reply;
- (void)setBlacklistPathRegex:(NSString *)pattern reply:(void (^)(void))reply;
- (void)setBundlesEnabled:(BOOL)bundlesEnabled reply:(void (^)(void))reply;
- (void)setTransitiveWhitelistingEnabled:(BOOL)enabled reply:(void (^)(void))reply;

///
/// Syncd Ops
Expand Down
6 changes: 5 additions & 1 deletion Source/common/SNTXPCUnprivilegedControlInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@
///
/// Database ops
///
- (void)databaseRuleCounts:(void (^)(int64_t binary, int64_t certificate))reply;
- (void)databaseRuleCounts:(void (^)(int64_t binary,
int64_t certificate,
int64_t compiler,
int64_t transitive))reply;
- (void)databaseEventCount:(void (^)(int64_t count))reply;

///
Expand Down Expand Up @@ -71,6 +74,7 @@
- (void)ruleSyncLastSuccess:(void (^)(NSDate *))reply;
- (void)syncCleanRequired:(void (^)(BOOL))reply;
- (void)bundlesEnabled:(void (^)(BOOL))reply;
- (void)transitiveWhitelistingEnabled:(void (^)(BOOL))reply;

///
/// GUI Ops
Expand Down
Loading

0 comments on commit 6b3d21c

Please sign in to comment.