Skip to content

Commit

Permalink
Experimental metrics (#1238)
Browse files Browse the repository at this point in the history
* Experimental metrics

* Fix tests, old platform builds

* Use more recent availability checks

* Update macro name, undef after usage
  • Loading branch information
mlw authored Nov 20, 2023
1 parent a5e8d77 commit f499654
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 2 deletions.
1 change: 1 addition & 0 deletions Source/santad/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ objc_library(
"//Source/common:SNTDeepCopy",
"//Source/common:SNTFileInfo",
"//Source/common:SNTLogging",
"//Source/common:SNTMetricSet",
"//Source/common:SNTRule",
"@FMDB",
"@MOLCertificate",
Expand Down
71 changes: 69 additions & 2 deletions Source/santad/SNTPolicyProcessor.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,33 @@
#import "Source/santad/SNTPolicyProcessor.h"
#include <Foundation/Foundation.h>

#include <Availability.h>
#include <Kernel/kern/cs_blobs.h>
#import <MOLCodesignChecker/MOLCodesignChecker.h>
#import <Security/SecCode.h>

#include "Source/common/SNTLogging.h"
#import <Security/Security.h>

#import "Source/common/SNTCachedDecision.h"
#import "Source/common/SNTConfigurator.h"
#import "Source/common/SNTDeepCopy.h"
#import "Source/common/SNTFileInfo.h"
#import "Source/common/SNTLogging.h"
#import "Source/common/SNTMetricSet.h"
#import "Source/common/SNTRule.h"
#import "Source/santad/DataLayer/SNTRuleTable.h"

NSArray<NSString *> *FieldValuesForProperties(BOOL csDevFlagSet, BOOL validationCategoryThree,
BOOL oidsSet) {
#define SNT_BOOL_STR(b) (b) ? @"True" : @"False"
return
@[ SNT_BOOL_STR(csDevFlagSet), SNT_BOOL_STR(validationCategoryThree), SNT_BOOL_STR(oidsSet) ];
#undef SNT_BOOL_STR
}

@interface SNTPolicyProcessor ()
@property SNTRuleTable *ruleTable;
@property SNTConfigurator *configurator;
@property SNTMetricCounter *experimentalDevMetrics;
@end

@implementation SNTPolicyProcessor
Expand All @@ -39,6 +51,11 @@ - (instancetype)initWithRuleTable:(SNTRuleTable *)ruleTable {
if (self) {
_ruleTable = ruleTable;
_configurator = [SNTConfigurator configurator];

_experimentalDevMetrics = [[SNTMetricSet sharedInstance]
counterWithName:@"/santa/tmp_signing_info_experiment"
fieldNames:@[ @"CSDevFlagSet", @"ValidationCategory", @"DevOIDSet" ]
helpText:@"Temporary experiment for dev signed code"];
}
return self;
}
Expand All @@ -48,6 +65,7 @@ - (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileIn
certificateSHA256:(nullable NSString *)certificateSHA256
teamID:(nullable NSString *)teamID
signingID:(nullable NSString *)signingID
targetProcess:(nullable const es_process_t *)targetProc
entitlementsFilterCallback:
(NSDictionary *_Nullable (^_Nullable)(
NSDictionary *_Nullable entitlements))entitlementsFilterCallback {
Expand Down Expand Up @@ -108,6 +126,53 @@ - (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileIn
cd.entitlements = [entitlements sntDeepCopy];
cd.entitlementsFiltered = NO;
}

#if defined(MAC_OS_VERSION_13_3) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_13_3
if (@available(macOS 13.0, *)) {
// Temporary experiment code...
if (targetProc != NULL && fileInfo.path != nil) {
// Doing a second SecStaticCodeCreate to not need to worry about modifying the
// dependency...
SecStaticCodeRef codeRef = NULL;
OSStatus status = SecStaticCodeCreateWithPath(
(__bridge CFURLRef)[NSURL fileURLWithPath:fileInfo.path], kSecCSDefaultFlags, &codeRef);
if (status == errSecSuccess) {
CFDictionaryRef cfSigningInfo = NULL;
SecCodeCopySigningInformation(
codeRef, kSecCSSigningInformation | kSecCSRequirementInformation, &cfSigningInfo);
NSDictionary *signingInfo = CFBridgingRelease(cfSigningInfo);

// Taken from Security framework: LWCRHelper.mm
NSString *reqVaidationCategryKey = @"validation-category";
// Taken from Security framework:
NSArray *keys = @[ @"1.2.840.113635.100.6.1.2", @"1.2.840.113635.100.6.1.12" ];
NSDictionary *lwCodeReq = signingInfo[(
__bridge NSString *)kSecCodeInfoDefaultDesignatedLightweightCodeRequirement];

NSDictionary *vals = CFBridgingRelease(SecCertificateCopyValues(
csInfo.leafCertificate.certRef, (__bridge CFArrayRef)keys, NULL));

BOOL validationCategoryThree = [lwCodeReq[reqVaidationCategryKey] intValue] == 3;
BOOL csDevFlagSet = ((targetProc->codesigning_flags & CS_DEV_CODE) != 0);
BOOL oidsSet = vals.count > 0;

[self.experimentalDevMetrics
incrementForFieldValues:FieldValuesForProperties(csDevFlagSet,
validationCategoryThree, oidsSet)];

if (!(csDevFlagSet == validationCategoryThree && csDevFlagSet == oidsSet)) {
NSDictionary *certVals = CFBridgingRelease(
SecCertificateCopyValues(csInfo.leafCertificate.certRef, NULL, NULL));
LOGI(@"EXPERIMENTAL Unexpected state difference: %@ | Flags(%d): 0x%08x, VC(%d): %d, "
@"oids(%d): %@",
fileInfo.path, csDevFlagSet, targetProc->codesigning_flags,
validationCategoryThree, [lwCodeReq[reqVaidationCategryKey] intValue], oidsSet,
[certVals allKeys]);
}
}
}
}
#endif
}
}
cd.quarantineURL = fileInfo.quarantineDataURL;
Expand Down Expand Up @@ -267,6 +332,7 @@ - (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileIn
certificateSHA256:nil
teamID:teamID
signingID:signingID
targetProcess:targetProc
entitlementsFilterCallback:^NSDictionary *(NSDictionary *entitlements) {
return entitlementsFilterCallback(entitlementsFilterTeamID, entitlements);
}];
Expand All @@ -287,6 +353,7 @@ - (nonnull SNTCachedDecision *)decisionForFilePath:(nonnull NSString *)filePath
certificateSHA256:certificateSHA256
teamID:teamID
signingID:signingID
targetProcess:NULL
entitlementsFilterCallback:nil];
}

Expand Down

0 comments on commit f499654

Please sign in to comment.