Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CDHash rule types #1301

Merged
merged 4 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Source/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ objc_library(
deps = [
":SNTCommonEnums",
":SNTRule",
":SNTRuleIdentifiers",
":SNTStoredEvent",
":SNTXPCBundleServiceInterface",
":SantaVnode",
Expand Down
1 change: 1 addition & 0 deletions Source/common/SNTCachedDecision.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
@property NSArray<MOLCertificate *> *certChain;
@property NSString *teamID;
@property NSString *signingID;
@property NSString *cdhash;
@property NSDictionary *entitlements;
@property BOOL entitlementsFiltered;

Expand Down
3 changes: 3 additions & 0 deletions Source/common/SNTCommonEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ typedef NS_ENUM(NSInteger, SNTAction) {
typedef NS_ENUM(NSInteger, SNTRuleType) {
SNTRuleTypeUnknown = 0,

SNTRuleTypeCDHash = 500,
SNTRuleTypeBinary = 1000,
SNTRuleTypeSigningID = 2000,
SNTRuleTypeCertificate = 3000,
Expand Down Expand Up @@ -84,6 +85,7 @@ typedef NS_ENUM(uint64_t, SNTEventState) {
SNTEventStateBlockTeamID = 1ULL << 20,
SNTEventStateBlockLongPath = 1ULL << 21,
SNTEventStateBlockSigningID = 1ULL << 22,
SNTEventStateBlockCDHash = 1ULL << 23,

// Bits 40-63 store allow decision types
SNTEventStateAllowUnknown = 1ULL << 40,
Expand All @@ -95,6 +97,7 @@ typedef NS_ENUM(uint64_t, SNTEventState) {
SNTEventStateAllowPendingTransitive = 1ULL << 46,
SNTEventStateAllowTeamID = 1ULL << 47,
SNTEventStateAllowSigningID = 1ULL << 48,
SNTEventStateAllowCDHash = 1ULL << 49,

// Block and Allow masks
SNTEventStateBlock = 0xFFFFFFULL << 16,
Expand Down
11 changes: 11 additions & 0 deletions Source/common/SNTRule.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#import "Source/common/SNTRule.h"

#include <CommonCrypto/CommonCrypto.h>
#include <Kernel/kern/cs_blobs.h>
#include <os/base.h>

#import "Source/common/SNTSyncConstants.h"
Expand Down Expand Up @@ -103,6 +104,14 @@ - (instancetype)initWithIdentifier:(NSString *)identifier
break;
}

case SNTRuleTypeCDHash: {
identifier = [[identifier lowercaseString] stringByTrimmingCharactersInSet:nonHex];
if (identifier.length != CS_CDHASH_LEN * 2) {
return nil;
}
break;
}

default: {
break;
}
Expand Down Expand Up @@ -173,6 +182,8 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict {
type = SNTRuleTypeTeamID;
} else if ([ruleTypeString isEqual:kRuleTypeSigningID]) {
type = SNTRuleTypeSigningID;
} else if ([ruleTypeString isEqual:kRuleTypeCDHash]) {
type = SNTRuleTypeCDHash;
} else {
return nil;
}
Expand Down
2 changes: 2 additions & 0 deletions Source/common/SNTRuleIdentifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
#import <Foundation/Foundation.h>

struct RuleIdentifiers {
NSString *cdhash;
NSString *binarySHA256;
NSString *signingID;
NSString *certificateSHA256;
NSString *teamID;
};

@interface SNTRuleIdentifiers : NSObject
@property(readonly) NSString *cdhash;
@property(readonly) NSString *binarySHA256;
@property(readonly) NSString *signingID;
@property(readonly) NSString *certificateSHA256;
Expand Down
4 changes: 3 additions & 1 deletion Source/common/SNTRuleIdentifiers.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ @implementation SNTRuleIdentifiers
- (instancetype)initWithRuleIdentifiers:(struct RuleIdentifiers)identifiers {
self = [super init];
if (self) {
_cdhash = identifiers.cdhash;
_binarySHA256 = identifiers.binarySHA256;
_signingID = identifiers.signingID;
_certificateSHA256 = identifiers.certificateSHA256;
Expand All @@ -28,7 +29,8 @@ - (instancetype)initWithRuleIdentifiers:(struct RuleIdentifiers)identifiers {
}

- (struct RuleIdentifiers)toStruct {
return (struct RuleIdentifiers){.binarySHA256 = self.binarySHA256,
return (struct RuleIdentifiers){.cdhash = self.cdhash,
.binarySHA256 = self.binarySHA256,
.signingID = self.signingID,
.certificateSHA256 = self.certificateSHA256,
.teamID = self.teamID};
Expand Down
5 changes: 5 additions & 0 deletions Source/common/SNTStoredEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@
///
@property NSString *signingID;

///
/// If the executed file was signed, this is the CDHash of the binary.
///
@property NSString *cdhash;

///
/// The user who executed the binary.
///
Expand Down
2 changes: 2 additions & 0 deletions Source/common/SNTStoredEvent.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ - (void)encodeWithCoder:(NSCoder *)coder {
ENCODE(self.signingChain, @"signingChain");
ENCODE(self.teamID, @"teamID");
ENCODE(self.signingID, @"signingID");
ENCODE(self.cdhash, @"cdhash");

ENCODE(self.executingUser, @"executingUser");
ENCODE(self.occurrenceDate, @"occurrenceDate");
Expand Down Expand Up @@ -97,6 +98,7 @@ - (instancetype)initWithCoder:(NSCoder *)decoder {
_signingChain = DECODEARRAY(MOLCertificate, @"signingChain");
_teamID = DECODE(NSString, @"teamID");
_signingID = DECODE(NSString, @"signingID");
_cdhash = DECODE(NSString, @"cdhash");

_executingUser = DECODE(NSString, @"executingUser");
_occurrenceDate = DECODE(NSDate, @"occurrenceDate");
Expand Down
5 changes: 5 additions & 0 deletions Source/common/SNTSyncConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern NSString *const kCompilerRuleCount;
extern NSString *const kTransitiveRuleCount;
extern NSString *const kTeamIDRuleCount;
extern NSString *const kSigningIDRuleCount;
extern NSString *const kCDHashRuleCount;
extern NSString *const kFullSyncInterval;
extern NSString *const kFCMToken;
extern NSString *const kFCMFullSyncInterval;
Expand All @@ -70,12 +71,14 @@ extern NSString *const kDecisionAllowCertificate;
extern NSString *const kDecisionAllowScope;
extern NSString *const kDecisionAllowTeamID;
extern NSString *const kDecisionAllowSigningID;
extern NSString *const kDecisionAllowCDHash;
extern NSString *const kDecisionBlockUnknown;
extern NSString *const kDecisionBlockBinary;
extern NSString *const kDecisionBlockCertificate;
extern NSString *const kDecisionBlockScope;
extern NSString *const kDecisionBlockTeamID;
extern NSString *const kDecisionBlockSigningID;
extern NSString *const kDecisionBlockCDHash;
extern NSString *const kDecisionUnknown;
extern NSString *const kDecisionBundleBinary;
extern NSString *const kLoggedInUsers;
Expand All @@ -101,6 +104,7 @@ extern NSString *const kCertValidFrom;
extern NSString *const kCertValidUntil;
extern NSString *const kTeamID;
extern NSString *const kSigningID;
extern NSString *const kCDHash;
extern NSString *const kQuarantineDataURL;
extern NSString *const kQuarantineRefererURL;
extern NSString *const kQuarantineTimestamp;
Expand All @@ -125,6 +129,7 @@ extern NSString *const kRuleTypeBinary;
extern NSString *const kRuleTypeCertificate;
extern NSString *const kRuleTypeTeamID;
extern NSString *const kRuleTypeSigningID;
extern NSString *const kRuleTypeCDHash;
extern NSString *const kRuleCustomMsg;
extern NSString *const kRuleCustomURL;
extern NSString *const kCursor;
Expand Down
5 changes: 5 additions & 0 deletions Source/common/SNTSyncConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
NSString *const kTransitiveRuleCount = @"transitive_rule_count";
NSString *const kTeamIDRuleCount = @"teamid_rule_count";
NSString *const kSigningIDRuleCount = @"signingid_rule_count";
NSString *const kCDHashRuleCount = @"cdhash_rule_count";
NSString *const kFullSyncInterval = @"full_sync_interval";
NSString *const kFCMToken = @"fcm_token";
NSString *const kFCMFullSyncInterval = @"fcm_full_sync_interval";
Expand Down Expand Up @@ -71,12 +72,14 @@
NSString *const kDecisionAllowScope = @"ALLOW_SCOPE";
NSString *const kDecisionAllowTeamID = @"ALLOW_TEAMID";
NSString *const kDecisionAllowSigningID = @"ALLOW_SIGNINGID";
NSString *const kDecisionAllowCDHash = @"ALLOW_CDHASH";
NSString *const kDecisionBlockUnknown = @"BLOCK_UNKNOWN";
NSString *const kDecisionBlockBinary = @"BLOCK_BINARY";
NSString *const kDecisionBlockCertificate = @"BLOCK_CERTIFICATE";
NSString *const kDecisionBlockScope = @"BLOCK_SCOPE";
NSString *const kDecisionBlockTeamID = @"BLOCK_TEAMID";
NSString *const kDecisionBlockSigningID = @"BLOCK_SIGNINGID";
NSString *const kDecisionBlockCDHash = @"BLOCK_CDHASH";
NSString *const kDecisionUnknown = @"UNKNOWN";
NSString *const kDecisionBundleBinary = @"BUNDLE_BINARY";
NSString *const kLoggedInUsers = @"logged_in_users";
Expand All @@ -102,6 +105,7 @@
NSString *const kCertValidUntil = @"valid_until";
NSString *const kTeamID = @"team_id";
NSString *const kSigningID = @"signing_id";
NSString *const kCDHash = @"cdhash";
NSString *const kQuarantineDataURL = @"quarantine_data_url";
NSString *const kQuarantineRefererURL = @"quarantine_referer_url";
NSString *const kQuarantineTimestamp = @"quarantine_timestamp";
Expand All @@ -126,6 +130,7 @@
NSString *const kRuleTypeCertificate = @"CERTIFICATE";
NSString *const kRuleTypeTeamID = @"TEAMID";
NSString *const kRuleTypeSigningID = @"SIGNINGID";
NSString *const kRuleTypeCDHash = @"CDHASH";
NSString *const kRuleCustomMsg = @"custom_msg";
NSString *const kRuleCustomURL = @"custom_url";
NSString *const kCursor = @"cursor";
Expand Down
13 changes: 4 additions & 9 deletions Source/common/SNTXPCUnprivilegedControlInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#import <MOLCertificate/MOLCertificate.h>

#import "Source/common/SNTCommonEnums.h"
#import "Source/common/SNTRuleIdentifiers.h"
#import "Source/common/SantaVnode.h"

@class SNTRule;
Expand All @@ -29,6 +30,7 @@ struct RuleCounts {
int64_t transitive;
int64_t teamID;
int64_t signingID;
int64_t cdhash;
};

///
Expand All @@ -55,17 +57,10 @@ struct RuleCounts {

///
/// @param filePath A Path to the file, can be nil.
/// @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 fileInfo and signingCertificate are both passed in, the most specific rule will be
/// returned. Binary rules take precedence over cert rules.
/// @param identifiers The various identifiers to be used when making a decision.
///
- (void)decisionForFilePath:(NSString *)filePath
fileSHA256:(NSString *)fileSHA256
certificateSHA256:(NSString *)certificateSHA256
teamID:(NSString *)teamID
signingID:(NSString *)signingID
identifiers:(SNTRuleIdentifiers *)identifiers
reply:(void (^)(SNTEventState))reply;

///
Expand Down
1 change: 1 addition & 0 deletions Source/common/santa.proto
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ message Execution {
REASON_LONG_PATH = 9;
REASON_NOT_RUNNING = 10;
REASON_SIGNING_ID = 11;
REASON_CDHASH = 12;
}
optional Reason reason = 10;

Expand Down
43 changes: 32 additions & 11 deletions Source/santactl/Commands/SNTCommandFileInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#import "Source/common/SNTFileInfo.h"
#import "Source/common/SNTLogging.h"
#import "Source/common/SNTRule.h"
#import "Source/common/SNTRuleIdentifiers.h"
#import "Source/common/SNTStoredEvent.h"
#import "Source/common/SNTXPCBundleServiceInterface.h"
#import "Source/common/SNTXPCControlInterface.h"
Expand All @@ -45,6 +46,7 @@
static NSString *const kUniversalSigningChain = @"Universal Signing Chain";
static NSString *const kTeamID = @"Team ID";
static NSString *const kSigningID = @"Signing ID";
static NSString *const kCDHash = @"CDHash";

// signing chain keys
static NSString *const kCommonName = @"Common Name";
Expand Down Expand Up @@ -123,6 +125,7 @@ @interface SNTCommandFileInfo : SNTCommand <SNTCommandProtocol>
@property(readonly, copy, nonatomic) SNTAttributeBlock downloadAgent;
@property(readonly, copy, nonatomic) SNTAttributeBlock teamID;
@property(readonly, copy, nonatomic) SNTAttributeBlock signingID;
@property(readonly, copy, nonatomic) SNTAttributeBlock cdhash;
@property(readonly, copy, nonatomic) SNTAttributeBlock type;
@property(readonly, copy, nonatomic) SNTAttributeBlock pageZero;
@property(readonly, copy, nonatomic) SNTAttributeBlock codeSigned;
Expand Down Expand Up @@ -201,8 +204,8 @@ + (NSString *)longHelpText {
+ (NSArray<NSString *> *)fileInfoKeys {
return @[
kPath, kSHA256, kSHA1, kBundleName, kBundleVersion, kBundleVersionStr, kDownloadReferrerURL,
kDownloadURL, kDownloadTimestamp, kDownloadAgent, kTeamID, kSigningID, kType, kPageZero,
kCodeSigned, kRule, kSigningChain, kUniversalSigningChain
kDownloadURL, kDownloadTimestamp, kDownloadAgent, kTeamID, kSigningID, kCDHash, kType,
kPageZero, kCodeSigned, kRule, kSigningChain, kUniversalSigningChain
];
}

Expand Down Expand Up @@ -236,6 +239,7 @@ - (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn {
kUniversalSigningChain : self.universalSigningChain,
kTeamID : self.teamID,
kSigningID : self.signingID,
kCDHash : self.cdhash,
};

_printQueue = dispatch_queue_create("com.google.santactl.print_queue", DISPATCH_QUEUE_SERIAL);
Expand Down Expand Up @@ -376,6 +380,8 @@ - (SNTAttributeBlock)rule {
NSError *err;
MOLCodesignChecker *csc = [fileInfo codesignCheckerWithError:&err];

NSString *cdhash =
[csc.signingInformation objectForKey:(__bridge NSString *)kSecCodeInfoUnique];
NSString *teamID =
[csc.signingInformation objectForKey:(__bridge NSString *)kSecCodeInfoTeamIdentifier];
NSString *identifier =
Expand All @@ -394,15 +400,21 @@ - (SNTAttributeBlock)rule {
}
}

[[cmd.daemonConn remoteObjectProxy] decisionForFilePath:fileInfo.path
fileSHA256:fileInfo.SHA256
certificateSHA256:err ? nil : csc.leafCertificate.SHA256
teamID:teamID
signingID:signingID
reply:^(SNTEventState s) {
state = s;
dispatch_semaphore_signal(sema);
}];
struct RuleIdentifiers identifiers = {
.cdhash = cdhash,
.binarySHA256 = fileInfo.SHA256,
.signingID = signingID,
.certificateSHA256 = err ? nil : csc.leafCertificate.SHA256,
.teamID = teamID,
};

[[cmd.daemonConn remoteObjectProxy]
decisionForFilePath:fileInfo.path
identifiers:[[SNTRuleIdentifiers alloc] initWithRuleIdentifiers:identifiers]
reply:^(SNTEventState s) {
state = s;
dispatch_semaphore_signal(sema);
}];
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
cmd.daemonUnavailable = YES;
return kCommunicationErrorMsg;
Expand All @@ -420,6 +432,8 @@ - (SNTAttributeBlock)rule {
case SNTEventStateBlockTeamID: [output appendString:@" (TeamID)"]; break;
case SNTEventStateAllowSigningID:
case SNTEventStateBlockSigningID: [output appendString:@" (SigningID)"]; break;
case SNTEventStateAllowCDHash:
case SNTEventStateBlockCDHash: [output appendString:@" (CDHash)"]; break;
case SNTEventStateAllowScope:
case SNTEventStateBlockScope: [output appendString:@" (Scope)"]; break;
case SNTEventStateAllowCompiler: [output appendString:@" (Compiler)"]; break;
Expand Down Expand Up @@ -519,6 +533,13 @@ - (SNTAttributeBlock)signingID {
};
}

- (SNTAttributeBlock)cdhash {
return ^id(SNTCommandFileInfo *cmd, SNTFileInfo *fileInfo) {
MOLCodesignChecker *csc = [fileInfo codesignCheckerWithError:NULL];
return [csc.signingInformation objectForKey:(__bridge NSString *)kSecCodeInfoUnique];
};
}

#pragma mark -

// Entry point for the command.
Expand Down
Loading
Loading