mirror of
https://github.com/google/santa.git
synced 2026-04-24 03:00:12 -04:00
Initial commit
This commit is contained in:
213
Source/common/SNTCodesignChecker.m.old
Normal file
213
Source/common/SNTCodesignChecker.m.old
Normal file
@@ -0,0 +1,213 @@
|
||||
#import "SNTCodesignChecker.h"
|
||||
|
||||
#import <Security/Security.h>
|
||||
|
||||
#import "SNTCertificate.h"
|
||||
|
||||
|
||||
// kStaticSigningFlags are the flags used when validating signatures on disk.
|
||||
//
|
||||
// Don't validate resources but do validate nested code. Ignoring resources _dramatically_ speeds
|
||||
// up validation (see below) but does mean images, plists, etc will not be checked and modifying
|
||||
// these will not be considered invalid. To ensure any code inside the binary is still checked,
|
||||
// we check nested code.
|
||||
//
|
||||
// Timings with different flags:
|
||||
// Checking Xcode 5.1.1 bundle:
|
||||
// kSecCSDefaultFlags: 3.895s
|
||||
// kSecCSDoNotValidateResources: 0.013s
|
||||
// kSecCSDoNotValidateResources | kSecCSCheckNestedCode: 0.013s
|
||||
//
|
||||
// Checking Google Chrome 36.0.1985.143 bundle:
|
||||
// kSecCSDefaultFlags: 0.529s
|
||||
// kSecCSDoNotValidateResources: 0.032s
|
||||
// kSecCSDoNotValidateResources | kSecCSCheckNestedCode: 0.033s
|
||||
//
|
||||
const SecCSFlags kStaticSigningFlags = kSecCSDoNotValidateResources | kSecCSCheckNestedCode;
|
||||
|
||||
// kSigningFlags are the flags used when validating signatures for running binaries.
|
||||
//
|
||||
// No special flags needed currently.
|
||||
const SecCSFlags kSigningFlags = kSecCSDefaultFlags;
|
||||
|
||||
|
||||
@implementation SNTCodesignChecker
|
||||
|
||||
#pragma mark Init/dealloc
|
||||
|
||||
- (instancetype)initWithSecStaticCodeRef:(SecStaticCodeRef)codeRef {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_codeRef = codeRef;
|
||||
CFRetain(_codeRef);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBinaryPath:(NSString *)binaryPath {
|
||||
SecStaticCodeRef codeRef = NULL;
|
||||
|
||||
// Get SecStaticCodeRef for binary
|
||||
if (SecStaticCodeCreateWithPath((__bridge CFURLRef)[NSURL fileURLWithPath:binaryPath
|
||||
isDirectory:NO],
|
||||
kSecCSDefaultFlags,
|
||||
&codeRef) == errSecSuccess) {
|
||||
self = [self initWithSecStaticCodeRef:codeRef];
|
||||
} else {
|
||||
self = nil;
|
||||
}
|
||||
|
||||
if (codeRef) CFRelease(codeRef);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithPID:(pid_t)PID {
|
||||
SecCodeRef codeRef = NULL;
|
||||
NSDictionary *attributes = @{(__bridge NSString *)kSecGuestAttributePid: @(PID)};
|
||||
|
||||
if (SecCodeCopyGuestWithAttributes(NULL,
|
||||
(__bridge CFDictionaryRef)attributes,
|
||||
kSecCSDefaultFlags,
|
||||
&codeRef) == errSecSuccess) {
|
||||
self = [self initWithSecStaticCodeRef:codeRef];
|
||||
} else {
|
||||
self = nil;
|
||||
}
|
||||
|
||||
if (codeRef) CFRelease(codeRef);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithSelf {
|
||||
SecCodeRef codeSelf = NULL;
|
||||
if (SecCodeCopySelf(kSecCSDefaultFlags, &codeSelf) == errSecSuccess) {
|
||||
self = [self initWithSecStaticCodeRef:codeSelf];
|
||||
} else {
|
||||
self = nil;
|
||||
}
|
||||
|
||||
if (codeSelf) CFRelease(codeSelf);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
[self doesNotRecognizeSelector:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (_codeRef) CFRelease(_codeRef);
|
||||
}
|
||||
|
||||
#pragma mark Validate
|
||||
|
||||
- (OSStatus)validate {
|
||||
return [self validateWithRequirement:NULL];
|
||||
}
|
||||
|
||||
- (OSStatus)validateAppleAnchor {
|
||||
SecRequirementRef req = NULL;
|
||||
SecRequirementCreateWithString(CFSTR("anchor apple"), kSecCSDefaultFlags, &req);
|
||||
return [self validateWithRequirement:req];
|
||||
}
|
||||
|
||||
- (OSStatus)validateAppleAnchorGeneric {
|
||||
SecRequirementRef req = NULL;
|
||||
SecRequirementCreateWithString(CFSTR("anchor apple generic"), kSecCSDefaultFlags, &req);
|
||||
return [self validateWithRequirement:req];
|
||||
}
|
||||
|
||||
- (OSStatus)validateWithRequirement:(SecRequirementRef)requirement {
|
||||
// Validate the binary and save the return code.
|
||||
if (CFGetTypeID(self.codeRef) == SecStaticCodeGetTypeID()) {
|
||||
return SecStaticCodeCheckValidity(self.codeRef, kStaticSigningFlags, requirement);
|
||||
} else if (CFGetTypeID(self.codeRef) == SecCodeGetTypeID()) {
|
||||
return SecCodeCheckValidity((SecCodeRef)self.codeRef, kSigningFlags, requirement);
|
||||
} else {
|
||||
return errSecCSSignatureNotVerifiable;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Description
|
||||
|
||||
- (NSString *)description {
|
||||
NSString *retStr;
|
||||
if (CFGetTypeID(self.codeRef) == SecStaticCodeGetTypeID()) {
|
||||
retStr = @"On-disk binary, ";
|
||||
} else {
|
||||
retStr = @"In-memory binary, ";
|
||||
}
|
||||
|
||||
if ([self validate] == errSecSuccess) {
|
||||
[retStr appendFormat:@"signed by %@, ", self.leafCertificate.orgName];
|
||||
} else {
|
||||
[retStr appendFormat:@"unsigned, "];
|
||||
}
|
||||
|
||||
[retStr appendFormat:@"located at: %@", self.binaryPath];
|
||||
|
||||
return retStr;
|
||||
}
|
||||
|
||||
#pragma mark Public accessors
|
||||
|
||||
- (NSDictionary *)signingInformation {
|
||||
static NSDictionary *signingInformation = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
// Get dictionary of signing information for binary
|
||||
CFDictionaryRef signingDict = NULL;
|
||||
SecCodeCopySigningInformation(self.codeRef, kSecCSSigningInformation, &signingDict);
|
||||
signingInformation = CFBridgingRelease(signingDict);
|
||||
});
|
||||
return signingInformation;
|
||||
}
|
||||
|
||||
- (NSArray *)certificates {
|
||||
static NSArray *certificates = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
// Get array of certificates, wrap each one in a SNTCertificate and store in a new array.
|
||||
NSArray *certs = self.signingInformation[(__bridge NSString *)kSecCodeInfoCertificates];
|
||||
|
||||
NSMutableArray *tempCerts = [[NSMutableArray alloc] initWithCapacity:certs.count];
|
||||
for (id cert in certs) {
|
||||
SNTCertificate *newCert =
|
||||
[[SNTCertificate alloc] initWithSecCertificateRef:(SecCertificateRef)cert];
|
||||
if (newCert) [tempCerts addObject:newCert];
|
||||
}
|
||||
certificates = [tempCerts copy];
|
||||
});
|
||||
return certificates;
|
||||
}
|
||||
|
||||
- (SNTCertificate *)leafCertificate {
|
||||
return [self.certificates firstObject];
|
||||
}
|
||||
|
||||
- (NSString *)binaryPath {
|
||||
CFURLRef path;
|
||||
OSStatus status = SecCodeCopyPath(_codeRef, kSecCSDefaultFlags, &path);
|
||||
NSURL *pathURL = CFBridgingRelease(path);
|
||||
if (status != errSecSuccess) return nil;
|
||||
return [pathURL path];
|
||||
}
|
||||
|
||||
#pragma mark Comparisons
|
||||
|
||||
- (BOOL)signingChainMatches:(SNTCodesignChecker *)otherChecker {
|
||||
return [self.certificates isEqual:otherChecker.certificates];
|
||||
}
|
||||
|
||||
- (BOOL)teamSigningMatches:(SNTCodesignChecker *)otherChecker {
|
||||
SNTCertificate *myLeaf = [self.certificates firstObject];
|
||||
SNTCertificate *otherLeaf = [otherChecker.certificates firstObject];
|
||||
|
||||
return ([myLeaf.orgUnit isEqual:otherLeaf.orgUnit] &&
|
||||
[self validateAppleAnchorGeneric] &&
|
||||
[otherChecker validateAppleAnchorGeneric]);
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user