Compare commits

...

26 Commits
0.9.5 ... 0.9.7

Author SHA1 Message Date
Russell Hancox
d295f2391f santactl/sync: In --debug log the full NSError for failed requests 2015-12-15 12:36:07 -05:00
Russell Hancox
c042222eea santad: Add user/group info to file changelogs also 2015-12-14 22:32:59 -05:00
Russell Hancox
63f6596bc2 santactl: Rename binaryinfo -> fileinfo. 2015-12-14 18:09:40 -05:00
Russell Hancox
d8a8aba0ea SNTFileInfo: Move machoType method to binaryinfo command, add XAR archive detection. 2015-12-14 17:25:32 -05:00
Russell Hancox
d9d9682029 santactl/sync: Let related-binary search take up to 5s 2015-12-14 16:37:19 -05:00
Russell Hancox
4a27a8ac70 Rakefile: Use Xcode to figure out where built products went, to avoid relying on particular Xcode settings. 2015-12-14 16:36:11 -05:00
Russell Hancox
32857ff304 Project: Apply latest Xcode recommendations 2015-12-14 16:35:34 -05:00
Russell Hancox
375bfd3862 santa-driver: Put locks around vnode_pid_map, use an OSObject subclass to store PID/PPID.
Put a R/W lock around vnode_pid_map_ to prevent use-after-free.
Create SantaPIDAndPPID to use instead of creating and then scanning strings.
Also rename SantaMessage -> SantaCachedDecision, as that's what it is.
2015-12-14 16:34:38 -05:00
Russell Hancox
9430c41b8a santad: Include user and group names in execution logs 2015-12-11 12:58:09 -05:00
Russell Hancox
9b342e146a santactl/sync: Include code sign info with related executables and encode to dict. 2015-12-10 17:37:22 -05:00
Russell Hancox
e5685f2959 santad: Don't try to add empty argument to array when processing execution arguments 2015-12-10 17:02:11 -05:00
Russell Hancox
4150feece2 santactl/sync: When uploading events for bundles, look for other bundled executables.
Many application bundles have related helper tools, which will individually need to be whitelisted unless they're covered by a certificate. To help make user's lives easier, when an event is triggered for a binary inside a bundle look for other executables in the same bundle and upload an event for those too (with an obvious tag) so that the server can let the user vote to whitelist all the binaries together.
2015-12-10 17:01:49 -05:00
Russell Hancox
6879ec5deb santa-driver: in DecisionManager free locks before anything else 2015-12-10 16:56:13 -05:00
Russell Hancox
28ad00ffad SantaGUI: Split block messages into unknown and banned.
This is so that a message can be configured for banned executables without having to provide a custom message for every single one.
2015-12-10 12:13:52 -05:00
Russell Hancox
bf51049fbf santa-driver: Save pid/ppid from VFS context when decision making for use when logging
Previously the execution logging from fileop didn't work when using posix_spawn as proc_selfpid/proc_selfppid still refer to the process calling posix_spawn. We can get the correct pid/ppid from the vfs_context in the vnode scope but we can't log executions from there as the arguments end up being wrong. Instead, save the vnode_id->pid/ppid mapping in the vnode scope and use that in the fileop scope for logging.
2015-12-10 12:12:38 -05:00
Russell Hancox
36189e9122 santad: Update SNTFileInfo to always get strings from bundle Info.plist data.
Also perform a one-time update of any events created before this change.
2015-12-04 13:09:56 -05:00
Russell Hancox
4c747463ac santad: Separate execution requests and logging into separate queues with appropriate priorities. 2015-12-04 12:39:26 -05:00
Russell Hancox
b4b1fbb9e6 santad: Run watchdog thread loop once before sleeping 2015-10-31 14:01:44 -04:00
Russell Hancox
209eaff3c6 SNTFileInfo: Embed SHA hashing loop in an autoreleasepool to avoid temporary RAM spikes 2015-10-31 13:45:47 -04:00
Russell Hancox
c3f70703fd santactl/status: Expose peak CPU/RAM use from santad. 2015-10-29 16:20:57 -04:00
Russell Hancox
f2967e7b94 santad: Switch watchdog CPU counter from rusage to task_info, capture peak CPU/RAM use. 2015-10-29 16:20:25 -04:00
Russell Hancox
77c46b5c43 SNTFileInfo: switch from NSData to NSFileHandle.
This seems to work much better than NSData with either mapped (SIGBUS when file is deleted) or uncached (ballooning memory use) reading.
2015-10-29 16:17:12 -04:00
Russell Hancox
5fda5bc081 santactl/binaryinfo: Only print bundle lines if bundle info is present 2015-10-29 12:35:27 -04:00
Russell Hancox
33a7b38c6a SNTFileInfo: check for NULL ptrs when parsing for embedded plist 2015-10-27 18:35:11 -04:00
Russell Hancox
2a7c0bd58c SNTFileInfo: Go back to using mmap, uncached read balloons memory use 2015-10-27 18:08:16 -04:00
Russell Hancox
86e4d0db0f santactl: Use yyyy instead of YYYY in NSDateFormatter 2015-10-27 17:58:23 -04:00
39 changed files with 584 additions and 225 deletions

View File

@@ -25,6 +25,17 @@ def xcodebuild(opts)
end
end
def xcodebuilddir
if not $xcode_build_dir
output = `xcodebuild #{XCODEBUILD_DEFAULTS} -scheme All -showBuildSettings`
if match = output.match(/BUILD_DIR = (.*)/)
$xcode_build_dir = match.captures.first
puts "Found Xcode build dir #{$xcode_build_dir}"
end
end
$xcode_build_dir
end
task :init do
unless File.exists?(WORKSPACE) and File.exists?('Pods')
puts "Pods missing, running 'pod install'"
@@ -88,8 +99,8 @@ namespace :install do
Rake::Task['build:build'].invoke(config)
puts "Installing with configuration: #{config}"
Rake::Task['remove_existing'].invoke()
system "sudo cp -r #{OUTPUT_PATH}/Products/#{config}/santa-driver.kext /Library/Extensions"
system "sudo cp -r #{OUTPUT_PATH}/Products/#{config}/Santa.app /Applications"
system "sudo cp -r #{xcodebuilddir}/#{config}/santa-driver.kext /Library/Extensions"
system "sudo cp -r #{xcodebuilddir}/#{config}/Santa.app /Applications"
end
end
@@ -107,11 +118,11 @@ task :dist do
FileUtils.mkdir_p("#{DIST_PATH}/dsym")
BINARIES.each do |x|
FileUtils.cp_r("#{OUTPUT_PATH}/Products/Release/#{x}", "#{DIST_PATH}/binaries")
FileUtils.cp_r("#{xcodebuilddir}/Release/#{x}", "#{DIST_PATH}/binaries")
end
DSYMS.each do |x|
FileUtils.cp_r("#{OUTPUT_PATH}/Products/Release/#{x}", "#{DIST_PATH}/dsym")
FileUtils.cp_r("#{xcodebuilddir}/Release/#{x}", "#{DIST_PATH}/dsym")
end
@@ -137,7 +148,7 @@ namespace :tests do
begin
puts "\033[?25l\033[12h" # hide cursor
puts "Running kernel tests"
system "cd /tmp/santa_kerneltests_tmp && sudo #{Dir.pwd}/#{OUTPUT_PATH}/Products/Debug/KernelTests"
system "cd /tmp/santa_kerneltests_tmp && sudo #{xcodebuilddir}/Debug/KernelTests"
rescue Exception
ensure
puts "\033[?25h\033[12l\n\n" # unhide cursor

View File

@@ -89,8 +89,8 @@
0D6FDC8718C6913D0044685C /* apple.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0D6FDC8618C6913D0044685C /* apple.pem */; };
0D6FDC9618C93A020044685C /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; };
0D6FDC9718C93A020044685C /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; };
0D7A7AF3174FCF4C00B77646 /* SantaMessage.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A7AF1174FCF4C00B77646 /* SantaMessage.cc */; };
0D7A7AF4174FCF4C00B77646 /* SantaMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D7A7AF2174FCF4C00B77646 /* SantaMessage.h */; };
0D7A7AF3174FCF4C00B77646 /* SantaCachedDecision.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A7AF1174FCF4C00B77646 /* SantaCachedDecision.cc */; };
0D7A7AF4174FCF4C00B77646 /* SantaCachedDecision.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D7A7AF2174FCF4C00B77646 /* SantaCachedDecision.h */; };
0D7D01871774F93A005DBAB4 /* SNTDriverManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D7D01861774F93A005DBAB4 /* SNTDriverManager.m */; };
0D7FFD4B1A017D4B00F34435 /* SNTDERDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FFD4A1A017D4B00F34435 /* SNTDERDecoder.m */; };
0D827E6519DF392E006EC811 /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; };
@@ -113,13 +113,15 @@
0DB390991AB1E11400614002 /* SNTCommandVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DB390981AB1E11400614002 /* SNTCommandVersion.m */; };
0DB537871AFD36EB00487F92 /* SNTRuleTableTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DB537861AFD36EB00487F92 /* SNTRuleTableTest.m */; };
0DB8ACC1185662DC00FEF9C7 /* SNTApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */; };
0DB98BFA1C1B9F3000B65DB1 /* SantaPIDAndPPID.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0DB98BF81C1B9F3000B65DB1 /* SantaPIDAndPPID.cc */; settings = {ASSET_TAGS = (); }; };
0DB98BFB1C1B9F3000B65DB1 /* SantaPIDAndPPID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DB98BF91C1B9F3000B65DB1 /* SantaPIDAndPPID.h */; settings = {ASSET_TAGS = (); }; };
0DC5D86D191AED220078A5C0 /* SNTRuleTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */; };
0DC5D86E191AED220078A5C0 /* SNTRuleTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */; };
0DC5D871192160180078A5C0 /* SNTCommandSyncLogUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D870192160180078A5C0 /* SNTCommandSyncLogUpload.m */; };
0DC765EA1B28D9EA00BAE651 /* santad in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0D9A7F3D1759330500035EB5 /* santad */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
0DC765EB1B28D9EA00BAE651 /* santactl in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0D35BD9E18FD71CE00921A21 /* santactl */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; };
0DCD5FBF1909D64A006B445C /* SNTCommandBinaryInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD5FBE1909D64A006B445C /* SNTCommandBinaryInfo.m */; };
0DCD5FBF1909D64A006B445C /* SNTCommandFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */; };
0DCD6042190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
0DCD6043190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
0DCD6044190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
@@ -306,8 +308,8 @@
0D6FDC8618C6913D0044685C /* apple.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = apple.pem; sourceTree = "<group>"; };
0D6FDC9418C93A020044685C /* SNTXPCConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCConnection.h; sourceTree = "<group>"; };
0D6FDC9518C93A020044685C /* SNTXPCConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCConnection.m; sourceTree = "<group>"; };
0D7A7AF1174FCF4C00B77646 /* SantaMessage.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SantaMessage.cc; sourceTree = "<group>"; };
0D7A7AF2174FCF4C00B77646 /* SantaMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SantaMessage.h; sourceTree = "<group>"; };
0D7A7AF1174FCF4C00B77646 /* SantaCachedDecision.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SantaCachedDecision.cc; sourceTree = "<group>"; };
0D7A7AF2174FCF4C00B77646 /* SantaCachedDecision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SantaCachedDecision.h; sourceTree = "<group>"; };
0D7D01851774F93A005DBAB4 /* SNTDriverManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTDriverManager.h; sourceTree = "<group>"; };
0D7D01861774F93A005DBAB4 /* SNTDriverManager.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = SNTDriverManager.m; sourceTree = "<group>"; };
0D7FFD491A017D4B00F34435 /* SNTDERDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTDERDecoder.h; sourceTree = "<group>"; };
@@ -334,12 +336,14 @@
0DB8ACBF185662DC00FEF9C7 /* SNTApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTApplication.h; sourceTree = "<group>"; };
0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SNTApplication.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
0DB8ACE41858D73000FEF9C7 /* santad-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "santad-Info.plist"; sourceTree = "<group>"; };
0DB98BF81C1B9F3000B65DB1 /* SantaPIDAndPPID.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SantaPIDAndPPID.cc; sourceTree = "<group>"; };
0DB98BF91C1B9F3000B65DB1 /* SantaPIDAndPPID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SantaPIDAndPPID.h; sourceTree = "<group>"; };
0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTRuleTable.m; sourceTree = "<group>"; };
0DC5D86F192160180078A5C0 /* SNTCommandSyncLogUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncLogUpload.h; sourceTree = "<group>"; };
0DC5D870192160180078A5C0 /* SNTCommandSyncLogUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandSyncLogUpload.m; sourceTree = "<group>"; };
0DC8C9E3180CC3BC00FCFB29 /* SNTXPCNotifierInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCNotifierInterface.h; sourceTree = "<group>"; };
0DCD5F771909C659006B445C /* SecurityInterface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityInterface.framework; path = System/Library/Frameworks/SecurityInterface.framework; sourceTree = SDKROOT; };
0DCD5FBE1909D64A006B445C /* SNTCommandBinaryInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandBinaryInfo.m; sourceTree = "<group>"; };
0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandFileInfo.m; sourceTree = "<group>"; };
0DCD6040190ACCB8006B445C /* SNTFileInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTFileInfo.h; sourceTree = "<group>"; };
0DCD6041190ACCB8006B445C /* SNTFileInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTFileInfo.m; sourceTree = "<group>"; };
0DCD604919105433006B445C /* SNTStoredEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTStoredEvent.h; sourceTree = "<group>"; };
@@ -482,15 +486,10 @@
0D35BDA018FD71CE00921A21 /* santactl */ = {
isa = PBXGroup;
children = (
0D35BDA118FD71CE00921A21 /* main.m */,
0D35BDAA18FD7CFD00921A21 /* SNTCommandController.h */,
0D35BDA118FD71CE00921A21 /* main.m */,
0D35BDAB18FD7CFD00921A21 /* SNTCommandController.m */,
0DCD5FBC1909D4FD006B445C /* binaryinfo */,
0DE4C8A318FF3AFA00466D04 /* flushcache */,
409232751A51914400A04527 /* rule */,
0D827E6819DF4F3F006EC811 /* status */,
0D35BDB618FD84FC00921A21 /* sync */,
0DB390971AB1E0F200614002 /* version */,
0DAF01141C1B794B00F5B6C3 /* Commands */,
0D35BDA318FD71CE00921A21 /* Resources */,
);
name = santactl;
@@ -642,14 +641,16 @@
0D91BCB9174E8A7E00131A7D /* santa-driver */ = {
isa = PBXGroup;
children = (
0D7A7AF2174FCF4C00B77646 /* SantaCachedDecision.h */,
0D7A7AF1174FCF4C00B77646 /* SantaCachedDecision.cc */,
0D4644C4182AF81700098690 /* SantaDecisionManager.h */,
0D4644C3182AF81700098690 /* SantaDecisionManager.cc */,
0D9A7F321759144800035EB5 /* SantaDriver.h */,
0D9A7F311759144800035EB5 /* SantaDriver.cc */,
0D9A7F361759148E00035EB5 /* SantaDriverClient.h */,
0D9A7F351759148E00035EB5 /* SantaDriverClient.cc */,
0D4644C4182AF81700098690 /* SantaDecisionManager.h */,
0D4644C3182AF81700098690 /* SantaDecisionManager.cc */,
0D7A7AF2174FCF4C00B77646 /* SantaMessage.h */,
0D7A7AF1174FCF4C00B77646 /* SantaMessage.cc */,
0DB98BF91C1B9F3000B65DB1 /* SantaPIDAndPPID.h */,
0DB98BF81C1B9F3000B65DB1 /* SantaPIDAndPPID.cc */,
0DA36C1F199EA46600A129D6 /* Resources */,
);
name = "santa-driver";
@@ -734,6 +735,19 @@
name = DataLayer;
sourceTree = "<group>";
};
0DAF01141C1B794B00F5B6C3 /* Commands */ = {
isa = PBXGroup;
children = (
0DCD5FBC1909D4FD006B445C /* fileinfo */,
0DE4C8A318FF3AFA00466D04 /* flushcache */,
409232751A51914400A04527 /* rule */,
0D827E6819DF4F3F006EC811 /* status */,
0D35BDB618FD84FC00921A21 /* sync */,
0DB390971AB1E0F200614002 /* version */,
);
name = Commands;
sourceTree = "<group>";
};
0DB390971AB1E0F200614002 /* version */ = {
isa = PBXGroup;
children = (
@@ -742,12 +756,12 @@
name = version;
sourceTree = "<group>";
};
0DCD5FBC1909D4FD006B445C /* binaryinfo */ = {
0DCD5FBC1909D4FD006B445C /* fileinfo */ = {
isa = PBXGroup;
children = (
0DCD5FBE1909D64A006B445C /* SNTCommandBinaryInfo.m */,
0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */,
);
path = binaryinfo;
path = fileinfo;
sourceTree = "<group>";
};
0DE4C8A318FF3AFA00466D04 /* flushcache */ = {
@@ -788,7 +802,8 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
0D7A7AF4174FCF4C00B77646 /* SantaMessage.h in Headers */,
0D7A7AF4174FCF4C00B77646 /* SantaCachedDecision.h in Headers */,
0DB98BFB1C1B9F3000B65DB1 /* SantaPIDAndPPID.h in Headers */,
0D4644C6182AF81700098690 /* SantaDecisionManager.h in Headers */,
0D9A7F341759144800035EB5 /* SantaDriver.h in Headers */,
0D9A7F381759148E00035EB5 /* SantaDriverClient.h in Headers */,
@@ -921,7 +936,7 @@
0D91BCA8174E8A6500131A7D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0510;
LastUpgradeCheck = 0700;
TargetAttributes = {
0D260DAB18B68E12002A0B55 = {
TestTargetID = 0D385DB5180DE4A900418BC6;
@@ -1276,7 +1291,7 @@
files = (
0DA73CA21934F88D0056D7C4 /* SNTLogging.m in Sources */,
0D35BDB518FD84F600921A21 /* SNTCommandSync.m in Sources */,
0DCD5FBF1909D64A006B445C /* SNTCommandBinaryInfo.m in Sources */,
0DCD5FBF1909D64A006B445C /* SNTCommandFileInfo.m in Sources */,
0DEFB7C01ACB28B000B92AAE /* SNTCommandSyncConstants.m in Sources */,
0DCD6062191188B1006B445C /* SNTAuthenticatingURLSession.m in Sources */,
0DCD605619115D17006B445C /* SNTXPCControlInterface.m in Sources */,
@@ -1329,7 +1344,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D7A7AF3174FCF4C00B77646 /* SantaMessage.cc in Sources */,
0D7A7AF3174FCF4C00B77646 /* SantaCachedDecision.cc in Sources */,
0DB98BFA1C1B9F3000B65DB1 /* SantaPIDAndPPID.cc in Sources */,
0D9A7F331759144800035EB5 /* SantaDriver.cc in Sources */,
0D9A7F371759148E00035EB5 /* SantaDriverClient.cc in Sources */,
0D4644C5182AF81700098690 /* SantaDecisionManager.cc in Sources */,
@@ -1521,6 +1537,7 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = "Tests/LogicTests/Resources/Tests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WARNING_CFLAGS = "";
WRAPPER_EXTENSION = xctest;
@@ -1565,6 +1582,7 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = "Tests/LogicTests/Resources/Tests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WARNING_CFLAGS = "";
WRAPPER_EXTENSION = xctest;
@@ -1734,6 +1752,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_WARN_CXX0X_EXTENSIONS = YES;
CODE_SIGN_IDENTITY = "Mac Developer";
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = c99;
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
@@ -39,15 +39,18 @@
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@@ -62,10 +65,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
@@ -38,15 +38,18 @@
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
@@ -62,10 +65,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
@@ -48,15 +48,18 @@
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@@ -71,10 +74,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
@@ -38,15 +38,18 @@
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
@@ -62,10 +65,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,21 +23,24 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@@ -52,10 +55,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
@@ -38,15 +38,18 @@
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
@@ -62,10 +65,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
@@ -38,16 +38,19 @@
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
debugAsWhichUser = "root"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
@@ -63,10 +66,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@@ -134,14 +134,20 @@
NSString *htmlFooter = @"</body></html>";
NSString *message;
if ([self.customMessage length] > 0) {
if (self.customMessage.length) {
message = self.customMessage;
} else {
message = [[SNTConfigurator configurator] defaultBlockMessage];
} else if (self.event.decision == EVENTSTATE_BLOCK_UNKNOWN) {
message = [[SNTConfigurator configurator] unknownBlockMessage];
if (!message) {
message = @"The following application has been blocked from executing<br />"
@"because its trustworthiness cannot be determined.";
}
} else {
message = [[SNTConfigurator configurator] bannedBlockMessage];
if (!message) {
message = @"The following application has been blocked from executing<br />"
@"because it has been deemed malicious.";
}
}
NSString *fullHTML = [NSString stringWithFormat:@"%@%@%@", htmlHeader, message, htmlFooter];

View File

@@ -62,6 +62,8 @@ typedef enum {
EVENTSTATE_BLOCK_CERTIFICATE = 7,
EVENTSTATE_BLOCK_SCOPE = 8,
EVENTSTATE_RELATED_BINARY = 9,
EVENTSTATE_MAX
} santa_eventstate_t;

View File

@@ -94,10 +94,17 @@ extern NSString * const kDefaultConfigFilePath;
@property(readonly, nonatomic) NSString *eventDetailText;
///
/// For any rule that doesn't have a custom message, this setting overrides the message
/// text that is display. If unset, a reasonable default is provided.
/// In lockdown mode this is the message shown to the user when an unknown binary
/// is blocked. If this message is not configured, a reasonable default is provided.
///
@property(readonly, nonatomic) NSString *defaultBlockMessage;
@property(readonly, nonatomic) NSString *unknownBlockMessage;
///
/// This is the message shown to the user when a binary is blocked because of a rule,
/// if that rule doesn't provide a custom message. If this is not configured, a reasonable
/// default is provided.
///
@property(readonly, nonatomic) NSString *bannedBlockMessage;
#pragma mark - Sync Settings

View File

@@ -45,7 +45,8 @@ static NSString * const kEnablePageZeroProtectionKey = @"EnablePageZeroProtectio
static NSString * const kMoreInfoURLKey = @"MoreInfoURL";
static NSString * const kEventDetailURLKey = @"EventDetailURL";
static NSString * const kEventDetailTextKey = @"EventDetailText";
static NSString * const kDefaultBlockMessage = @"DefaultBlockMessage";
static NSString * const kUnknownBlockMessage = @"UnknownBlockMessage";
static NSString * const kBannedBlockMessage = @"BannedBlockMessage";
static NSString * const kSyncBaseURLKey = @"SyncBaseURL";
static NSString * const kSyncLastSuccess = @"SyncLastSuccess";
@@ -192,8 +193,12 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
return self.configData[kEventDetailTextKey];
}
- (NSString *)defaultBlockMessage {
return self.configData[kDefaultBlockMessage];
- (NSString *)unknownBlockMessage {
return self.configData[kUnknownBlockMessage];
}
- (NSString *)bannedBlockMessage {
return self.configData[kBannedBlockMessage];
}
- (NSURL *)syncBaseURL {

View File

@@ -51,12 +51,6 @@
///
- (NSString *)SHA256;
///
/// @return The type of Mach-O file, one of:
/// Dynamic Library, Kernel Extension, Fat Binary or Thin Binary.
///
- (NSString *)machoType;
///
/// @return The architectures included in this binary (e.g. x86_64, ppc).
///
@@ -97,6 +91,11 @@
///
- (BOOL)isMissingPageZero;
///
/// @return YES if this file is an XAR archive.
///
- (BOOL)isXARArchive;
///
/// @return An NSBundle if this file is part of a bundle.
///

View File

@@ -18,6 +18,7 @@
#include <mach-o/loader.h>
#include <mach-o/swap.h>
#include <sys/stat.h>
// Simple class to hold the data of a mach_header and the offset within the file
// in which that header was found.
@@ -39,15 +40,14 @@
@interface SNTFileInfo ()
@property NSString *path;
@property NSData *fileData;
// Dictionary of MachHeaderWithOffset objects where the keys are the architecture strings
@property NSDictionary *machHeaders;
@property NSFileHandle *fileHandle;
@property NSUInteger fileSize;
// Cached properties
@property NSBundle *bundleRef;
@property NSDictionary *infoDict;
@property NSDictionary *quarantineDict;
@property NSDictionary *cachedHeaders;
@end
@implementation SNTFileInfo
@@ -69,11 +69,13 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
return nil;
}
_fileData = [NSData dataWithContentsOfFile:_path
options:NSDataReadingUncached
error:error];
if (_fileData.length == 0) return nil;
[self parseMachHeaders];
_fileHandle = [NSFileHandle fileHandleForReadingAtPath:_path];
struct stat fileStat;
fstat(_fileHandle.fileDescriptor, &fileStat);
_fileSize = fileStat.st_size;
if (_fileSize == 0) return nil;
}
return self;
@@ -83,11 +85,34 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
return [self initWithPath:path error:NULL];
}
- (NSString *)SHA1 {
unsigned char sha1[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(self.fileData.bytes, (unsigned int)self.fileData.length, sha1);
# pragma mark Hashing
- (NSString *)SHA1 {
const int chunkSize = 4096;
CC_SHA1_CTX c;
CC_SHA1_Init(&c);
for (uint64_t offset = 0; offset < self.fileSize; offset += chunkSize) {
@autoreleasepool {
int readSize;
if (offset + chunkSize > self.fileSize) {
readSize = (int)(self.fileSize - offset);
} else {
readSize = chunkSize;
}
NSData *chunk = [self safeSubdataWithRange:NSMakeRange(offset, readSize)];
if (!chunk) {
CC_SHA1_Final(NULL, &c);
return nil;
}
CC_SHA1_Update(&c, chunk.bytes, readSize);
}
}
unsigned char sha1[CC_SHA1_DIGEST_LENGTH];
CC_SHA1_Final(sha1, &c);
// Convert the binary SHA into hex
NSMutableString *buf = [[NSMutableString alloc] initWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
[buf appendFormat:@"%02x", (unsigned char)sha1[i]];
@@ -97,30 +122,52 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
}
- (NSString *)SHA256 {
const int chunkSize = 4096;
CC_SHA256_CTX c;
CC_SHA256_Init(&c);
for (uint64_t offset = 0; offset < self.fileSize; offset += chunkSize) {
@autoreleasepool {
int readSize;
if (offset + chunkSize > self.fileSize) {
readSize = (int)(self.fileSize - offset);
} else {
readSize = chunkSize;
}
NSData *chunk = [self safeSubdataWithRange:NSMakeRange(offset, readSize)];
if (!chunk) {
CC_SHA256_Final(NULL, &c);
return nil;
}
CC_SHA256_Update(&c, chunk.bytes, readSize);
}
}
unsigned char sha256[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(self.fileData.bytes, (unsigned int)self.fileData.length, sha256);
CC_SHA256_Final(sha256, &c);
NSMutableString *buf = [[NSMutableString alloc] initWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[buf appendFormat:@"%02x", (unsigned char)sha256[i]];
}
return buf;
}
- (NSString *)machoType {
if ([self isDylib]) return @"Dynamic Library";
if ([self isKext]) return @"Kernel Extension";
if ([self isFat]) return @"Fat Binary";
if ([self isMachO]) return @"Thin Binary";
if ([self isScript]) return @"Script";
return @"Unknown (not executable?)";
}
# pragma mark File Type Info
- (NSArray *)architectures {
return [self.machHeaders allKeys];
}
- (BOOL)isExecutable {
struct mach_header *mach_header = [self firstMachHeader];
if (mach_header && mach_header->filetype == MH_EXECUTE) return YES;
return NO;
}
- (BOOL)isDylib {
struct mach_header *mach_header = [self firstMachHeader];
if (mach_header && mach_header->filetype == MH_DYLIB) return YES;
@@ -134,11 +181,11 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
}
- (BOOL)isMachO {
return ([self.machHeaders count] > 0);
return (self.machHeaders.count > 0);
}
- (BOOL)isFat {
return ([self.machHeaders count] > 1);
return (self.machHeaders.count > 1);
}
- (BOOL)isScript {
@@ -146,17 +193,15 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
return (strncmp("#!", magic, 2) == 0);
}
- (BOOL)isExecutable {
struct mach_header *mach_header = [self firstMachHeader];
if (!mach_header) return NO;
if (mach_header->filetype == MH_OBJECT || mach_header->filetype == MH_EXECUTE) return YES;
return NO;
- (BOOL)isXARArchive {
const char *magic = (const char *)[[self safeSubdataWithRange:NSMakeRange(0, 4)] bytes];
return (strncmp("xar!", magic, 4) == 0);
}
- (BOOL)isMissingPageZero {
// This method only checks i386 arch because the kernel enforces this for other archs
// See bsd/kern/mach_loader.c, search for enforce_hard_pagezero.
MachHeaderWithOffset *x86Header = self.machHeaders[@"i386"];
MachHeaderWithOffset *x86Header = self.machHeaders[[self nameForCPUType:CPU_TYPE_X86]];
if (!x86Header) return NO;
struct mach_header *mh = (struct mach_header *)[x86Header.data bytes];
@@ -244,21 +289,23 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
}
- (NSString *)bundleIdentifier {
return [self.infoPlist objectForKey:@"CFBundleIdentifier"];
return [[self.infoPlist objectForKey:@"CFBundleIdentifier"] description];
}
- (NSString *)bundleName {
return [self.infoPlist objectForKey:@"CFBundleName"];
return [[self.infoPlist objectForKey:@"CFBundleName"] description];
}
- (NSString *)bundleVersion {
return [self.infoPlist objectForKey:@"CFBundleVersion"];
return [[self.infoPlist objectForKey:@"CFBundleVersion"] description];
}
- (NSString *)bundleShortVersionString {
return [self.infoPlist objectForKey:@"CFBundleShortVersionString"];
return [[self.infoPlist objectForKey:@"CFBundleShortVersionString"] description];
}
#pragma mark Quarantine Data
- (NSString *)quarantineDataURL {
NSURL *url = [self quarantineData][(__bridge NSString *)kLSQuarantineDataURLKey];
return [url absoluteString];
@@ -277,24 +324,21 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
return [self quarantineData][(__bridge NSString *)kLSQuarantineTimeStampKey];
}
- (NSUInteger)fileSize {
return self.fileData.length;
}
#pragma mark Internal Methods
- (void)parseMachHeaders {
if (self.machHeaders) return;
- (NSDictionary *)machHeaders {
if (self.cachedHeaders) return self.cachedHeaders;
// Sanity check file length
if (self.fileData.length < sizeof(struct mach_header)) {
self.machHeaders = [NSDictionary dictionary];
return;
if (self.fileSize < sizeof(struct mach_header)) {
self.cachedHeaders = [NSDictionary dictionary];
return self.cachedHeaders;
}
NSMutableDictionary *machHeaders = [NSMutableDictionary dictionary];
NSData *machHeader = [self parseSingleMachHeader:self.fileData];
NSData *machHeader = [self parseSingleMachHeader:[self safeSubdataWithRange:NSMakeRange(0,
4096)]];
if (machHeader) {
struct mach_header *mh = (struct mach_header *)[machHeader bytes];
MachHeaderWithOffset *mhwo = [[MachHeaderWithOffset alloc] initWithData:machHeader offset:0];
@@ -328,7 +372,8 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
}
}
self.machHeaders = [machHeaders copy];
self.cachedHeaders = [machHeaders copy];
return self.cachedHeaders;
}
- (NSData *)parseSingleMachHeader:(NSData *)inputData {
@@ -391,7 +436,7 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
NSData *sectData = [self safeSubdataWithRange:NSMakeRange(offset, sz_section)];
if (!sectData) return nil;
struct section_64 *sect = (struct section_64 *)[sectData bytes];
if (strncmp(sect->sectname, "__info_plist", 12) == 0 && sect->size < 2000000) {
if (sect && strncmp(sect->sectname, "__info_plist", 12) == 0 && sect->size < 2000000) {
NSData *plistData = [self safeSubdataWithRange:NSMakeRange(sect->offset, sect->size)];
if (!plistData) return nil;
NSDictionary *plist;
@@ -407,20 +452,23 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
}
///
/// Return one of the mach_header's in this file.
/// Return the first mach_header in this file.
///
- (struct mach_header *)firstMachHeader {
return (struct mach_header *)([[[[self.machHeaders allValues] firstObject] data] bytes]);
}
///
/// Wrap @c subdataWithRange: in a @@try/@@catch, returning nil on exception.
/// Useful for when the range is beyond the end of the file.
/// Extract a range of the file as an NSData, handling any exceptions.
/// Returns nil if the requested range is outside of the range of the file.
///
- (NSData *)safeSubdataWithRange:(NSRange)range {
@try {
return [self.fileData subdataWithRange:range];
if ((range.location + range.length) > self.fileSize) return nil;
[self.fileHandle seekToFileOffset:range.location];
NSData *d = [self.fileHandle readDataOfLength:range.length];
if (d.length != range.length) return nil;
return d;
}
@catch (NSException *e) {
return nil;
@@ -428,7 +476,7 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
}
///
/// Retrieve quarantine data for a file
/// Retrieve quarantine data for a file and caches the dictionary
///
- (NSDictionary *)quarantineData {
if (!self.quarantineDict && NSURLQuarantinePropertiesKey != NULL) {
@@ -459,6 +507,13 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
return nil;
}
///
/// Resolves a given path:
/// + Follows symlinks
/// + Converts relative paths to absolute
/// + If path is a directory, checks to see if that directory is a bundle and if so
/// returns the path to that bundles CFBundleExecutable.
///
- (NSString *)resolvePath:(NSString *)path {
// Convert to absolute, standardized path
path = [path stringByResolvingSymlinksInPath];

View File

@@ -46,8 +46,7 @@
/// Config ops
///
- (void)clientMode:(void (^)(santa_clientmode_t))reply;
- (void)watchdogCPUEvents:(void (^)(uint64_t))reply;
- (void)watchdogRAMEvents:(void (^)(uint64_t))reply;
- (void)watchdogInfo:(void (^)(uint64_t, uint64_t, double, double))reply;
- (void)setClientMode:(santa_clientmode_t)mode reply:(void (^)())reply;
- (void)setNextSyncInterval:(uint64_t)seconds reply:(void (^)())reply;
- (void)setSyncLastSuccess:(NSDate *)date reply:(void (^)())reply;

View File

@@ -12,19 +12,19 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#include "SantaMessage.h"
#include "SantaCachedDecision.h"
OSDefineMetaClassAndStructors(SantaMessage, OSObject);
OSDefineMetaClassAndStructors(SantaCachedDecision, OSObject);
uint64_t SantaMessage::getMicrosecs() const {
uint64_t SantaCachedDecision::getMicrosecs() const {
return microsecs_;
}
santa_action_t SantaMessage::getAction() const {
santa_action_t SantaCachedDecision::getAction() const {
return action_;
}
void SantaMessage::setAction(
void SantaCachedDecision::setAction(
const santa_action_t action, const uint64_t microsecs) {
action_ = action;
microsecs_ = microsecs;

View File

@@ -12,19 +12,19 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#ifndef SANTA__SANTA_DRIVER__SANTAMESSAGE_H
#define SANTA__SANTA_DRIVER__SANTAMESSAGE_H
#ifndef SANTA__SANTA_DRIVER__SANTACACHEDDECISION_H
#define SANTA__SANTA_DRIVER__SANTACACHEDDECISION_H
#include <libkern/c++/OSObject.h>
#include "SNTKernelCommon.h"
///
/// An OSObject wrapper around a @c santa_action_t and a time.
/// An OSObject subclass to store a @c santa_action_t and a timestamp.
/// Only OSObject subclasses can be inserted into an OSDictionary.
///
class SantaMessage : public OSObject {
OSDeclareDefaultStructors(SantaMessage)
class SantaCachedDecision : public OSObject {
OSDeclareDefaultStructors(SantaCachedDecision)
public:
// Returns the time the action was last set.
@@ -41,4 +41,4 @@ class SantaMessage : public OSObject {
uint64_t microsecs_;
};
#endif // SANTA__SANTA_DRIVER__SANTAMESSAGE_H
#endif // SANTA__SANTA_DRIVER__SANTACACHEDDECISIONWRAPPER_H

View File

@@ -29,8 +29,10 @@ bool SantaDecisionManager::init() {
dataqueue_lock_ = lck_mtx_alloc_init(sdm_lock_grp_, sdm_lock_attr_);
cached_decisions_lock_ = lck_rw_alloc_init(sdm_lock_grp_, sdm_lock_attr_);
vnode_pid_map_lock_ = lck_rw_alloc_init(sdm_lock_grp_, sdm_lock_attr_);
cached_decisions_ = OSDictionary::withCapacity(1000);
vnode_pid_map_ = OSDictionary::withCapacity(1000);
dataqueue_ = IOSharedDataQueue::withEntries(kMaxQueueEvents,
sizeof(santa_message_t));
@@ -42,14 +44,16 @@ bool SantaDecisionManager::init() {
}
void SantaDecisionManager::free() {
OSSafeReleaseNULL(dataqueue_);
OSSafeReleaseNULL(cached_decisions_);
if (cached_decisions_lock_) {
lck_rw_free(cached_decisions_lock_, sdm_lock_grp_);
cached_decisions_lock_ = nullptr;
}
if (vnode_pid_map_lock_) {
lck_rw_free(vnode_pid_map_lock_, sdm_lock_grp_);
vnode_pid_map_lock_ = nullptr;
}
if (dataqueue_lock_) {
lck_mtx_free(dataqueue_lock_, sdm_lock_grp_);
dataqueue_lock_ = nullptr;
@@ -70,6 +74,10 @@ void SantaDecisionManager::free() {
sdm_lock_grp_attr_ = nullptr;
}
OSSafeReleaseNULL(dataqueue_);
OSSafeReleaseNULL(cached_decisions_);
OSSafeReleaseNULL(vnode_pid_map_);
super::free();
}
@@ -181,7 +189,7 @@ void SantaDecisionManager::AddToCache(
}
if (decision == ACTION_REQUEST_CHECKBW) {
SantaMessage *pending = new SantaMessage();
SantaCachedDecision *pending = new SantaCachedDecision();
pending->setAction(ACTION_REQUEST_CHECKBW, 0);
lck_rw_lock_exclusive(cached_decisions_lock_);
cached_decisions_->setObject(identifier, pending);
@@ -189,8 +197,8 @@ void SantaDecisionManager::AddToCache(
pending->release(); // it was retained when added to the dictionary
} else {
lck_rw_lock_exclusive(cached_decisions_lock_);
SantaMessage *pending =
OSDynamicCast(SantaMessage, cached_decisions_->getObject(identifier));
SantaCachedDecision *pending = OSDynamicCast(
SantaCachedDecision, cached_decisions_->getObject(identifier));
if (pending) {
pending->setAction(decision, microsecs);
}
@@ -232,8 +240,8 @@ santa_action_t SantaDecisionManager::GetFromCache(const char *identifier) {
uint64_t decision_time = 0;
lck_rw_lock_shared(cached_decisions_lock_);
SantaMessage *cached_decision =
OSDynamicCast(SantaMessage, cached_decisions_->getObject(identifier));
SantaCachedDecision *cached_decision = OSDynamicCast(
SantaCachedDecision, cached_decisions_->getObject(identifier));
if (cached_decision) {
result = cached_decision->getAction();
decision_time = cached_decision->getMicrosecs();
@@ -390,6 +398,8 @@ void SantaDecisionManager::DecrementListenerInvocations() {
OSDecrementAtomic(&listener_invocations_);
}
#pragma mark Callbacks
int SantaDecisionManager::VnodeCallback(const kauth_cred_t cred,
const vfs_context_t ctx,
const vnode_t vp,
@@ -414,8 +424,19 @@ int SantaDecisionManager::VnodeCallback(const kauth_cred_t cred,
}
switch (returnedAction) {
case ACTION_RESPOND_CHECKBW_ALLOW:
case ACTION_RESPOND_CHECKBW_ALLOW: {
proc_t proc = vfs_context_proc(ctx);
if (proc) {
SantaPIDAndPPID *pidWrapper = new SantaPIDAndPPID;
pidWrapper->pid = proc_pid(proc);
pidWrapper->ppid = proc_ppid(proc);
lck_rw_lock_exclusive(vnode_pid_map_lock_);
vnode_pid_map_->setObject(vnode_str, pidWrapper);
lck_rw_unlock_exclusive(vnode_pid_map_lock_);
pidWrapper->release();
}
return KAUTH_RESULT_ALLOW;
}
case ACTION_RESPOND_CHECKBW_DENY:
*errno = EPERM;
return KAUTH_RESULT_DENY;
@@ -444,6 +465,19 @@ void SantaDecisionManager::FileOpCallback(
message->vnode_id = vnode_id;
message->action = ACTION_NOTIFY_EXEC;
strlcpy(message->path, path, sizeof(message->path));
char vnode_str[MAX_VNODE_ID_STR];
snprintf(vnode_str, MAX_VNODE_ID_STR, "%llu", vnode_id);
lck_rw_lock_shared(vnode_pid_map_lock_);
SantaPIDAndPPID *pidWrapper = OSDynamicCast(
SantaPIDAndPPID, vnode_pid_map_->getObject(vnode_str));
if (pidWrapper) {
message->pid = pidWrapper->pid;
message->ppid = pidWrapper->ppid;
}
lck_rw_unlock_shared(vnode_pid_map_lock_);
PostToQueue(message);
delete message;
return;
@@ -478,8 +512,6 @@ void SantaDecisionManager::FileOpCallback(
#undef super
#pragma mark Kauth Callbacks
extern "C" int fileop_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) {

View File

@@ -24,9 +24,10 @@
#include <sys/proc.h>
#include <sys/vnode.h>
#include "SantaMessage.h"
#include "SantaCachedDecision.h"
#include "SNTKernelCommon.h"
#include "SNTLogging.h"
#include "SantaPIDAndPPID.h"
///
/// SantaDecisionManager is responsible for intercepting Vnode execute actions
@@ -201,8 +202,10 @@ class SantaDecisionManager : public OSObject {
lck_attr_t *sdm_lock_attr_;
lck_rw_t *cached_decisions_lock_;
lck_mtx_t *dataqueue_lock_;
lck_rw_t *vnode_pid_map_lock_;
OSDictionary *cached_decisions_;
OSDictionary *vnode_pid_map_;
IOSharedDataQueue *dataqueue_;
SInt32 failed_queue_requests_;

View File

@@ -22,7 +22,6 @@
#include "SantaDecisionManager.h"
#include "SantaDriver.h"
#include "SantaMessage.h"
#include "SNTKernelCommon.h"
///

View File

@@ -0,0 +1,17 @@
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#include "SantaPIDAndPPID.h"
OSDefineMetaClassAndStructors(SantaPIDAndPPID, OSObject);

View File

@@ -0,0 +1,32 @@
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#ifndef SANTA__SANTA_DRIVER__SANTAPIDANDPPID_H
#define SANTA__SANTA_DRIVER__SANTAPIDANDPPID_H
#include <libkern/c++/OSObject.h>
///
/// An OSObject wrapper around a PID and PPID.
/// Only OSObject subclasses can be inserted into an OSDictionary.
///
class SantaPIDAndPPID : public OSObject {
OSDeclareDefaultStructors(SantaPIDAndPPID)
public:
pid_t pid;
pid_t ppid;
};
#endif // SANTA__SANTA_DRIVER__SANTAPIDANDPPID_H

View File

@@ -20,12 +20,12 @@
#import "MOLCodesignChecker.h"
#import "SNTFileInfo.h"
@interface SNTCommandBinaryInfo : NSObject<SNTCommand>
@interface SNTCommandFileInfo : NSObject<SNTCommand>
@end
@implementation SNTCommandBinaryInfo
@implementation SNTCommandFileInfo
REGISTER_COMMAND_NAME(@"binaryinfo")
REGISTER_COMMAND_NAME(@"fileinfo")
+ (BOOL)requiresRoot {
return NO;
@@ -36,13 +36,13 @@ REGISTER_COMMAND_NAME(@"binaryinfo")
}
+ (NSString *)shortHelpText {
return @"Prints information about a binary.";
return @"Prints information about a file.";
}
+ (NSString *)longHelpText {
return (@"The details provided will be the same ones Santa uses to make a decision\n"
@"about binaries. This includes SHA-256, SHA-1, code signing information and\n"
@"the type of binary.");
@"about executables. This includes SHA-256, SHA-1, code signing information and\n"
@"the type of file.");
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
@@ -60,14 +60,17 @@ REGISTER_COMMAND_NAME(@"binaryinfo")
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"YYYY/MM/dd HH:mm:ss Z";
dateFormatter.dateFormat = @"yyyy/MM/dd HH:mm:ss Z";
[self printKey:@"Path" value:fileInfo.path];
[self printKey:@"SHA-256" value:fileInfo.SHA256];
[self printKey:@"SHA-1" value:fileInfo.SHA1];
[self printKey:@"Bundle Name" value:fileInfo.bundleName];
[self printKey:@"Bundle Version" value:fileInfo.bundleVersion];
[self printKey:@"Bundle Version Str" value:fileInfo.bundleShortVersionString];
if (fileInfo.bundlePath) {
[self printKey:@"Bundle Name" value:fileInfo.bundleName];
[self printKey:@"Bundle Version" value:fileInfo.bundleVersion];
[self printKey:@"Bundle Version Str" value:fileInfo.bundleShortVersionString];
}
if (fileInfo.quarantineDataURL) {
[self printKey:@"Download Referer URL" value:fileInfo.quarantineRefererURL];
@@ -78,14 +81,15 @@ REGISTER_COMMAND_NAME(@"binaryinfo")
}
NSArray *archs = [fileInfo architectures];
if (archs) {
NSString *s = [NSString stringWithFormat:@"%@ (%@)",
fileInfo.machoType, [archs componentsJoinedByString:@", "]];
[self printKey:@"Type" value:s];
} else {
[self printKey:@"Type" value:fileInfo.machoType];
if (archs.count == 0) {
[self printKey:@"Type" value:[self humanReadableFileType:fileInfo]];
exit(0);
}
NSString *s = [NSString stringWithFormat:@"%@ (%@)",
[self humanReadableFileType:fileInfo], [archs componentsJoinedByString:@", "]];
[self printKey:@"Type" value:s];
if ([fileInfo isMissingPageZero]) {
[self printKey:@"Page Zero" value:@"__PAGEZERO segment missing/bad!"];
}
@@ -118,4 +122,14 @@ REGISTER_COMMAND_NAME(@"binaryinfo")
printf("%-21s: %s\n", [key UTF8String], [value UTF8String]);
}
+ (NSString *)humanReadableFileType:(SNTFileInfo *)fi {
if ([fi isScript]) return @"Script";
if ([fi isXARArchive]) return @"XAR Archive";
if ([fi isDylib]) return @"Dynamic Library";
if ([fi isKext]) return @"Kernel Extension";
if ([fi isFat]) return @"Fat Binary";
if ([fi isMachO]) return @"Thin Binary";
return @"Unknown";
}
@end

View File

@@ -48,6 +48,7 @@ REGISTER_COMMAND_NAME(@"status")
// Daemon status
__block NSString *clientMode;
__block uint64_t cpuEvents, ramEvents;
__block double cpuPeak, ramPeak;
dispatch_group_enter(group);
[[daemonConn remoteObjectProxy] clientMode:^(santa_clientmode_t cm) {
switch (cm) {
@@ -61,15 +62,15 @@ REGISTER_COMMAND_NAME(@"status")
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[[daemonConn remoteObjectProxy] watchdogCPUEvents:^(uint64_t events) {
cpuEvents = events;
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[[daemonConn remoteObjectProxy] watchdogRAMEvents:^(uint64_t events) {
ramEvents = events;
[[daemonConn remoteObjectProxy] watchdogInfo:^(uint64_t wd_cpuEvents, uint64_t wd_ramEvents,
double wd_cpuPeak, double wd_ramPeak) {
cpuEvents = wd_cpuEvents;
cpuPeak = wd_cpuPeak;
ramEvents = wd_ramEvents;
ramPeak = wd_ramPeak;
dispatch_group_leave(group);
}];
BOOL fileLogging = ([[SNTConfigurator configurator] fileChangesRegex] != nil);
// Kext status
@@ -97,7 +98,7 @@ REGISTER_COMMAND_NAME(@"status")
// Sync status
NSString *syncURLStr = [[[SNTConfigurator configurator] syncBaseURL] absoluteString];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"YYYY/MM/dd HH:mm:ss Z";
dateFormatter.dateFormat = @"yyyy/MM/dd HH:mm:ss Z";
NSDate *lastSyncSuccess = [[SNTConfigurator configurator] syncLastSuccess];
NSString *lastSyncSuccessStr = [dateFormatter stringFromDate:lastSyncSuccess] ?: @"Never";
BOOL syncCleanReqd = [[SNTConfigurator configurator] syncCleanRequired];
@@ -114,6 +115,8 @@ REGISTER_COMMAND_NAME(@"status")
@"file_logging": @(fileLogging),
@"watchdog_cpu_events": @(cpuEvents),
@"watchdog_ram_events": @(ramEvents),
@"watchdog_cpu_peak": @(cpuPeak),
@"watchdog_ram_peak": @(ramPeak),
},
@"kernel": @{
@"cache_count": @(cacheCount),
@@ -138,8 +141,8 @@ REGISTER_COMMAND_NAME(@"status")
printf(">>> Daemon Info\n");
printf(" %-22s | %s\n", "Mode", [clientMode UTF8String]);
printf(" %-22s | %s\n", "File Logging", (fileLogging ? "Yes" : "No"));
printf(" %-22s | %lld\n", "Watchdog CPU Events", cpuEvents);
printf(" %-22s | %lld\n", "Watchdog RAM Events", ramEvents);
printf(" %-22s | %lld (Peak: %.2f%%)\n", "Watchdog CPU Events", cpuEvents, cpuPeak);
printf(" %-22s | %lld (Peak: %.2fMB)\n", "Watchdog RAM Events", ramEvents, ramPeak);
printf(">>> Kernel Info\n");
printf(" %-22s | %lld\n", "Kernel cache count", cacheCount);
printf(">>> Database Info\n");

View File

@@ -49,6 +49,7 @@ extern NSString * const kDecisionBlockBinary;
extern NSString * const kDecisionBlockCertificate;
extern NSString * const kDecisionBlockScope;
extern NSString * const kDecisionUnknown;
extern NSString * const kDecisionRelatedBinary;
extern NSString * const kLoggedInUsers;
extern NSString * const kCurrentSessions;
extern NSString * const kFileBundleID;

View File

@@ -51,6 +51,7 @@ NSString * const kDecisionBlockBinary = @"BLOCK_BINARY";
NSString * const kDecisionBlockCertificate = @"BLOCK_CERTIFICATE";
NSString * const kDecisionBlockScope = @"BLOCK_SCOPE";
NSString * const kDecisionUnknown = @"UNKNOWN";
NSString * const kDecisionRelatedBinary = @"RELATED_BINARY";
NSString * const kLoggedInUsers = @"logged_in_users";
NSString * const kCurrentSessions = @"current_sessions";
NSString * const kFileBundleID = @"file_bundle_id";

View File

@@ -18,8 +18,10 @@
#import "NSData+Zlib.h"
#import "MOLCertificate.h"
#import "MOLCodesignChecker.h"
#import "SNTCommandSyncConstants.h"
#import "SNTCommandSyncState.h"
#import "SNTFileInfo.h"
#import "SNTStoredEvent.h"
#import "SNTXPCConnection.h"
#import "SNTXPCControlInterface.h"
@@ -82,6 +84,11 @@
[uploadEvents addObject:[self dictionaryForEvent:event]];
[eventIds addObject:event.idx];
if (event.fileBundleID) {
NSArray *relatedBinaries = [self findRelatedBinaries:event];
[uploadEvents addObjectsFromArray:relatedBinaries];
}
if (eventIds.count >= batchSize) break;
}
@@ -115,6 +122,7 @@
LOGE(@"HTTP Response: %ld %@",
statusCode,
[[NSHTTPURLResponse localizedStringForStatusCode:statusCode] capitalizedString]);
LOGD(@"%@", error);
handler(NO);
} else {
LOGI(@"Uploaded %lu events", eventIds.count);
@@ -162,6 +170,7 @@
ADDKEY(newEvent, kDecision, kDecisionBlockCertificate);
break;
case EVENTSTATE_BLOCK_SCOPE: ADDKEY(newEvent, kDecision, kDecisionBlockScope); break;
case EVENTSTATE_RELATED_BINARY: ADDKEY(newEvent, kDecision, kDecisionRelatedBinary); break;
default: ADDKEY(newEvent, kDecision, kDecisionUnknown);
}
@@ -199,4 +208,68 @@
#undef ADDKEY
}
+ (NSArray *)findRelatedBinaries:(SNTStoredEvent *)event {
// Prevent processing the same bundle twice.
static NSMutableDictionary *previouslyProcessedBundles;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
previouslyProcessedBundles = [NSMutableDictionary dictionary];
});
if (previouslyProcessedBundles[event.fileBundleID]) return nil;
previouslyProcessedBundles[event.fileBundleID] = @YES;
NSMutableArray *relatedEvents = [NSMutableArray array];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block BOOL shouldCancel = NO;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
SNTFileInfo *originalFile = [[SNTFileInfo alloc] initWithPath:event.filePath];
NSString *bundlePath = originalFile.bundlePath;
originalFile = nil; // release originalFile early.
NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:bundlePath];
NSString *file;
while (file = [dirEnum nextObject]) {
@autoreleasepool {
if (shouldCancel) break;
if ([dirEnum fileAttributes][NSFileType] != NSFileTypeRegular) continue;
file = [bundlePath stringByAppendingPathComponent:file];
// Don't record the binary that triggered this event as a related binary.
if ([file isEqual:event.filePath]) continue;
SNTFileInfo *fi = [[SNTFileInfo alloc] initWithPath:file];
if (fi.isExecutable) {
SNTStoredEvent *se = [[SNTStoredEvent alloc] init];
se.filePath = fi.path;
se.fileSHA256 = fi.SHA256;
se.decision = EVENTSTATE_RELATED_BINARY;
se.fileBundleID = event.fileBundleID;
se.fileBundleName = event.fileBundleName;
se.fileBundleVersion = event.fileBundleVersion;
se.fileBundleVersionString = event.fileBundleVersionString;
MOLCodesignChecker *cs = [[MOLCodesignChecker alloc] initWithBinaryPath:se.filePath];
se.signingChain = cs.certificates;
[relatedEvents addObject:[self dictionaryForEvent:se]];
}
}
}
dispatch_semaphore_signal(sema);
});
// Give the search up to 5s per event to run.
// This might need tweaking if it seems to slow down syncing or misses too much to be useful.
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5))) {
shouldCancel = YES;
LOGD(@"Timed out while searching for related events. Bundle ID: %@", event.fileBundleID);
}
return relatedEvents;
}
@end

View File

@@ -48,6 +48,7 @@
LOGE(@"HTTP Response: %ld %@",
statusCode,
[[NSHTTPURLResponse localizedStringForStatusCode:statusCode] capitalizedString]);
LOGD(@"%@", error);
handler(NO);
} else {
LOGI(@"Uploaded %lu logs", [logsToUpload count]);

View File

@@ -40,6 +40,7 @@
LOGE(@"HTTP Response: %ld %@",
statusCode,
[[NSHTTPURLResponse localizedStringForStatusCode:statusCode] capitalizedString]);
LOGD(@"%@", error);
handler(NO);
} else {
NSDictionary *r = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

View File

@@ -72,6 +72,7 @@
LOGE(@"HTTP Response: %ld %@",
statusCode,
[[NSHTTPURLResponse localizedStringForStatusCode:statusCode] capitalizedString]);
LOGD(@"%@", error);
handler(NO);
} else {
NSDictionary *r = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

View File

@@ -65,6 +65,7 @@
LOGE(@"HTTP Response: %ld %@",
statusCode,
[[NSHTTPURLResponse localizedStringForStatusCode:statusCode] capitalizedString]);
LOGD(@"%@", error);
handler(NO);
} else {
NSDictionary *resp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

View File

@@ -112,10 +112,15 @@
- (void)run {
LOGI(@"Connected to driver, activating.");
// Create a concurrent queue to put requests on, then set its priority to high.
dispatch_queue_t q =
dispatch_queue_create("com.google.santad.driver_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_set_target_queue(q, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
// Create the queues used for execution requests and logging.
dispatch_queue_t exec_queue = dispatch_queue_create(
"com.google.santad.execution_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_set_target_queue(exec_queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
dispatch_queue_t log_queue = dispatch_queue_create(
"com.google.santad.log_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_set_target_queue(
log_queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));
[self.driverManager listenWithBlock:^(santa_message_t message) {
@autoreleasepool {
@@ -129,7 +134,7 @@
case ACTION_NOTIFY_LINK:
case ACTION_NOTIFY_RENAME:
case ACTION_NOTIFY_WRITE: {
dispatch_async(q, ^{
dispatch_async(log_queue, ^{
NSRegularExpression *re = [[SNTConfigurator configurator] fileChangesRegex];
NSString *path = @(message.path);
if ([re numberOfMatchesInString:path options:0 range:NSMakeRange(0, path.length)]) {
@@ -139,13 +144,13 @@
break;
}
case ACTION_NOTIFY_EXEC: {
dispatch_async(q, ^{
dispatch_async(log_queue, ^{
[self.eventLog logAllowedExecution:message];
});
break;
}
case ACTION_REQUEST_CHECKBW: {
dispatch_async(q, ^{
dispatch_async(exec_queue, ^{
[self.execController validateBinaryWithMessage:message];
});
break;

View File

@@ -26,6 +26,8 @@
// Globals used by the santad watchdog thread
uint64_t watchdogCPUEvents = 0;
uint64_t watchdogRAMEvents = 0;
double watchdogCPUPeak = 0;
double watchdogRAMPeak = 0;
@interface SNTDaemonControlController ()
@property dispatch_source_t syncTimer;
@@ -172,12 +174,8 @@ uint64_t watchdogRAMEvents = 0;
reply();
}
- (void)watchdogCPUEvents:(void (^)(uint64_t))reply {
reply(watchdogCPUEvents);
}
- (void)watchdogRAMEvents:(void (^)(uint64_t))reply {
reply(watchdogRAMEvents);
- (void)watchdogInfo:(void (^)(uint64_t, uint64_t, double, double))reply {
reply(watchdogCPUEvents, watchdogRAMEvents, watchdogCPUPeak, watchdogRAMPeak);
}
@end

View File

@@ -14,7 +14,9 @@
#import "SNTEventLog.h"
#include <grp.h>
#include <libproc.h>
#include <pwd.h>
#include <sys/sysctl.h>
#import "SNTCachedDecision.h"
@@ -88,9 +90,17 @@
if (proc_pidpath(message.pid, ppath, PATH_MAX) < 1) {
strncpy(ppath, "(null)", 6);
}
outStr =
[outStr stringByAppendingFormat:@"|pid=%d|ppid=%d|process=%s|processpath=%s|uid=%d|gid=%d",
message.pid, message.ppid, message.pname, ppath, message.uid, message.gid];
NSString *user, *group;
struct passwd *pw = getpwuid(message.uid);
if (pw) user = @(pw->pw_name);
struct group *gr = getgrgid(message.gid);
if (gr) group = @(gr->gr_name);
outStr = [outStr stringByAppendingFormat:(@"|pid=%d|ppid=%d|process=%s|processpath=%s|"
@"uid=%d|user=%@|gid=%d|group=%@"),
message.pid, message.ppid, message.pname, ppath,
message.uid, user, message.gid, group];
if (sha256) {
outStr = [outStr stringByAppendingFormat:@"|sha256=%@", sha256];
}
@@ -145,8 +155,14 @@
cd.certSHA256, [self sanitizeString:cd.certCommonName]];
}
outLog = [outLog stringByAppendingFormat:@"|pid=%d|ppid=%d|uid=%d|gid=%d",
message.pid, message.ppid, message.uid, message.gid];
NSString *user, *group;
struct passwd *pw = getpwuid(message.uid);
if (pw) user = @(pw->pw_name);
struct group *gr = getgrgid(message.gid);
if (gr) group = @(gr->gr_name);
outLog = [outLog stringByAppendingFormat:@"|pid=%d|ppid=%d|uid=%d|user=%@|gid=%d|group=%@",
message.pid, message.ppid, message.uid, user, message.gid, group];
LOGI(@"%@", outLog);
}
@@ -205,7 +221,7 @@
NSMutableArray *args = [NSMutableArray arrayWithCapacity:argc];
for (int i = 0; i < argc; i++) {
NSString *arg = @(cp);
[args addObject:arg];
if (arg) [args addObject:arg];
// Move the pointer past this string and the terminator at the end.
cp += strlen(cp) + 1;

View File

@@ -32,6 +32,40 @@
newVersion = 1;
}
if (version < 2) {
// Clean-up: Find events where the bundle details might not be strings and update them.
FMResultSet *rs = [db executeQuery:@"SELECT * FROM events"];
while ([rs next]) {
SNTStoredEvent *se = [self eventFromResultSet:rs];
if (!se) continue;
Class NSStringClass = [NSString class];
if ([se.fileBundleID class] != NSStringClass) {
se.fileBundleID = [se.fileBundleID description];
}
if ([se.fileBundleName class] != NSStringClass) {
se.fileBundleName = [se.fileBundleName description];
}
if ([se.fileBundleVersion class] != NSStringClass) {
se.fileBundleVersion = [se.fileBundleVersion description];
}
if ([se.fileBundleVersionString class] != NSStringClass) {
se.fileBundleVersionString = [se.fileBundleVersionString description];
}
NSData *eventData;
NSNumber *idx = [rs objectForColumnName:@"idx"];
@try {
eventData = [NSKeyedArchiver archivedDataWithRootObject:se];
[db executeUpdate:@"UPDATE events SET eventdata=? WHERE idx=?", eventData, idx];
} @catch (NSException *exception) {
[db executeUpdate:@"DELETE FROM events WHERE idx=?", idx];
}
}
[rs close];
newVersion = 2;
}
return newVersion;
}

View File

@@ -53,7 +53,6 @@
_notifierConnection = notifier;
_eventLog = eventLog;
// Workaround for xpcproxy/libsecurity bug on Yosemite
// This establishes the XPC connection between libsecurity and syspolicyd.
// Not doing this causes a deadlock as establishing this link goes through xpcproxy.
(void)[[MOLCodesignChecker alloc] initWithSelf];
@@ -168,7 +167,6 @@
}
struct passwd *user = getpwuid(message.uid);
endpwent();
if (user) {
se.executingUser = @(user->pw_name);
}
@@ -285,7 +283,7 @@
while ((nxt = getutxent())) {
if (nxt->ut_type != USER_PROCESS) continue;
NSString *userName = [NSString stringWithUTF8String:nxt->ut_user];
NSString *userName = @(nxt->ut_user);
NSString *sessionName;
if (strnlen(nxt->ut_host, 1) > 0) {

View File

@@ -21,10 +21,12 @@
extern uint64_t watchdogCPUEvents;
extern uint64_t watchdogRAMEvents;
extern double watchdogCPUPeak;
extern double watchdogRAMPeak;
/// Converts a timeval struct to double, converting the microseconds value to seconds.
static inline double timeval_to_double(struct timeval tv) {
return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
static inline double timeval_to_double(time_value_t tv) {
return (double)tv.seconds + (double)tv.microseconds / 1000000.0;
}
/// The watchdog thread function, used to monitor santad CPU/RAM usage and print a warning
@@ -45,36 +47,39 @@ void *watchdogThreadFunction(__unused void *idata) {
double prevTotalTime = 0.0;
double prevRamUseMB = 0.0;
struct rusage usage;
struct mach_task_basic_info taskInfo;
mach_msg_type_number_t taskInfoCount = MACH_TASK_BASIC_INFO_COUNT;
while(true) {
@autoreleasepool {
sleep(timeInterval);
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
(task_info_t)&taskInfo, &taskInfoCount) == KERN_SUCCESS) {
// CPU
double totalTime = (timeval_to_double(taskInfo.user_time) +
timeval_to_double(taskInfo.system_time));
double percentage = (((totalTime - prevTotalTime) / (double)timeInterval) * 100.0);
prevTotalTime = totalTime;
// CPU
getrusage(RUSAGE_SELF, &usage);
double totalTime = timeval_to_double(usage.ru_utime) + timeval_to_double(usage.ru_stime);
double percentage = (((totalTime - prevTotalTime) / (double)timeInterval) * 100.0);
prevTotalTime = totalTime;
if (percentage > cpuWarnThreshold) {
LOGW(@"Watchdog: potentially high CPU use, ~%.2f%% over last %d seconds.",
percentage, timeInterval);
watchdogCPUEvents++;
}
if (percentage > cpuWarnThreshold) {
LOGW(@"Watchdog: potentially high CPU use, ~%.2f%% over last %d seconds.",
percentage, timeInterval);
watchdogCPUEvents++;
}
if (percentage > watchdogCPUPeak) watchdogCPUPeak = percentage;
// RAM
if (KERN_SUCCESS == task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
(task_info_t)&taskInfo, &taskInfoCount)) {
double ramUseMB = (double) taskInfo.resident_size / 1024 / 1024;
// RAM
double ramUseMB = (double)taskInfo.resident_size / 1024 / 1024;
if (ramUseMB > memWarnThreshold && ramUseMB > prevRamUseMB) {
LOGW(@"Watchdog: potentially high RAM use, RSS is %.2fMB.", ramUseMB);
watchdogRAMEvents++;
}
prevRamUseMB = ramUseMB;
if (ramUseMB > watchdogRAMPeak) watchdogRAMPeak = ramUseMB;
}
sleep(timeInterval);
}
}
return NULL;

View File

@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.google.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>