Compare commits

..

48 Commits
0.8.1 ... 0.8.3

Author SHA1 Message Date
Russell Hancox
aef3d57dcf SantaGUI: Ensure configuration is loaded before first message arrives, let window be moved, close window properly when opening event URL 2015-03-30 18:45:06 -04:00
Russell Hancox
cfb38068f8 santa-driver: DisconnectClient should return straight away if client is not properly connected 2015-03-30 18:37:36 -04:00
Russell Hancox
ca19d9fde7 SNTConfigurator: Do initial file monitoring async 2015-03-30 18:37:18 -04:00
Russell Hancox
e19aab36bd SantaGUI: Close window when opening web pages 2015-03-27 16:56:13 -04:00
Russell Hancox
111540f0a8 LogicTests: Update some Stub calls to Expect 2015-03-27 15:39:13 -04:00
Russell Hancox
88897477b6 santad: Now that SNTConfigurator auto-reloads, stop tracking clientMode separately. Also reload logAllDecisions if req'd. 2015-03-27 15:38:55 -04:00
Russell Hancox
a9d6e42d5a SNTConfigurator: Have configuration auto-reload if file on disk changes 2015-03-27 15:38:10 -04:00
Russell Hancox
8b5720b291 santad: Update comments in DriverManager 2015-03-27 15:37:08 -04:00
Russell Hancox
2d9f392efc santa-driver: Ensure fSDM and fDataQueue are NULL'd ASAP. 2015-03-27 15:36:24 -04:00
Russell Hancox
76844eb77d santa-driver: lock data queue mutex when retaining/releasing queue 2015-03-27 15:35:50 -04:00
Russell Hancox
2db996f8e0 SantaGUI: Add configurable About Window and Event Detail buttons 2015-03-27 15:35:16 -04:00
Russell Hancox
6c27ac60a1 SNTConfigurator: if MachineID hasn't been overridden get one from IOKit 2015-03-26 15:08:26 -04:00
Russell Hancox
d4c4b26c3b santactl/sync: Fix MachineOwnerPlist* config methods, don't crash if machine owner missing 2015-03-26 08:24:53 -04:00
Russell Hancox
50614f589c santactl/sync: Update Rule download API 2015-03-25 17:17:41 -04:00
Russell Hancox
0292d4e956 GUI: Handle missing custom message in event notifications 2015-03-16 17:29:27 -04:00
Russell Hancox
4e1e4cde3b santactl/sync: Fix broken Log Upload, re-add gzip compression 2015-03-16 17:05:49 -04:00
Russell Hancox
c86f0e7c80 Project: unload kext using bundle ID 2015-03-16 15:09:38 -04:00
Russell Hancox
77b8edda79 Project: enable 'deep' static analysis for all builds except for LogicTests and KernelTests 2015-03-16 15:04:18 -04:00
Russell Hancox
f3d098c521 Project: Add LogicTests scheme that can be used for logic tests without building all binaries 2015-03-16 15:03:46 -04:00
Russell Hancox
0afe465ac5 santactl: Rename machineIDOverride to machineID 2015-03-13 18:18:09 -04:00
Russell Hancox
472558a03c santad: Add LogAllEvents option 2015-03-13 18:17:09 -04:00
Russell Hancox
dfef7d8567 SantaGUI: Fix broken predicate for pending notifications 2015-03-13 17:33:18 -04:00
Russell Hancox
925903e07d SantaGUI: Move publisher certs button, make publisher info autosize width 2015-03-13 17:29:31 -04:00
Russell Hancox
a43c0ee295 SantaGUI: swap publisher/sha256 fields in message window 2015-03-13 16:57:25 -04:00
Russell Hancox
1e82b5abc6 Missed some newlines in printf statements 2015-03-13 16:56:38 -04:00
Russell Hancox
7502dbdec6 Project: Enable NDEBUG for FMDB in release builds. 2015-03-13 15:35:21 -04:00
Russell Hancox
217ad25531 santactl: move more commands from LOG* to printf 2015-03-13 12:48:49 -04:00
Russell Hancox
7c3b533679 santactl: Update help strings 2015-03-13 12:47:28 -04:00
Russell Hancox
2c4ba45988 santa-driver: Move from IO*Lock to lck_* 2015-03-12 14:34:52 -04:00
Russell Hancox
26ee0a68d1 santactl: Separate out version info from status, move user-only commands from LOG* to printf 2015-03-12 14:31:49 -04:00
Russell Hancox
27eb2e9cff santactl: Remove old todo about establishing connection 2015-03-11 21:42:15 -04:00
Russell Hancox
9431d954b5 SNTXPCConnection: invalidate connection if verification doesn't complete 2015-03-11 21:41:53 -04:00
Russell Hancox
1a2d8b55f8 SNTSystemInfo: NSHost is awful, use gethostname() instead 2015-03-11 21:24:56 -04:00
Russell Hancox
d27a26ca50 santad: Make driver-waiting an exponential backoff up to 16s 2015-03-11 19:14:41 -04:00
Russell Hancox
56d4a6b9fb santa-driver: Change when we consider the client connected to avoid getting into a state where events are being held but no memory descriptor is in place yet. 2015-03-10 17:40:03 -04:00
Russell Hancox
28a94cd56a santa-driver: each error state is already logged, don't log again 2015-03-10 17:39:29 -04:00
Russell Hancox
4344fc3d7d santa-driver: Remove process listener, it doesn't do anything useful and stops Hopper from working 2015-03-09 18:38:22 -04:00
Russell Hancox
40431d835e SNTStoredEvent: pid and ppid need to be encoded/decoded to be included in database/uploads 2015-03-09 12:19:26 -04:00
Russell Hancox
942804c478 santa-driver: Fix typo 2015-03-09 11:44:09 -04:00
Russell Hancox
d109aae6ef santad/santactl: include pid and ppid in event upload 2015-03-09 09:52:56 -04:00
Russell Hancox
b89040c37a santactl/sync: Add ability to refuse redirects 2015-03-06 17:41:31 -05:00
Russell Hancox
63aefb4654 santa-driver: increase max queue events to 256 2015-03-06 12:00:48 -05:00
Russell Hancox
1c92e968e3 SNTAuthenticatingURLSession: remove unnecessary import 2015-03-06 12:00:33 -05:00
Russell Hancox
c1b7f9ae63 SNTAuthenticatingURLSession: fix potential crash where client identity
is released before NSURLCredential is created
2015-03-05 13:58:31 -05:00
Russell Hancox
0507bc83d2 SNTCertificate: comment updats 2015-03-05 12:04:19 -05:00
Russell Hancox
7028c24425 Add missing copyright header from SNTDERDecoder.m 2015-03-05 12:03:55 -05:00
Russell Hancox
6ede057521 Update README.md 2015-02-04 10:26:12 -05:00
Russell Hancox
6f2ccca60a Tests: Add to SNTDERDecoderTest and SNTCertificateTest 2015-02-03 22:48:04 -05:00
50 changed files with 1041 additions and 470 deletions

12
Podfile
View File

@@ -4,6 +4,18 @@ inhibit_all_warnings!
target :santad do
pod 'FMDB'
post_install do |rep|
rep.project.targets.each do |target|
target.build_configurations.each do |config|
if config.name != 'Release' then
break
end
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ''
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] <<= "NDEBUG=1"
end
end
end
end
target :LogicTests do

View File

@@ -51,16 +51,9 @@ Known Issues
Santa is not yet a 1.0 and we have some known issues to be aware of:
* Potential race-condition: we currently have a single TODO in the kext code to
investigate a potential race condition where a binary is executed and then very
quickly modified between the kext getting the SHA-1 and the decision being made.
* Kext communication security: the kext will only accept a connection from a
single client at a time and said client must be running as root. We haven't yet
found a good way to ensure the kext only accepts connections from a valid client,
short of hardcoding the SHA-1 in the kext. This shouldn't present a huge problem
as the daemon is loaded on boot-up by launchd, so any later attempts to connect
will be blocked.
found a good way to ensure the kext only accepts connections from a valid client.
* Database protection: the SQLite database is installed with permissions so that
only the root user can read/write it. We're considering approaches to secure

View File

@@ -5,8 +5,8 @@ DEFAULT_SCHEME = 'All'
OUTPUT_PATH = 'Build'
DIST_PATH = 'Dist'
BINARIES = ['Santa.app', 'santa-driver.kext', 'santad', 'santactl']
XCTOOL_DEFAULTS = "-workspace #{WORKSPACE} -scheme #{DEFAULT_SCHEME}"
XCODE_DEFAULTS = "-workspace #{WORKSPACE} -scheme #{DEFAULT_SCHEME} -derivedDataPath #{OUTPUT_PATH} -parallelizeTargets"
XCTOOL_DEFAULTS = "-workspace #{WORKSPACE}"
XCODE_DEFAULTS = "-workspace #{WORKSPACE} -derivedDataPath #{OUTPUT_PATH} -parallelizeTargets"
task :default do
system("rake -sT")
@@ -61,7 +61,7 @@ end
desc "Clean"
task :clean => :init do
puts "Cleaning"
system "xcodebuild #{XCODE_DEFAULTS} clean"
system "xcodebuild #{XCODE_DEFAULTS} -scheme All clean"
FileUtils.rm_rf(OUTPUT_PATH)
FileUtils.rm_rf(DIST_PATH)
end
@@ -82,9 +82,9 @@ namespace :build do
config = args[:configuration]
puts "Building with configuration: #{config}"
if xctool_available
system "xctool #{XCTOOL_DEFAULTS} -configuration #{config} build"
system "xctool #{XCTOOL_DEFAULTS} -scheme All -configuration #{config} build"
else
system "xcodebuild #{XCODE_DEFAULTS} -configuration #{config} build"
system "xcodebuild #{XCODE_DEFAULTS} -scheme All -configuration #{config} build"
end
end
end
@@ -146,9 +146,9 @@ namespace :tests do
task :logic => [:init] do
puts "Running logic tests"
if xctool_available
system "xctool #{XCTOOL_DEFAULTS} test"
system "xctool #{XCTOOL_DEFAULTS} -scheme LogicTests test"
else
system "xcodebuild #{XCODE_DEFAULTS} test"
system "xcodebuild #{XCODE_DEFAULTS} -scheme LogicTests test"
end
end
@@ -178,7 +178,7 @@ end
task :unload_kext do
puts "Unloading kernel extension"
system "sudo kextunload /santa-driver.kext 2>/dev/null"
system "sudo kextunload -b com.google.santa-driver 2>/dev/null"
end
task :unload_gui do

View File

@@ -42,6 +42,7 @@
0D1B477119A53419008CADD3 /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0D1B476F19A53419008CADD3 /* AboutWindow.xib */; };
0D20710E1A7C4A86008B0A9A /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
0D28D53819D9F5910015C5EB /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; };
0D2CD4611A81C7B100C9C910 /* dn.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0D2CD4601A81C7B100C9C910 /* dn.plist */; };
0D31DF4718D254B3002B300D /* SNTCodesignChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D59C0E317710E6000748EBF /* SNTCodesignChecker.m */; };
0D35BD9F18FD71CE00921A21 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D9A7F3E1759330500035EB5 /* Foundation.framework */; };
0D35BDA218FD71CE00921A21 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDA118FD71CE00921A21 /* main.m */; };
@@ -96,6 +97,10 @@
0D7FFD4B1A017D4B00F34435 /* SNTDERDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FFD4A1A017D4B00F34435 /* SNTDERDecoder.m */; };
0D827E6519DF392E006EC811 /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; };
0D827E6719DF3C74006EC811 /* SNTCommandStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D827E6619DF3C74006EC811 /* SNTCommandStatus.m */; };
0D8868091AC48A1100B86659 /* SNTSystemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B419D1D98A00955F08 /* SNTSystemInfo.m */; };
0D88680A1AC48A1200B86659 /* SNTSystemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B419D1D98A00955F08 /* SNTSystemInfo.m */; };
0D88680C1AC48A1400B86659 /* SNTSystemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B419D1D98A00955F08 /* SNTSystemInfo.m */; };
0D88680D1AC48A5D00B86659 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D3AFBF718FB4C870087BCEE /* IOKit.framework */; };
0D8C200C180F359A00CE2BF8 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D8C200B180F359A00CE2BF8 /* Security.framework */; };
0D8E18CD19107B56000F89B8 /* SNTDaemonControlController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D8E18CC19107B56000F89B8 /* SNTDaemonControlController.m */; };
0D9A7F331759144800035EB5 /* SantaDriver.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0D9A7F311759144800035EB5 /* SantaDriver.cc */; };
@@ -107,6 +112,7 @@
0DA73C9F1934F8100056D7C4 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; };
0DA73CA11934F8100056D7C4 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; };
0DA73CA21934F88D0056D7C4 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; };
0DB390991AB1E11400614002 /* SNTCommandVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DB390981AB1E11400614002 /* SNTCommandVersion.m */; };
0DB8ACC1185662DC00FEF9C7 /* SNTApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */; };
0DC5D86D191AED220078A5C0 /* SNTRuleTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */; };
0DC5D86E191AED220078A5C0 /* SNTRuleTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */; };
@@ -141,6 +147,8 @@
0DE50F6C19130358007B2B0C /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
0DE50F6E191304E0007B2B0C /* SNTRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE50F671912716A007B2B0C /* SNTRule.m */; };
0DE6788D1784A8C2007A9E52 /* SNTExecutionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6788C1784A8C2007A9E52 /* SNTExecutionController.m */; };
0DF395641AB76A7900CBC520 /* NSData+Zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DF395631AB76A7900CBC520 /* NSData+Zlib.m */; };
0DF395661AB76ABC00CBC520 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DF395651AB76ABC00CBC520 /* libz.dylib */; };
4092327A1A51B66400A04527 /* SNTCommandRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 409232791A51B65D00A04527 /* SNTCommandRule.m */; };
8BFD9B39112F4D16B3D0EFFB /* libPods-LogicTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 752301D17AA44BDE8B6D0541 /* libPods-LogicTests.a */; };
E86AE075D7F24FB88FB627C5 /* libPods-santad.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A84545E322F475FA0B505D5 /* libPods-santad.a */; };
@@ -213,6 +221,7 @@
0D28E5E119269B3600280F87 /* SNTLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTLogging.h; sourceTree = "<group>"; };
0D28E5E31926AFE400280F87 /* SNTKernelCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTKernelCommon.h; sourceTree = "<group>"; };
0D28E5E41926B55600280F87 /* santactl-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "santactl-Info.plist"; sourceTree = "<group>"; };
0D2CD4601A81C7B100C9C910 /* dn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = dn.plist; sourceTree = "<group>"; };
0D35BD9E18FD71CE00921A21 /* santactl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = santactl; sourceTree = BUILT_PRODUCTS_DIR; };
0D35BDA118FD71CE00921A21 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
0D35BDA418FD71CE00921A21 /* santactl-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "santactl-Prefix.pch"; sourceTree = "<group>"; };
@@ -286,6 +295,7 @@
0D9A7F411759330500035EB5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = main.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
0DA73C9E1934F8100056D7C4 /* SNTLogging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTLogging.m; sourceTree = "<group>"; };
0DB2B92318085753001C01D9 /* santad-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "santad-Prefix.pch"; sourceTree = "<group>"; };
0DB390981AB1E11400614002 /* SNTCommandVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SNTCommandVersion.m; path = version/SNTCommandVersion.m; sourceTree = "<group>"; };
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>"; };
@@ -315,6 +325,9 @@
0DE50F671912716A007B2B0C /* SNTRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTRule.m; sourceTree = "<group>"; };
0DE6788B1784A8C2007A9E52 /* SNTExecutionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTExecutionController.h; sourceTree = "<group>"; };
0DE6788C1784A8C2007A9E52 /* SNTExecutionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SNTExecutionController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
0DF395621AB76A7900CBC520 /* NSData+Zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Zlib.h"; sourceTree = "<group>"; };
0DF395631AB76A7900CBC520 /* NSData+Zlib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Zlib.m"; sourceTree = "<group>"; };
0DF395651AB76ABC00CBC520 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
13A4FE400F3857C0F5831498 /* Pods-LogicTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LogicTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LogicTests/Pods-LogicTests.debug.xcconfig"; sourceTree = "<group>"; };
409232791A51B65D00A04527 /* SNTCommandRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SNTCommandRule.m; path = rule/SNTCommandRule.m; sourceTree = "<group>"; };
627BB4EC9917DC20E89D718C /* Pods-santad.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad.debug.xcconfig"; path = "Pods/Target Support Files/Pods-santad/Pods-santad.debug.xcconfig"; sourceTree = "<group>"; };
@@ -347,6 +360,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0DF395661AB76ABC00CBC520 /* libz.dylib in Frameworks */,
0DE4C8A118FEF28200466D04 /* Security.framework in Frameworks */,
0D35BDBD18FDA23600921A21 /* IOKit.framework in Frameworks */,
0D35BD9F18FD71CE00921A21 /* Foundation.framework in Frameworks */,
@@ -357,6 +371,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0D88680D1AC48A5D00B86659 /* IOKit.framework in Frameworks */,
0D6F12D819EC8822006B218E /* SecurityInterface.framework in Frameworks */,
0D8C200C180F359A00CE2BF8 /* Security.framework in Frameworks */,
0D385DB8180DE4A900418BC6 /* Cocoa.framework in Frameworks */,
@@ -403,6 +418,7 @@
0D260DB018B68E12002A0B55 /* Resources */ = {
isa = PBXGroup;
children = (
0D2CD4601A81C7B100C9C910 /* dn.plist */,
0D6FDC8618C6913D0044685C /* apple.pem */,
0D6FDC8218C68D7E0044685C /* GIAG2.crt */,
0D6FDC8418C68E500044685C /* GIAG2.pem */,
@@ -416,14 +432,15 @@
0D35BDA018FD71CE00921A21 /* santactl */ = {
isa = PBXGroup;
children = (
409232751A51914400A04527 /* rule */,
0D35BDA118FD71CE00921A21 /* main.m */,
0D35BDAA18FD7CFD00921A21 /* SNTCommandController.h */,
0D35BDAB18FD7CFD00921A21 /* SNTCommandController.m */,
0DCD5FBC1909D4FD006B445C /* binaryinfo */,
0DE4C8A318FF3AFA00466D04 /* flushcache */,
409232751A51914400A04527 /* rule */,
0D827E6819DF4F3F006EC811 /* status */,
0D35BDB618FD84FC00921A21 /* sync */,
0DB390971AB1E0F200614002 /* version */,
0D35BDA318FD71CE00921A21 /* Resources */,
);
name = santactl;
@@ -442,6 +459,8 @@
0D35BDB618FD84FC00921A21 /* sync */ = {
isa = PBXGroup;
children = (
0DF395621AB76A7900CBC520 /* NSData+Zlib.h */,
0DF395631AB76A7900CBC520 /* NSData+Zlib.m */,
0DCD6060191188B1006B445C /* SNTAuthenticatingURLSession.h */,
0DCD6061191188B1006B445C /* SNTAuthenticatingURLSession.m */,
0D35BDB418FD84F600921A21 /* SNTCommandSync.m */,
@@ -552,6 +571,7 @@
0D91BCB6174E8A7E00131A7D /* Frameworks */ = {
isa = PBXGroup;
children = (
0DF395651AB76ABC00CBC520 /* libz.dylib */,
0DCD5F771909C659006B445C /* SecurityInterface.framework */,
0D3AFBF718FB4C870087BCEE /* IOKit.framework */,
0D8C200B180F359A00CE2BF8 /* Security.framework */,
@@ -658,6 +678,14 @@
name = DataLayer;
sourceTree = "<group>";
};
0DB390971AB1E0F200614002 /* version */ = {
isa = PBXGroup;
children = (
0DB390981AB1E11400614002 /* SNTCommandVersion.m */,
);
name = version;
sourceTree = "<group>";
};
0DCD5FBC1909D4FD006B445C /* binaryinfo */ = {
isa = PBXGroup;
children = (
@@ -863,6 +891,7 @@
0D6FDC8518C68E500044685C /* GIAG2.pem in Resources */,
0D6FDC8318C68D7E0044685C /* GIAG2.crt in Resources */,
0D6F12DA19EDE51E006B218E /* tubitak.crt in Resources */,
0D2CD4611A81C7B100C9C910 /* dn.plist in Resources */,
0D6FDC8718C6913D0044685C /* apple.pem in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1048,6 +1077,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D88680C1AC48A1400B86659 /* SNTSystemInfo.m in Sources */,
0D63DD5E1906FCB400D346C4 /* SNTDatabaseController.m in Sources */,
0D3AFBF018FB4C6C0087BCEE /* SNTDriverManager.m in Sources */,
0DCD6044190ACCB8006B445C /* SNTFileInfo.m in Sources */,
@@ -1093,6 +1123,7 @@
0DCD605C19117A90006B445C /* SNTCommandSyncPreflight.m in Sources */,
0D41640519197AD7006A356A /* SNTCommandSyncEventUpload.m in Sources */,
0D42D2B919D2042900955F08 /* SNTConfigurator.m in Sources */,
0DF395641AB76A7900CBC520 /* NSData+Zlib.m in Sources */,
0D10BE871A0AABD600C0C944 /* SNTDropRootPrivs.m in Sources */,
0DE4C8A618FF3B1700466D04 /* SNTCommandFlushCache.m in Sources */,
4092327A1A51B66400A04527 /* SNTCommandRule.m in Sources */,
@@ -1103,6 +1134,7 @@
0DE50F6E191304E0007B2B0C /* SNTRule.m in Sources */,
0D0A1EC3191998C900B8450F /* SNTCommandSyncRuleDownload.m in Sources */,
0D35BDC018FDA5C800921A21 /* SNTCertificate.m in Sources */,
0DB390991AB1E11400614002 /* SNTCommandVersion.m in Sources */,
0D42D2B519D1D98A00955F08 /* SNTSystemInfo.m in Sources */,
0D827E6719DF3C74006EC811 /* SNTCommandStatus.m in Sources */,
0D0A1EC6191AB9B000B8450F /* SNTCommandSyncPostflight.m in Sources */,
@@ -1118,6 +1150,7 @@
0D54E0B11976F8D3000BB59F /* SNTFileInfo.m in Sources */,
0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */,
0D385DF1180DE51600418BC6 /* SNTAppDelegate.m in Sources */,
0D88680A1AC48A1200B86659 /* SNTSystemInfo.m in Sources */,
0DCD605119115A06006B445C /* SNTXPCNotifierInterface.m in Sources */,
0D827E6519DF392E006EC811 /* SNTConfigurator.m in Sources */,
0D385DF2180DE51600418BC6 /* SNTMessageWindowController.m in Sources */,
@@ -1147,6 +1180,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D8868091AC48A1100B86659 /* SNTSystemInfo.m in Sources */,
0DE6788D1784A8C2007A9E52 /* SNTExecutionController.m in Sources */,
0D10BE861A0AABD600C0C944 /* SNTDropRootPrivs.m in Sources */,
0D63DD5C1906FCB400D346C4 /* SNTDatabaseController.m in Sources */,
@@ -1273,7 +1307,6 @@
baseConfigurationReference = 13A4FE400F3857C0F5831498 /* Pods-LogicTests.debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Santa.app/Contents/MacOS/Santa";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
@@ -1323,7 +1356,6 @@
baseConfigurationReference = BE74E23CF5A553E5F02462B9 /* Pods-LogicTests.release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Santa.app/Contents/MacOS/Santa";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
@@ -1368,6 +1400,7 @@
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1406,6 +1439,7 @@
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1439,6 +1473,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1479,6 +1514,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1541,6 +1577,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_MODULES = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
@@ -1575,6 +1612,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_MODULES = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
@@ -1620,6 +1658,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
@@ -1654,6 +1693,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D260DAB18B68E12002A0B55"
BuildableName = "LogicTests.xctest"
BlueprintName = "LogicTests"
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D260DAB18B68E12002A0B55"
BuildableName = "LogicTests.xctest"
BlueprintName = "LogicTests"
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D260DAB18B68E12002A0B55"
BuildableName = "LogicTests.xctest"
BlueprintName = "LogicTests"
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D260DAB18B68E12002A0B55"
BuildableName = "LogicTests.xctest"
BlueprintName = "LogicTests"
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D260DAB18B68E12002A0B55"
BuildableName = "LogicTests.xctest"
BlueprintName = "LogicTests"
ReferencedContainer = "container:Santa.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="13F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14C1514" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SNTAboutWindowController">
<connections>
<outlet property="moreInfoButton" destination="SRu-Kf-vu5" id="Vj2-9Q-05d"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
@@ -15,7 +16,7 @@
<window title="Santa" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="200"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1578"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1577"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="480" height="200"/>
<autoresizingMask key="autoresizingMask"/>
@@ -36,19 +37,32 @@
<rect key="frame" x="18" y="65" width="444" height="60"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" id="CcT-ul-1eA">
<font key="font" metaFont="system"/>
<string key="title">Santa is a binary whitelisting system for Mac OS X.
<string key="title">Santa is an application whitelisting system for Mac OS X.
There are no user-configurable settings.</string>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Udo-BY-n7e">
<rect key="frame" x="196" y="21" width="88" height="32"/>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SRu-Kf-vu5">
<rect key="frame" x="130" y="21" width="111" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="76" id="2Xc-ax-2bV"/>
<constraint firstAttribute="width" constant="99" id="JHv-2J-QSe"/>
</constraints>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="uSw-o1-lWW">
<buttonCell key="cell" type="push" title="More Info..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6fe-ju-aET">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="openMoreInfoURL:" target="-2" id="dps-TN-rkS"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Udo-BY-n7e">
<rect key="frame" x="240" y="21" width="111" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="99" id="2Xc-ax-2bV"/>
</constraints>
<buttonCell key="cell" type="push" title="Dismiss" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="uSw-o1-lWW">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
@@ -58,10 +72,13 @@ There are no user-configurable settings.</string>
</button>
</subviews>
<constraints>
<constraint firstItem="Udo-BY-n7e" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" priority="900" constant="191" id="1T4-DB-Dz8"/>
<constraint firstItem="SRu-Kf-vu5" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="136" id="Ake-nU-qhW"/>
<constraint firstItem="BnL-ZS-kXw" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="20" symbolic="YES" id="Fj1-SG-mzF"/>
<constraint firstAttribute="bottom" secondItem="Udo-BY-n7e" secondAttribute="bottom" constant="28" id="bpF-hC-haN"/>
<constraint firstItem="BnL-ZS-kXw" firstAttribute="centerX" secondItem="Udo-BY-n7e" secondAttribute="centerX" constant="0.5" id="csK-2p-W94"/>
<constraint firstAttribute="bottom" secondItem="SRu-Kf-vu5" secondAttribute="bottom" constant="28" id="fCB-02-SEt"/>
<constraint firstItem="BnL-ZS-kXw" firstAttribute="centerX" secondItem="se5-gp-TjO" secondAttribute="centerX" id="kez-S0-6Gg"/>
<constraint firstItem="Udo-BY-n7e" firstAttribute="leading" secondItem="SRu-Kf-vu5" secondAttribute="trailing" constant="11" id="sYO-yY-w9w"/>
</constraints>
</view>
<connections>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14C1514" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
@@ -7,6 +7,7 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SNTMessageWindowController">
<connections>
<outlet property="openEventButton" destination="7ua-5a-uSd" id="9s4-ZA-Vlo"/>
<outlet property="window" destination="9Bq-yh-54f" id="Uhs-WF-TV9"/>
</connections>
</customObject>
@@ -57,7 +58,7 @@
</connections>
</textField>
<textField horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PXc-xv-A28">
<rect key="frame" x="175" y="142" width="304" height="17"/>
<rect key="frame" x="175" y="117" width="304" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="4hh-R2-86s"/>
</constraints>
@@ -70,45 +71,12 @@
<binding destination="-2" name="value" keyPath="self.event.fileSHA256" id="SzX-Ep-rBa"/>
</connections>
</textField>
<button toolTip="Show code signing certificate chain" translatesAutoresizingMaskIntoConstraints="NO" id="cJf-k6-OxS" userLabel="Publisher Certs">
<rect key="frame" x="340" y="118" width="10" height="15"/>
<textField horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C3G-wL-u7w">
<rect key="frame" x="175" y="142" width="309" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="10" id="QTm-Iv-m5p"/>
<constraint firstAttribute="width" constant="305" id="Dem-wH-KHm"/>
</constraints>
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="NSFollowLinkFreestandingTemplate" imagePosition="overlaps" alignment="center" refusesFirstResponder="YES" imageScaling="proportionallyDown" inset="2" id="R72-Qy-Xbb">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="showCertInfo:" target="-2" id="dB0-a3-X31"/>
<binding destination="-2" name="hidden" keyPath="self.publisherInfo" id="fFR-f3-Oiw">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="BbV-3h-mmL">
<rect key="frame" x="220" y="33" width="110" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="110" id="6Uh-Bd-N64"/>
<constraint firstAttribute="height" constant="22" id="GH6-nw-6rD"/>
</constraints>
<buttonCell key="cell" type="roundTextured" title="OK" bezelStyle="texturedRounded" alignment="center" refusesFirstResponder="YES" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="XR6-Xa-gP4">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
<modifierMask key="keyEquivalentModifierMask" shift="YES"/>
</buttonCell>
<connections>
<action selector="closeWindow:" target="-2" id="qQq-gh-8lw"/>
</connections>
</button>
<textField horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="C3G-wL-u7w">
<rect key="frame" x="175" y="117" width="159" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Code signing information" placeholderString="" id="ztA-La-XgT">
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Code signing information" placeholderString="" id="ztA-La-XgT">
<font key="font" metaFont="system"/>
<color key="textColor" white="0.0" alpha="0.5" colorSpace="deviceWhite"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
@@ -130,7 +98,7 @@ DQ
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lvJ-Rk-UT5">
<rect key="frame" x="18" y="117" width="120" height="17"/>
<rect key="frame" x="18" y="142" width="120" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Publisher" id="yL9-yD-JXX">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@@ -149,7 +117,7 @@ DQ
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KEB-eH-x2Y">
<rect key="frame" x="18" y="142" width="120" height="17"/>
<rect key="frame" x="18" y="117" width="120" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="SHA-256" id="eKN-Ic-5zy">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@@ -176,6 +144,60 @@ DQ
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<font key="titleFont" metaFont="system"/>
</box>
<button toolTip="Show code signing certificate chain" translatesAutoresizingMaskIntoConstraints="NO" id="cJf-k6-OxS" userLabel="Publisher Certs">
<rect key="frame" x="51" y="143" width="14" height="14"/>
<constraints>
<constraint firstAttribute="width" constant="14" id="QTm-Iv-m5p"/>
<constraint firstAttribute="height" constant="14" id="YwG-0s-jop"/>
</constraints>
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="NSInfo" imagePosition="overlaps" alignment="center" refusesFirstResponder="YES" imageScaling="proportionallyDown" inset="2" id="R72-Qy-Xbb">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="showCertInfo:" target="-2" id="dB0-a3-X31"/>
<binding destination="-2" name="hidden" keyPath="self.publisherInfo" id="fFR-f3-Oiw">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="BbV-3h-mmL">
<rect key="frame" x="282" y="33" width="110" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="110" id="6Uh-Bd-N64"/>
<constraint firstAttribute="height" constant="22" id="GH6-nw-6rD"/>
</constraints>
<buttonCell key="cell" type="roundTextured" title="Dismiss" bezelStyle="texturedRounded" alignment="center" refusesFirstResponder="YES" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="XR6-Xa-gP4">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
<modifierMask key="keyEquivalentModifierMask" shift="YES"/>
</buttonCell>
<connections>
<action selector="closeWindow:" target="-2" id="qQq-gh-8lw"/>
</connections>
</button>
<button verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="7ua-5a-uSd">
<rect key="frame" x="158" y="33" width="112" height="25"/>
<constraints>
<constraint firstAttribute="width" priority="900" constant="112" id="Pec-Pa-4aZ"/>
</constraints>
<buttonCell key="cell" type="roundTextured" title="Open Event..." bezelStyle="texturedRounded" alignment="center" refusesFirstResponder="YES" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="X1b-TF-1TL">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</buttonCell>
<connections>
<action selector="openEventDetails:" target="-2" id="VhL-ql-rCV"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="h6f-PY-cc0" firstAttribute="bottom" secondItem="4Li-ul-zIi" secondAttribute="bottom" id="1Nc-gl-xMe"/>
@@ -183,39 +205,44 @@ DQ
<constraint firstItem="C3G-wL-u7w" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="ALv-0v-szi"/>
<constraint firstItem="cJf-k6-OxS" firstAttribute="centerY" secondItem="C3G-wL-u7w" secondAttribute="centerY" id="FdL-ZZ-Vbe"/>
<constraint firstItem="t8c-Fx-e5h" firstAttribute="top" secondItem="Iwq-Lx-rLv" secondAttribute="top" constant="30" id="FuB-GX-0jg"/>
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="leading" secondItem="cJf-k6-OxS" secondAttribute="trailing" constant="-45" id="GD2-Ka-deo"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="centerY" secondItem="oFj-ol-xpL" secondAttribute="centerY" id="GXI-pT-FM1"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="20" id="IwX-ja-ZIs"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="centerY" secondItem="d9e-Wv-Y5H" secondAttribute="centerY" id="JeD-9X-ULA"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="d9e-Wv-Y5H" secondAttribute="leading" priority="999" id="MVr-jY-GDj"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="top" secondItem="cD5-Su-lXR" secondAttribute="bottom" constant="30" id="Nsl-zf-poH"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="SCl-Ky-VmT"/>
<constraint firstItem="7ua-5a-uSd" firstAttribute="top" secondItem="oFj-ol-xpL" secondAttribute="bottom" constant="35" id="Scq-zQ-Sao"/>
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="KEB-eH-x2Y" secondAttribute="trailing" constant="20" id="Seb-c0-MUL"/>
<constraint firstAttribute="centerX" secondItem="cD5-Su-lXR" secondAttribute="centerX" id="V0a-Py-iEc"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="lvJ-Rk-UT5" secondAttribute="leading" priority="999" id="Z6G-l9-G4a"/>
<constraint firstAttribute="centerX" secondItem="BbV-3h-mmL" secondAttribute="centerX" id="acs-5J-vQY"/>
<constraint firstAttribute="centerX" secondItem="BbV-3h-mmL" secondAttribute="centerX" priority="900" id="acs-5J-vQY"/>
<constraint firstItem="KEB-eH-x2Y" firstAttribute="leading" secondItem="oFj-ol-xpL" secondAttribute="leading" priority="999" id="b5A-M7-ZsD"/>
<constraint firstItem="KEB-eH-x2Y" firstAttribute="centerY" secondItem="PXc-xv-A28" secondAttribute="centerY" id="cHe-pZ-0Oq"/>
<constraint firstItem="cD5-Su-lXR" firstAttribute="top" secondItem="t8c-Fx-e5h" secondAttribute="bottom" constant="30" id="dYg-zP-wh2"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="eSz-lz-Fdh"/>
<constraint firstItem="4Li-ul-zIi" firstAttribute="top" secondItem="pc8-G9-4pJ" secondAttribute="top" id="fzY-94-y2n"/>
<constraint firstAttribute="centerX" secondItem="t8c-Fx-e5h" secondAttribute="centerX" constant="-0.5" id="h3d-Kc-q88"/>
<constraint firstItem="BbV-3h-mmL" firstAttribute="leading" secondItem="7ua-5a-uSd" secondAttribute="trailing" constant="12" id="ioO-NJ-Jqo"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="centerY" secondItem="lvJ-Rk-UT5" secondAttribute="centerY" id="jfs-YI-7Ae"/>
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="trailing" secondItem="KEB-eH-x2Y" secondAttribute="trailing" id="jlD-Lo-abc"/>
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="oFj-ol-xpL" secondAttribute="trailing" constant="20" id="kOG-Cj-hFG"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="trailing" secondItem="lvJ-Rk-UT5" secondAttribute="trailing" id="lse-kg-lA2"/>
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="trailing" secondItem="KEB-eH-x2Y" secondAttribute="trailing" id="pdq-a6-Y73"/>
<constraint firstAttribute="centerX" secondItem="7ua-5a-uSd" secondAttribute="centerX" constant="61" id="phL-j9-rPq"/>
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="lvJ-Rk-UT5" secondAttribute="trailing" constant="20" id="qKi-KT-jzJ"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="top" secondItem="C3G-wL-u7w" secondAttribute="bottom" constant="8" id="rwU-fp-qh6"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="top" secondItem="C3G-wL-u7w" secondAttribute="bottom" constant="8" id="sG1-gQ-Qoo"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="bottom" constant="8" id="snd-8T-LjC"/>
<constraint firstItem="PXc-xv-A28" firstAttribute="bottom" secondItem="h6f-PY-cc0" secondAttribute="top" constant="-8" id="sG1-gQ-Qoo"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="bottom" secondItem="PXc-xv-A28" secondAttribute="top" constant="-8" id="snd-8T-LjC"/>
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="d9e-Wv-Y5H" secondAttribute="trailing" constant="20" id="stz-Vm-Kxo"/>
<constraint firstItem="PXc-xv-A28" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="tAa-1s-xVZ"/>
<constraint firstAttribute="bottom" secondItem="BbV-3h-mmL" secondAttribute="bottom" constant="35" id="ukF-FH-DE8"/>
<constraint firstItem="cJf-k6-OxS" firstAttribute="leading" secondItem="C3G-wL-u7w" secondAttribute="trailing" constant="8" id="wsf-ru-MoA"/>
<constraint firstItem="PXc-xv-A28" firstAttribute="top" secondItem="pc8-G9-4pJ" secondAttribute="bottom" constant="8" id="zst-nc-VqA"/>
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="baseline" secondItem="pc8-G9-4pJ" secondAttribute="baseline" id="xGd-Xr-3Z0"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="bottom" secondItem="C3G-wL-u7w" secondAttribute="top" constant="-8" id="zst-nc-VqA"/>
</constraints>
</view>
<point key="canvasLocation" x="162" y="710.5"/>
<point key="canvasLocation" x="113" y="777.5"/>
</window>
</objects>
<resources>
<image name="NSFollowLinkFreestandingTemplate" width="14" height="14"/>
<image name="NSInfo" width="32" height="32"/>
</resources>
</document>

View File

@@ -14,4 +14,8 @@
@interface SNTAboutWindowController : NSWindowController
@property IBOutlet NSButton *moreInfoButton;
- (IBAction)openMoreInfoURL:(id)sender;
@end

View File

@@ -14,10 +14,24 @@
#import "SNTAboutWindowController.h"
#import "SNTConfigurator.h"
@implementation SNTAboutWindowController
- (instancetype)init {
return [super initWithWindowNibName:@"AboutWindow"];
}
- (void)loadWindow {
[super loadWindow];
if (![[SNTConfigurator configurator] moreInfoURL]) {
[self.moreInfoButton removeFromSuperview];
}
}
- (IBAction)openMoreInfoURL:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[[SNTConfigurator configurator] moreInfoURL]];
[self close];
}
@end

View File

@@ -15,6 +15,7 @@
#import "SNTAppDelegate.h"
#import "SNTAboutWindowController.h"
#import "SNTConfigurator.h"
#import "SNTNotificationManager.h"
#import "SNTXPCConnection.h"
@@ -44,6 +45,9 @@
object:nil];
[self createConnection];
// Load configuration from disk ready for first message.
(void)[SNTConfigurator configurator];
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag {
@@ -73,7 +77,6 @@
self.listener.invalidationHandler = nil;
[self.listener invalidate];
self.listener = nil;
NSLog(@"KILLING CONNECTION");
}
- (void)attemptReconnection {

View File

@@ -47,11 +47,17 @@
///
/// A 'friendly' string representing the certificate information
///
@property(readonly) IBOutlet NSString *publisherInfo;
@property(readonly) NSString *publisherInfo;
///
/// An optional message to display with this block.
///
@property(readonly) IBOutlet NSAttributedString *attributedCustomMessage;
@property(readonly) NSAttributedString *attributedCustomMessage;
///
/// Reference to the "Open Event" button in the XIB. Used to either remove the button
/// if it isn't needed or set its title if it is.
///
@property IBOutlet NSButton *openEventButton;
@end

View File

@@ -17,6 +17,7 @@
#import <SecurityInterface/SFCertificatePanel.h>
#import "SNTCertificate.h"
#import "SNTConfigurator.h"
#import "SNTFileInfo.h"
#import "SNTMessageWindow.h"
#import "SNTStoredEvent.h"
@@ -27,14 +28,26 @@
self = [super initWithWindowNibName:@"MessageWindow"];
if (self) {
_event = event;
_customMessage = message;
[self.window setMovableByWindowBackground:NO];
[self.window setLevel:NSPopUpMenuWindowLevel];
[self.window center];
_customMessage = (message != (NSString *)[NSNull null] ? message : nil);
}
return self;
}
- (void)loadWindow {
[super loadWindow];
[self.window setLevel:NSPopUpMenuWindowLevel];
[self.window center];
if (![[SNTConfigurator configurator] eventDetailURL]) {
[self.openEventButton removeFromSuperview];
} else {
NSString *eventDetailText = [[SNTConfigurator configurator] eventDetailText];
if (eventDetailText) {
[self.openEventButton setTitle:eventDetailText];
}
}
}
- (IBAction)showWindow:(id)sender {
[(SNTMessageWindow *)self.window fadeIn:sender];
}
@@ -62,10 +75,25 @@
showGroup:YES];
}
- (IBAction)openEventDetails:(id)sender {
NSString *formatStr = [[SNTConfigurator configurator] eventDetailURL];
formatStr = [formatStr stringByReplacingOccurrencesOfString:@"%file_sha%"
withString:self.event.fileSHA256];
formatStr = [formatStr stringByReplacingOccurrencesOfString:@"%username%"
withString:self.event.executingUser];
formatStr =
[formatStr stringByReplacingOccurrencesOfString:@"%machine_id%"
withString:[[SNTConfigurator configurator] machineID]];
[self closeWindow:sender];
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:formatStr]];
}
#pragma mark Generated properties
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
if (! [key isEqualToString:@"event"]) {
if (![key isEqualToString:@"event"]) {
return [NSSet setWithObject:@"event"];
} else {
return nil;
@@ -111,7 +139,6 @@
NSAttributedString *returnStr = [[NSAttributedString alloc] initWithHTML:htmlData
documentAttributes:NULL];
return returnStr;
}
@end

View File

@@ -54,9 +54,16 @@
- (void)postBlockNotification:(SNTStoredEvent *)event withCustomMessage:(NSString *)message {
// See if this binary is already in the list of pending notifications.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"fileSHA256==%@", event.fileSHA256];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"event.fileSHA256==%@",
event.fileSHA256];
if ([[self.pendingNotifications filteredArrayUsingPredicate:predicate] count]) return;
if (!event) {
NSLog(@"Error: Missing event object in message received from daemon!");
return;
}
if (!message) message = (NSString *)[NSNull null];
// Notifications arrive on a background thread but UI updates must happen on the main thread.
// This includes making windows.
[self performSelectorOnMainThread:@selector(postBlockNotificationMainThread:)

View File

@@ -18,9 +18,7 @@
#import <Security/Security.h>
@interface SNTCertificate ()
///
/// A container for cached property values
///
@property NSMutableDictionary *memoizedData;
@end
@@ -46,7 +44,8 @@ static NSString *const kCertDataKey = @"certData";
// Despite the header file claiming that SecCertificateCreateWithData will return NULL if
// @c certData doesn't contain a valid DER-encoded X509 cert, this isn't always true.
// radar://problem/16124651
// To workaround, check that the certificate serial number can be retrieved.
// To workaround, check that the certificate serial number can be retrieved. According to
// RFC5280, the serial number field is required.
NSData *ser = CFBridgingRelease(SecCertificateCopySerialNumber(cert, NULL));
if (ser) {
self = [self initWithSecCertificateRef:cert];

View File

@@ -20,11 +20,47 @@
///
@interface SNTConfigurator : NSObject
#pragma mark - Daemon Settings
///
/// The operating mode
///
@property santa_clientmode_t clientMode;
///
/// Whether or not to log all events, even for whitelisted binaries.
///
@property BOOL logAllEvents;
# pragma mark - GUI Settings
///
/// The URL to open when the user clicks "More Info..." when opening Santa.app.
/// If unset, the button will not be displayed.
///
@property(readonly) NSURL *moreInfoURL;
///
/// When the user gets a block notification, a button can be displayed which will
/// take them to a web page with more information about that event.
/// This property contains a kind of format string to be turned into the URL to send them to.
/// The following sequences will be replaced in the final URL:
///
/// %file_sha% -- SHA-256 of the file that was blocked.
/// %machine_id% -- ID of the machine.
/// %username% -- executing user.
///
/// @note: This is not an NSURL because the format-string parsing is done elsewhere.
///
/// If this item isn't set, the Open Event button will not be displayed.
///
@property(readonly) NSString *eventDetailURL;
///
/// Related to the above property, this string represents the text to show on the button.
///
@property(readonly) NSString *eventDetailText;
# pragma mark - Sync Settings
///
@@ -40,7 +76,7 @@
///
/// If set, this over-rides the default machine ID used for syncing
///
@property(readonly) NSString *machineIDOverride;
@property(readonly) NSString *machineID;
# pragma mark Server Auth Settings

View File

@@ -15,10 +15,16 @@
#import "SNTConfigurator.h"
#import "SNTLogging.h"
#import "SNTSystemInfo.h"
@interface SNTConfigurator ()
@property NSString *configFilePath;
@property NSMutableDictionary *configData;
@property dispatch_source_t fileMonitoringSource;
@property(strong) void (^fileEventHandler)(void);
@property(strong) void (^fileCancelHandler)(void);
@end
@implementation SNTConfigurator
@@ -27,6 +33,14 @@
static NSString * const kConfigFilePath = @"/var/db/santa/config.plist";
/// The keys in the config file
static NSString * const kClientModeKey = @"ClientMode";
static NSString * const kLogAllEventsKey = @"LogAllEvents";
static NSString * const kMoreInfoURLKey = @"MoreInfoURL";
static NSString * const kEventDetailURLKey = @"EventDetailURL";
static NSString * const kEventDetailTextKey = @"EventDetailText";
static NSString * const kSyncBaseURLKey = @"SyncBaseURL";
static NSString * const kClientAuthCertificateFileKey = @"ClientAuthCertificateFile";
static NSString * const kClientAuthCertificatePasswordKey = @"ClientAuthCertificatePassword";
@@ -34,7 +48,6 @@ static NSString * const kClientAuthCertificateCNKey = @"ClientAuthCertificateCN"
static NSString * const kClientAuthCertificateIssuerKey = @"ClientAuthCertificateIssuerCN";
static NSString * const kServerAuthRootsDataKey = @"ServerAuthRootsData";
static NSString * const kServerAuthRootsFileKey = @"ServerAuthRootsFile";
static NSString * const kClientModeKey = @"ClientMode";
static NSString * const kMachineOwnerKey = @"MachineOwner";
static NSString * const kMachineIDKey = @"MachineID";
@@ -49,7 +62,7 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
self = [super init];
if (self) {
_configFilePath = filePath;
[self reloadConfigData];
[self beginWatchingConfigFile];
}
return self;
}
@@ -99,7 +112,7 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
if (self.configData[kMachineOwnerPlistFileKey] && self.configData[kMachineOwnerPlistKeyKey]) {
NSDictionary *plist =
[NSDictionary dictionaryWithContentsOfFile:self.configData[kMachineOwnerPlistFileKey]];
return plist[kMachineOwnerPlistKeyKey];
return plist[self.configData[kMachineOwnerPlistKeyKey]];
}
if (self.configData[kMachineOwnerKey]) {
@@ -109,18 +122,24 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
return @"";
}
- (NSString *)machineIDOverride {
- (NSString *)machineID {
NSString *machineId;
if (self.configData[kMachineIDPlistFileKey] && self.configData[kMachineIDPlistKeyKey]) {
NSDictionary *plist =
[NSDictionary dictionaryWithContentsOfFile:self.configData[kMachineIDPlistFileKey]];
return plist[kMachineIDPlistKeyKey];
machineId = plist[kMachineIDPlistKeyKey];
}
if (self.configData[kMachineIDKey]) {
return self.configData[kMachineIDKey];
machineId = self.configData[kMachineIDKey];
}
return @"";
if (!machineId || [machineId isEqual:@""]) {
machineId = [SNTSystemInfo hardwareUUID];
}
return machineId;
}
- (santa_clientmode_t)clientMode {
@@ -135,12 +154,32 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
- (void)setClientMode:(santa_clientmode_t)newMode {
if (newMode > CLIENTMODE_UNKNOWN && newMode < CLIENTMODE_MAX) {
[self reloadConfigData];
self.configData[kClientModeKey] = @(newMode);
[self saveConfigToDisk];
}
}
- (BOOL)logAllEvents {
return [self.configData[kLogAllEventsKey] boolValue];
}
- (void)setLogAllEvents:(BOOL)logAllEvents {
self.configData[kLogAllEventsKey] = @(logAllEvents);
[self saveConfigToDisk];
}
- (NSURL *)moreInfoURL {
return [NSURL URLWithString:self.configData[kMoreInfoURLKey]];
}
- (NSString *)eventDetailURL {
return self.configData[kEventDetailURLKey];
}
- (NSString *)eventDetailText {
return self.configData[kEventDetailTextKey];
}
#pragma mark Private
///
@@ -158,12 +197,10 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
/// but will fail silently if this cannot be done.
///
- (void)reloadConfigData {
NSFileManager *fm = [NSFileManager defaultManager];
if (!self.configData) self.configData = [NSMutableDictionary dictionary];
if (![fm fileExistsAtPath:self.configFilePath]) {
_configData = [NSMutableDictionary dictionary];
return;
}
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:self.configFilePath]) return;
// Ensure the config file permissions are 0644. Fail silently if they can't be changed.
NSDictionary *fileAttrs = [fm attributesOfItemAtPath:self.configFilePath error:nil];
@@ -178,10 +215,7 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
options:NSDataReadingMappedIfSafe
error:&error];
if (error) {
fprintf(stderr, "%s\n", [[NSString stringWithFormat:@"Could not read configuration file %@: %@",
self.configFilePath, [error localizedDescription]] UTF8String]);
_configData = [NSMutableDictionary dictionary];
LOGE(@"Could not read configuration file: %@", [error localizedDescription]);
return;
}
@@ -191,16 +225,62 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
format:NULL
error:&error];
if (error) {
fprintf(stderr, "%s\n",
[[NSString stringWithFormat:@"Could not parse configuration file %@: %@",
self.configFilePath,
[error localizedDescription]] UTF8String]);
_configData = [NSMutableDictionary dictionary];
LOGE(@"Could not parse configuration file: %@", [error localizedDescription]);
return;
}
_configData = [configData mutableCopy];
// Ensure user isn't trying to change the client mode while running, only santactl can do that.
if (self.configData[kClientModeKey] && configData[kClientModeKey] &&
![self.configData[kClientModeKey] isEqual:configData[kClientModeKey]]) {
LOGW(@"Client mode in config file was changed behind our back, resetting.");
NSMutableDictionary *configDataMutable = [configData mutableCopy];
configDataMutable[kClientModeKey] = self.configData[kClientModeKey];
self.configData = configDataMutable;
[self saveConfigToDisk];
} else {
self.configData = [configData mutableCopy];
}
}
- (void)beginWatchingConfigFile {
if (self.fileMonitoringSource) return;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
if (!queue) return;
__weak typeof(self) weakSelf = self;
int mask = (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE |
DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_RENAME);
self.fileEventHandler = ^{
unsigned long l = dispatch_source_get_data(weakSelf.fileMonitoringSource);
if (l & DISPATCH_VNODE_DELETE || l & DISPATCH_VNODE_RENAME) {
dispatch_source_cancel(weakSelf.fileMonitoringSource);
} else {
[weakSelf reloadConfigData];
}
};
self.fileCancelHandler = ^{
int fd;
if (weakSelf.fileMonitoringSource) {
fd = (int)dispatch_source_get_handle(weakSelf.fileMonitoringSource);
close(fd);
}
while ((fd = open([weakSelf.configFilePath fileSystemRepresentation], O_EVTONLY)) < 0) {
sleep(1);
}
weakSelf.fileMonitoringSource = dispatch_source_create(
DISPATCH_SOURCE_TYPE_VNODE, fd, mask, queue);
dispatch_source_set_event_handler(weakSelf.fileMonitoringSource, weakSelf.fileEventHandler);
dispatch_source_set_cancel_handler(weakSelf.fileMonitoringSource, weakSelf.fileCancelHandler);
dispatch_resume(weakSelf.fileMonitoringSource);
[weakSelf reloadConfigData];
};
dispatch_async(queue, self.fileCancelHandler);
}
@end

View File

@@ -90,4 +90,9 @@
///
@property NSNumber *pid;
///
/// The parent process ID of the binary being executed.
///
@property NSNumber *ppid;
@end

View File

@@ -41,6 +41,8 @@
ENCODE(self.executingUser, @"executingUser");
ENCODE(self.occurrenceDate, @"occurrenceDate");
ENCODE(@(self.decision), @"decision");
ENCODE(self.pid, @"pid");
ENCODE(self.ppid, @"ppid");
ENCODE(self.loggedInUsers, @"loggedInUsers");
ENCODE(self.currentSessions, @"currentSessions");
@@ -63,6 +65,8 @@
_executingUser = DECODE(NSString, @"executingUser");
_occurrenceDate = DECODE(NSDate, @"occurrenceDate");
_decision = [DECODE(NSNumber, @"decision") intValue];
_pid = DECODE(NSNumber, @"pid");
_ppid = DECODE(NSNumber, @"ppid");
_loggedInUsers = DECODEARRAY(NSString, @"loggedInUsers");
_currentSessions = DECODEARRAY(NSString, @"currentSessions");

View File

@@ -26,9 +26,9 @@
CFSTR(kIOPlatformSerialNumberKey),
kCFAllocatorDefault,
0));
IOObjectRelease(platformExpert);
return serial;
}
@@ -60,7 +60,9 @@
}
+ (NSString *)longHostname {
return [[NSHost currentHost] name];
char hostname[MAXHOSTNAMELEN];
gethostname(hostname, (int)sizeof(hostname));
return @(hostname);
}
# pragma mark - Internal

View File

@@ -123,6 +123,7 @@
for (int sleepLoops = 0; sleepLoops < 1000 && !verificationComplete; sleepLoops++) {
usleep(5000);
}
if (!verificationComplete) [self invalidate];
}
}

View File

@@ -20,8 +20,10 @@ OSDefineMetaClassAndStructors(SantaDecisionManager, OSObject);
#pragma mark Object Lifecycle
bool SantaDecisionManager::init() {
dataqueue_lock_ = IORWLockAlloc();
cached_decisions_lock_ = IORWLockAlloc();
sdm_lock_grp_ = lck_grp_alloc_init("santa-locks", lck_grp_attr_alloc_init());
dataqueue_lock_ = lck_mtx_alloc_init(sdm_lock_grp_, lck_attr_alloc_init());
cached_decisions_lock_ = lck_rw_alloc_init(sdm_lock_grp_, lck_attr_alloc_init());
cached_decisions_ = OSDictionary::withCapacity(1000);
return kIOReturnSuccess;
@@ -34,15 +36,20 @@ void SantaDecisionManager::free() {
}
if (cached_decisions_lock_) {
IORWLockFree(cached_decisions_lock_);
lck_rw_free(cached_decisions_lock_, sdm_lock_grp_);
cached_decisions_lock_ = NULL;
}
if (dataqueue_lock_ ) {
IORWLockFree(dataqueue_lock_);
lck_mtx_free(dataqueue_lock_, sdm_lock_grp_);
dataqueue_lock_ = NULL;
}
if (sdm_lock_grp_) {
lck_grp_free(sdm_lock_grp_);
sdm_lock_grp_ = NULL;
}
super::free();
}
@@ -54,16 +61,20 @@ void SantaDecisionManager::ConnectClient(IOSharedDataQueue *queue, pid_t pid) {
// Any decisions made while the daemon wasn't
// connected should be cleared
cached_decisions_->flushCollection();
ClearCache();
lck_mtx_lock(dataqueue_lock_);
dataqueue_ = queue;
dataqueue_->retain();
lck_mtx_unlock(dataqueue_lock_);
owning_pid_ = pid;
owning_proc_ = proc_find(pid);
}
void SantaDecisionManager::DisconnectClient() {
if (owning_pid_ < 1) return;
owning_pid_ = -1;
// Ask santad to shutdown, in case it's running.
@@ -75,8 +86,10 @@ void SantaDecisionManager::DisconnectClient() {
message.vnode_id = 0;
PostToQueue(message);
lck_mtx_lock(dataqueue_lock_);
dataqueue_->release();
dataqueue_ = NULL;
lck_mtx_unlock(dataqueue_lock_);
proc_rele(owning_proc_);
owning_proc_ = NULL;
@@ -89,12 +102,6 @@ bool SantaDecisionManager::ClientConnected() {
# pragma mark Listener Control
kern_return_t SantaDecisionManager::StartListener() {
process_listener_ = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
process_scope_callback,
reinterpret_cast<void *>(this));
if (!process_listener_) return kIOReturnInternalError;
LOGD("Process listener started.");
vnode_listener_ = kauth_listen_scope(KAUTH_SCOPE_VNODE,
vnode_scope_callback,
reinterpret_cast<void *>(this));
@@ -109,9 +116,6 @@ kern_return_t SantaDecisionManager::StopListener() {
kauth_unlisten_scope(vnode_listener_);
vnode_listener_ = NULL;
kauth_unlisten_scope(process_listener_);
process_listener_ = NULL;
// Wait for any active invocations to finish before returning
do {
IOSleep(5);
@@ -121,7 +125,6 @@ kern_return_t SantaDecisionManager::StopListener() {
ClearCache();
LOGD("Vnode listener stopped.");
LOGD("Process listener stopped.");
return kIOReturnSuccess;
}
@@ -130,7 +133,7 @@ kern_return_t SantaDecisionManager::StopListener() {
void SantaDecisionManager::AddToCache(
const char *identifier, santa_action_t decision, uint64_t microsecs) {
IORWLockWrite(cached_decisions_lock_);
lck_rw_lock_exclusive(cached_decisions_lock_);
if (cached_decisions_->getCount() > kMaxCacheSize) {
// This could be made a _lot_ smarter, say only removing entries older
@@ -155,17 +158,18 @@ void SantaDecisionManager::AddToCache(
}
}
IORWLockUnlock(cached_decisions_lock_);
lck_rw_unlock_exclusive(cached_decisions_lock_);
}
void SantaDecisionManager::CacheCheck(const char *identifier) {
IORWLockRead(cached_decisions_lock_);
lck_rw_lock_shared(cached_decisions_lock_);
bool shouldInvalidate = (cached_decisions_->getObject(identifier) != NULL);
IORWLockUnlock(cached_decisions_lock_);
if (shouldInvalidate) {
IORWLockWrite(cached_decisions_lock_);
lck_rw_lock_shared_to_exclusive(cached_decisions_lock_);
cached_decisions_->removeObject(identifier);
IORWLockUnlock(cached_decisions_lock_);
lck_rw_unlock_exclusive(cached_decisions_lock_);
} else {
lck_rw_unlock_shared(cached_decisions_lock_);
}
}
@@ -174,23 +178,23 @@ uint64_t SantaDecisionManager::CacheCount() {
}
void SantaDecisionManager::ClearCache() {
IORWLockWrite(cached_decisions_lock_);
lck_rw_lock_exclusive(cached_decisions_lock_);
cached_decisions_->flushCollection();
IORWLockUnlock(cached_decisions_lock_);
lck_rw_unlock_exclusive(cached_decisions_lock_);
}
santa_action_t SantaDecisionManager::GetFromCache(const char *identifier) {
santa_action_t result = ACTION_UNSET;
uint64_t decision_time = 0;
IORWLockRead(cached_decisions_lock_);
lck_rw_lock_shared(cached_decisions_lock_);
SantaMessage *cached_decision = OSDynamicCast(
SantaMessage, cached_decisions_->getObject(identifier));
if (cached_decision) {
result = cached_decision->getAction();
decision_time = cached_decision->getMicrosecs();
}
IORWLockUnlock(cached_decisions_lock_);
lck_rw_unlock_shared(cached_decisions_lock_);
if (CHECKBW_RESPONSE_VALID(result)) {
uint64_t diff_time = GetCurrentUptime();
@@ -210,9 +214,9 @@ santa_action_t SantaDecisionManager::GetFromCache(const char *identifier) {
}
if (decision_time < diff_time) {
IORWLockWrite(cached_decisions_lock_);
lck_rw_lock_exclusive(cached_decisions_lock_);
cached_decisions_->removeObject(identifier);
IORWLockUnlock(cached_decisions_lock_);
lck_rw_unlock_exclusive(cached_decisions_lock_);
return ACTION_UNSET;
}
}
@@ -223,12 +227,12 @@ santa_action_t SantaDecisionManager::GetFromCache(const char *identifier) {
# pragma mark Queue Management
bool SantaDecisionManager::PostToQueue(santa_message_t message) {
IORWLockWrite(dataqueue_lock_);
lck_mtx_lock(dataqueue_lock_);
bool kr = false;
if (dataqueue_) {
kr = dataqueue_->enqueue(&message, sizeof(message));
}
IORWLockUnlock(dataqueue_lock_);
lck_mtx_unlock(dataqueue_lock_);
return kr;
}
@@ -258,9 +262,8 @@ santa_action_t SantaDecisionManager::FetchDecision(
path[0] = '\0';
}
// If daemon isn't connected, allow and cache
if (owning_pid_ < 1) {
LOGI("Exeuction request without daemon running: %s", path);
if (!ClientConnected()) {
LOGI("Execution request without daemon running: %s", path);
AddToCache(vnode_id_str,
ACTION_RESPOND_CHECKBW_ALLOW,
GetCurrentUptime());
@@ -335,38 +338,9 @@ void SantaDecisionManager::DecrementListenerInvocations() {
OSDecrementAtomic(&listener_invocations_);
}
bool SantaDecisionManager::MatchesOwningPID(const pid_t other_pid) {
return (owning_pid_ == other_pid);
}
#undef super
#pragma mark Kauth Callbacks
extern "C" int process_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) {
if (idata == NULL) {
LOGE("Process callback established without valid decision manager.");
return KAUTH_RESULT_ALLOW;
}
SantaDecisionManager *sdm = OSDynamicCast(
SantaDecisionManager, reinterpret_cast<OSObject *>(idata));
// NOTE: this prevents a debugger from attaching to an existing santad
// process but doesn't prevent starting santad under a debugger. This check
// is only here to try and prevent the user from deadlocking their machine
// by attaching a debugger, so if they work around it and end up deadlocking,
// that's their problem.
if (action == KAUTH_PROCESS_CANTRACE &&
sdm->MatchesOwningPID(proc_pid((proc_t)arg0))) {
*(reinterpret_cast<int *>(arg1)) = EPERM;
LOGD("Denied debugger access");
return KAUTH_RESULT_DENY;
}
return KAUTH_RESULT_ALLOW;
}
#pragma mark Kauth Callback
extern "C" int vnode_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
@@ -391,7 +365,7 @@ extern "C" int vnode_scope_callback(
// Don't operate on ACCESS events, as they're advisory
if (action & KAUTH_VNODE_ACCESS) return returnResult;
// Filter for only WRITE_DATA actions
// Filter for only writes
if (action & KAUTH_VNODE_WRITE_DATA ||
action & KAUTH_VNODE_APPEND_DATA ||
action & KAUTH_VNODE_DELETE) {
@@ -431,17 +405,7 @@ extern "C" int vnode_scope_callback(
default:
// NOTE: Any unknown response or error condition causes us to fail open.
// Whilst from a security perspective this is bad, it's important that
// we don't break user's machines. Every fallen open response will come
// through this code path and cause this log entry to be created, so we
// can investigate each case and try to fix the root cause.
char path[MAX_PATH_LEN];
int name_len = MAX_PATH_LEN;
if (vn_getpath(vnode, path, &name_len) != 0) {
path[0] = '\0';
}
LOGW("Didn't receive a valid response for %s. Received: %d.",
path,
returnedAction);
// we don't break user's machines.
break;
}

View File

@@ -83,10 +83,10 @@ class SantaDecisionManager : public OSObject {
/// Returns whether a client is currently connected or not.
bool ClientConnected();
/// Starts both kauth listeners.
/// Starts the kauth listener.
kern_return_t StartListener();
/// Stops both kauth listeners. After stopping new callback requests,
/// Stops the kauth listener. After stopping new callback requests,
/// waits until all current invocations have finished before clearing the
/// cache and returning.
kern_return_t StopListener();
@@ -128,22 +128,20 @@ class SantaDecisionManager : public OSObject {
/// Returns the current system uptime in microseconds
uint64_t GetCurrentUptime();
/// Increments the count of active vnode callback's pending.
void IncrementListenerInvocations();
/// Decrements the count of active vnode callback's pending.
void DecrementListenerInvocations();
/// Returns true if other_pid is the same as the current client pid.
bool MatchesOwningPID(const pid_t other_pid);
private:
lck_grp_t *sdm_lock_grp_;
lck_rw_t *cached_decisions_lock_;
lck_mtx_t *dataqueue_lock_;
OSDictionary *cached_decisions_;
IORWLock *cached_decisions_lock_;
IOSharedDataQueue *dataqueue_;
IORWLock *dataqueue_lock_;
SInt32 listener_invocations_;
@@ -151,7 +149,6 @@ class SantaDecisionManager : public OSObject {
proc_t owning_proc_;
kauth_listener_t vnode_listener_;
kauth_listener_t process_listener_;
};
///
@@ -168,18 +165,4 @@ extern "C" int vnode_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
///
/// The kauth callback function for the Process scope
/// @param actor's credentials
/// @param data that was passed when the listener was registered
/// @param action that was requested (KAUTH_PROCESS_{CANTRACE,CANSIGNAL})
/// @param target process
/// @param Pointer to an errno-style error.
/// @param unused
/// @param unused
///
extern "C" int process_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
#endif // SANTA__SANTA_DRIVER__SANTADECISIONMANAGER_H

View File

@@ -48,6 +48,8 @@ bool SantaDriverClient::start(IOService *provider) {
void SantaDriverClient::stop(IOService *provider) {
super::stop(provider);
fSDM = NULL;
fProvider = NULL;
}
@@ -61,9 +63,9 @@ bool SantaDriverClient::terminate(IOOptionBits options) {
LOGI("Client disconnected.");
fSharedMemory->release();
fDataQueue->release();
fSharedMemory = NULL;
fDataQueue->release();
fDataQueue = NULL;
if (fProvider && fProvider->isOpen(this)) fProvider->close(this);
@@ -94,6 +96,9 @@ IOReturn SantaDriverClient::clientMemoryForType(UInt32 type,
fSharedMemory->retain(); // client will decrement this ref
*memory = fSharedMemory;
fSDM->ConnectClient(fDataQueue, proc_selfpid());
LOGI("Client connected, PID: %d.", proc_selfpid());
return kIOReturnSuccess;
}
@@ -122,10 +127,6 @@ IOReturn SantaDriverClient::open() {
return kIOReturnVMError;
}
fSDM->ConnectClient(fDataQueue, proc_selfpid());
LOGI("Client connected, PID: %d.", proc_selfpid());
return kIOReturnSuccess;
}

View File

@@ -29,7 +29,7 @@
#include "SNTKernelCommon.h"
// The maximum number of messages can be kept in the IODataQueue at any time.
const int kMaxQueueEvents = 64;
const int kMaxQueueEvents = 256;
///
/// This class is instantiated by IOKit when a new client process attempts to

View File

@@ -55,18 +55,17 @@ static NSMutableDictionary *registeredCommands;
+ (NSString *)helpForCommandWithName:(NSString *)commandName {
Class<SNTCommand> command = registeredCommands[commandName];
if (command) {
NSMutableString *helpText = [[NSMutableString alloc] init];
[helpText appendFormat:@"Help for '%@':\n", commandName];
[helpText appendString:[command longHelpText]];
return helpText;
NSString *longHelp = [command longHelpText];
if (longHelp) {
return [NSString stringWithFormat:@"Help for '%@':\n%@", commandName, longHelp];
} else {
return @"This command does not have any help information.";
}
}
return nil;
}
+ (SNTXPCConnection *)connectToDaemon {
// TODO(rah): Re-factor this so that successfully establishing the connection runs the command,
// instead of having to sleep until the connection is made.
SNTXPCConnection *daemonConn =
[[SNTXPCConnection alloc] initClientWithName:[SNTXPCControlInterface serviceId]
options:NSXPCConnectionPrivileged];
@@ -78,7 +77,7 @@ static NSMutableDictionary *registeredCommands;
};
daemonConn.invalidationHandler = ^{
printf("An error occurred communicating with the daemon\n");
printf("An error occurred communicating with the daemon, is it running?\n");
exit(1);
};

View File

@@ -36,59 +36,61 @@ REGISTER_COMMAND_NAME(@"binaryinfo");
}
+ (NSString *)shortHelpText {
return @"Prints information about the given binary.";
return @"Prints information about a binary.";
}
+ (NSString *)longHelpText {
return (@"The details provided will be the same ones Santa uses to make a decision about binaries"
@"This includes SHA-1, SHA-256, code signing information and the type of binary");
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.");
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
NSString *filePath = [arguments firstObject];
if (!filePath) {
LOGI(@"Missing file path");
printf("Missing file path\n");
exit(1);
}
SNTFileInfo *fileInfo = [[SNTFileInfo alloc] initWithPath:filePath];
if (!fileInfo) {
LOGI(@"Invalid file");
printf("Invalid file\n");
exit(1);
}
LOGI(@"Info for file: %@", [fileInfo path]);
LOGI(@"-----------------------------------------------------------");
LOGI(@"%-20s: %@", "SHA-1", [fileInfo SHA1]);
LOGI(@"%-20s: %@", "SHA-256", [fileInfo SHA256]);
printf("%-12s: %s\n", "Path", [[fileInfo path] UTF8String]);
printf("%-12s: %s\n", "SHA-256", [[fileInfo SHA256] UTF8String]);
printf("%-12s: %s\n", "SHA-1", [[fileInfo SHA1] UTF8String]);
NSArray *archs = [fileInfo architectures];
if (archs) {
LOGI(@"%-20s: %@ (%@)", "Type", [fileInfo machoType], [archs componentsJoinedByString:@", "]);
printf("%-12s: %s (%s)\n", "Type",
[[fileInfo machoType] UTF8String],
[[archs componentsJoinedByString:@", "] UTF8String]);
} else {
LOGI(@"%-20s: %@", "Type", [fileInfo machoType]);
printf("%-12s: %s\n", "Type", [[fileInfo machoType] UTF8String]);
}
SNTCodesignChecker *csc = [[SNTCodesignChecker alloc] initWithBinaryPath:filePath];
LOGI(@"%-20s: %s", "Code-signed", (csc) ? "Yes" : "No");
printf("%-12s: %s\n", "Code-signed", (csc) ? "Yes" : "No");
if (csc) {
LOGI(@"Signing chain\n");
printf("Signing chain:\n");
[csc.certificates enumerateObjectsUsingBlock:^(SNTCertificate *c,
unsigned long idx,
BOOL *stop) {
idx++; // index from 1
LOGI(@" %2lu. %-20s: %@", idx, "SHA-1", c.SHA1);
LOGI(@" %-20s: %@", "SHA-256", c.SHA256);
LOGI(@" %-20s: %@", "Common Name", c.commonName);
LOGI(@" %-20s: %@", "Organization", c.orgName);
LOGI(@" %-20s: %@", "Organizational Unit", c.orgUnit);
LOGI(@" %-20s: %@", "Valid From", c.validFrom);
LOGI(@" %-20s: %@", "Valid Until", c.validUntil);
LOGI(@"");
printf(" %2lu. %-20s: %s\n", idx, "SHA-256", [c.SHA256 UTF8String]);
printf(" %-20s: %s\n", "SHA-1", [c.SHA1 UTF8String]);
printf(" %-20s: %s\n", "Common Name", [c.commonName UTF8String]);
printf(" %-20s: %s\n", "Organization", [c.orgName UTF8String]);
printf(" %-20s: %s\n", "Organizational Unit", [c.orgUnit UTF8String]);
printf(" %-20s: %s\n", "Valid From", [[c.validFrom description] UTF8String]);
printf(" %-20s: %s\n", "Valid Until", [[c.validUntil description] UTF8String]);
printf("\n");
}];
}

View File

@@ -34,12 +34,12 @@ REGISTER_COMMAND_NAME(@"flushcache");
}
+ (NSString *)shortHelpText {
return @"Flush the kernel cache";
return @"Flush the kernel cache.";
}
+ (NSString *)longHelpText {
return @"Flushes the in-kernel cache of whitelisted binaries.\n\n"
@"Returns 0 if successful, 1 otherwise";
return (@"Flushes the in-kernel cache of whitelisted binaries.\n"
@"Returns 0 if successful, 1 otherwise");
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {

View File

@@ -43,18 +43,17 @@ REGISTER_COMMAND_NAME(@"rule");
}
+ (NSString *)shortHelpText {
return @"Adds a rule for the given binary or hash.";
return @"Manually add/remove rules.";
}
+ (NSString *)longHelpText {
return (@"santactl rule {add|remove}\n"
@"--whitelist: add to whitelist\n"
@"--blacklist: add to blacklist\n"
@"--silent-blacklist: add to silent blacklist\n"
@"--message {message}: custom message\n"
@"--path {path}: path of binary to add\n"
@"--sha256 {sha256}: hash to add\n"
);
return (@"Usage: santactl rule {add|remove} [options]\n"
@" --whitelist: add to whitelist\n"
@" --blacklist: add to blacklist\n"
@" --silent-blacklist: add to silent blacklist\n"
@" --message {message}: custom message\n"
@" --path {path}: path of binary to add\n"
@" --sha256 {sha256}: hash to add\n");
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
@@ -62,12 +61,12 @@ REGISTER_COMMAND_NAME(@"rule");
// Ensure we have no privileges
if (!DropRootPrivileges()) {
LOGE(@"Failed to drop root privileges. Exiting.");
printf("Failed to drop root privileges.\n");
exit(1);
}
if ([config syncBaseURL] != nil) {
LOGE(@"SyncBaseURL is set, rules are managed centrally");
printf("SyncBaseURL is set, rules are managed centrally.\n");
exit(1);
}
@@ -75,7 +74,7 @@ REGISTER_COMMAND_NAME(@"rule");
// add or remove
if (!action) {
LOGI(@"Missing action");
printf("Missing action - add or remove?\n");
exit(1);
}
@@ -85,7 +84,7 @@ REGISTER_COMMAND_NAME(@"rule");
} else if ([action compare:@"remove" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
state = RULESTATE_REMOVE;
} else {
LOGI(@"Unknown action, expected add or remove");
printf("Unknown action, expected add or remove.\n");
exit(1);
}
@@ -105,44 +104,44 @@ REGISTER_COMMAND_NAME(@"rule");
state = RULESTATE_SILENT_BLACKLIST;
} else if ([argument compare:@"--message" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
if (++i > ([arguments count])) {
LOGI(@"No message specified");
printf("No message specified.\n");
}
customMsg = [arguments objectAtIndex:i];
} else if ([argument compare:@"--path" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
if (++i > ([arguments count])) {
LOGI(@"No path specified");
printf("No path specified.\n");
}
filePath = [arguments objectAtIndex:i];
} else if ([argument compare:@"--sha256" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
if (++i > ([arguments count])) {
LOGI(@"No SHA-256 specified");
printf("No SHA-256 specified.\n");
}
SHA256 = [arguments objectAtIndex:i];
} else {
LOGI(@"Unknown argument %@", argument);
printf("Unknown argument %s.\n", [argument UTF8String]);
exit(1);
}
}
if (state == RULESTATE_UNKNOWN) {
LOGI(@"No state specified");
printf("No state specified.\n");
exit(1);
}
if (filePath) {
SNTFileInfo *fileInfo = [[SNTFileInfo alloc] initWithPath:filePath];
if (!fileInfo) {
LOGI(@"Not a regular file or executable bundle");
printf("Not a regular file or executable bundle.\n");
exit(1);
}
SHA256 = [fileInfo SHA256];
} else if (SHA256) {
} else {
LOGI(@"No SHA-256 or binary specified");
printf("No SHA-256 or binary specified.\n");
exit(1);
}
@@ -154,9 +153,9 @@ REGISTER_COMMAND_NAME(@"rule");
[[daemonConn remoteObjectProxy] databaseRuleAddRule:newRule withReply:^{
if (state == RULESTATE_REMOVE) {
LOGI(@"Removed rule for SHA-256: %@", [newRule shasum]);
printf("Removed rule for SHA-256: %s.\n", [newRule.shasum UTF8String]);
} else {
LOGI(@"Added rule for SHA-256: %@", [newRule shasum]);
printf("Added rule for SHA-256: %s.\n", [newRule.shasum UTF8String]);
}
exit(0);
}];

View File

@@ -14,11 +14,6 @@
#import "SNTCommandController.h"
#include <IOKit/kext/KextManager.h>
#import "SNTFileInfo.h"
#import "SNTKernelCommon.h"
#import "SNTLogging.h"
#import "SNTXPCConnection.h"
#import "SNTXPCControlInterface.h"
@@ -38,85 +33,40 @@ REGISTER_COMMAND_NAME(@"status");
}
+ (NSString *)shortHelpText {
return @"Get status about Santa";
return @"Show Santa status information.";
}
+ (NSString *)longHelpText {
return @"Returns status information about Santa.";
return nil;
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
// Version information
LOGI(@">>> Versions");
LOGI(@"%-30s | %@", "santa-driver version", [self kextVersion]);
LOGI(@"%-30s | %@", "santad version", [self daemonVersion]);
LOGI(@"%-30s | %@",
"santactl version",
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]);
LOGI(@"%-30s | %@", "SantaGUI version", [self guiVersion]);
LOGI(@"");
// Kext status
if (daemonConn) {
__block uint64_t cacheCount = -1;
[[daemonConn remoteObjectProxy] cacheCount:^(uint64_t count) {
cacheCount = count;
}];
do { usleep(5000); } while (cacheCount == -1);
LOGI(@">>> Kernel Info");
LOGI(@"%-30s | %d", "Kernel cache count", cacheCount);
LOGI(@"");
__block uint64_t cacheCount = -1;
[[daemonConn remoteObjectProxy] cacheCount:^(uint64_t count) {
cacheCount = count;
}];
do { usleep(5000); } while (cacheCount == -1);
printf(">>> Kernel Info\n");
printf(" %-25s | %lld\n", "Kernel cache count", cacheCount);
// Database counts
__block uint64_t eventCount = 1, binaryRuleCount = -1, certRuleCount = -1;
[[daemonConn remoteObjectProxy] databaseRuleCounts:^(uint64_t binary, uint64_t certificate) {
binaryRuleCount = binary;
certRuleCount = certificate;
}];
[[daemonConn remoteObjectProxy] databaseEventCount:^(uint64_t count) {
eventCount = count;
}];
do { usleep(5000); } while (eventCount == -1 || binaryRuleCount == -1 || certRuleCount == -1);
LOGI(@">>> Database Info");
LOGI(@"%-30s | %d", "Binary Rules", binaryRuleCount);
LOGI(@"%-30s | %d", "Certificate Rules", certRuleCount);
LOGI(@"%-30s | %d", "Events Pending Upload", eventCount);
LOGI(@"");
} else {
LOGI(@">>> santad is not running, cannot provide any more information.");
}
// Database counts
__block uint64_t eventCount = 1, binaryRuleCount = -1, certRuleCount = -1;
[[daemonConn remoteObjectProxy] databaseRuleCounts:^(uint64_t binary, uint64_t certificate) {
binaryRuleCount = binary;
certRuleCount = certificate;
}];
[[daemonConn remoteObjectProxy] databaseEventCount:^(uint64_t count) {
eventCount = count;
}];
do { usleep(5000); } while (eventCount == -1 || binaryRuleCount == -1 || certRuleCount == -1);
printf(">>> Database Info\n");
printf(" %-25s | %lld\n", "Binary Rules", binaryRuleCount);
printf(" %-25s | %lld\n", "Certificate Rules", certRuleCount);
printf(" %-25s | %lld\n", "Events Pending Upload", eventCount);
exit(0);
}
+ (NSString *)kextVersion {
NSDictionary *loadedKexts = CFBridgingRelease(
KextManagerCopyLoadedKextInfo((__bridge CFArrayRef)@[ @(USERCLIENT_ID) ],
(__bridge CFArrayRef)@[ @"CFBundleVersion" ]));
if (loadedKexts[@(USERCLIENT_ID)] && loadedKexts[@(USERCLIENT_ID)][@"CFBundleVersion"]) {
return loadedKexts[@(USERCLIENT_ID)][@"CFBundleVersion"];
}
SNTFileInfo *driverInfo =
[[SNTFileInfo alloc] initWithPath:@"/Library/Extensions/santa-driver.kext"];
if (driverInfo) {
return [driverInfo.bundleVersion stringByAppendingString:@" (unloaded)"];
}
return @"not found";
}
+ (NSString *)daemonVersion {
SNTFileInfo *daemonInfo = [[SNTFileInfo alloc] initWithPath:@"/usr/libexec/santad"];
return daemonInfo.bundleVersion;
}
+ (NSString *)guiVersion {
SNTFileInfo *guiInfo =
[[SNTFileInfo alloc] initWithPath:@"/Applications/Santa.app/Contents/MacOS/Santa"];
return guiInfo.bundleVersion;
}
@end

View File

@@ -0,0 +1,21 @@
/// 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.
/// Category on NSData providing the option of getting zlib or gzip compressed data.
@interface NSData (Zlib)
- (NSData *)zlibCompressed;
- (NSData *)gzipCompressed;
@end

View File

@@ -0,0 +1,66 @@
/// 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.
#import "NSData+Zlib.h"
#import <zlib.h>
@implementation NSData (Zlib)
- (NSData *)compressIncludingGzipHeader:(BOOL)includeHeader {
if ([self length]) {
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = (uint)[self length];
stream.next_in = (Bytef *)[self bytes];
stream.total_out = 0;
stream.avail_out = 0;
int chunkSize = 16384;
int windowSize = 15;
if (includeHeader) {
windowSize += 16;
}
if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, windowSize, 8, Z_DEFAULT_STRATEGY) == Z_OK) {
NSMutableData *data = [NSMutableData dataWithLength:chunkSize];
while (stream.avail_out == 0) {
if (stream.total_out >= [data length]) {
data.length += chunkSize;
}
stream.next_out = (uint8_t *)[data mutableBytes] + stream.total_out;
stream.avail_out = (uInt)([data length] - stream.total_out);
deflate(&stream, Z_FINISH);
}
deflateEnd(&stream);
data.length = stream.total_out;
return data;
}
}
return nil;
}
- (NSData *)zlibCompressed {
return [self compressIncludingGzipHeader:NO];
}
- (NSData *)gzipCompressed {
return [self compressIncludingGzipHeader:YES];
}
@end

View File

@@ -29,6 +29,11 @@
///
@property(nonatomic) NSString *userAgent;
///
/// If set to YES, this session refuses redirect requests. Defaults to NO.
///
@property(nonatomic) BOOL refusesRedirects;
///
/// If set, the server that we connect to _must_ match this string. Redirects to other
/// hosts will not be allowed.

View File

@@ -15,7 +15,6 @@
#import "SNTAuthenticatingURLSession.h"
#import "SNTCertificate.h"
#import "SNTConfigurator.h"
#import "SNTDERDecoder.h"
#import "SNTLogging.h"
@@ -107,6 +106,18 @@
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest *))completionHandler {
if (self.refusesRedirects) {
completionHandler(NULL);
} else {
completionHandler(request);
}
}
#pragma mark Private Helpers for URLSession:didReceiveChallenge:completionHandler:
///
@@ -152,6 +163,7 @@
}
foundIdentity = (__bridge SecIdentityRef)identities[0][(__bridge id)kSecImportItemIdentity];
CFRetain(foundIdentity);
} else {
CFArrayRef cfIdentities;
err = SecItemCopyMatching((__bridge CFDictionaryRef)@{
@@ -186,6 +198,7 @@
if ([clientCert.commonName compare:self.clientCertCommonName
options:NSCaseInsensitiveSearch] == NSOrderedSame) {
foundIdentity = identityRef;
CFRetain(foundIdentity);
*stop = YES;
return; // return from enumeration block
}
@@ -193,6 +206,7 @@
if ([clientCert.issuerCommonName compare:self.clientCertIssuerCn
options:NSCaseInsensitiveSearch] == NSOrderedSame) {
foundIdentity = identityRef;
CFRetain(foundIdentity);
*stop = YES;
return; // return from enumeration block
}
@@ -206,6 +220,7 @@
[clientCert.issuerOrgUnit isEqual:decoder.organizationalUnit]) {
foundIdentity = identityRef;
CFRetain(foundIdentity);
*stop = YES;
return; // return from enumeration block
}
@@ -216,9 +231,12 @@
if (foundIdentity) {
LOGD(@"Client Trust: Valid client identity %@.", foundIdentity);
return [NSURLCredential credentialWithIdentity:foundIdentity
certificates:nil
persistence:NSURLCredentialPersistenceForSession];
NSURLCredential *cred =
[NSURLCredential credentialWithIdentity:foundIdentity
certificates:nil
persistence:NSURLCredentialPersistenceForSession];
CFRelease(foundIdentity);
return cred;
} else {
LOGD(@"Client Trust: No valid identity found.");
return nil;

View File

@@ -24,7 +24,6 @@
#import "SNTConfigurator.h"
#import "SNTDropRootPrivs.h"
#import "SNTLogging.h"
#import "SNTSystemInfo.h"
#import "SNTXPCConnection.h"
#import "SNTXPCControlInterface.h"
@@ -47,11 +46,11 @@ REGISTER_COMMAND_NAME(@"sync");
}
+ (NSString *)shortHelpText {
return @"Synchronizes Santa with the server";
return @"Synchronizes Santa with the server.";
}
+ (NSString *)longHelpText {
return @"";
return nil;
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
@@ -78,6 +77,7 @@ REGISTER_COMMAND_NAME(@"sync");
if (santactlVersion) {
authURLSession.userAgent = [authURLSession.userAgent stringByAppendingString:santactlVersion];
}
authURLSession.refusesRedirects = YES;
// Configure server auth
if ([config syncServerAuthRootsFile]) {
@@ -121,15 +121,17 @@ REGISTER_COMMAND_NAME(@"sync");
}
authURLSession.serverHostname = s.progress.syncBaseURL.host;
s.progress.machineID = config.machineIDOverride;
if (!s.progress.machineID || [s.progress.machineID isEqual:@""]) {
s.progress.machineID = [SNTSystemInfo hardwareUUID];
}
s.progress.machineID = config.machineID;
if (!s.progress.machineID || [s.progress.machineID isEqual:@""]) {
LOGE(@"Missing Machine ID. Can't sync without it.");
exit(1);
}
s.progress.machineOwner = config.machineOwner;
if (!s.progress.machineOwner) {
s.progress.machineOwner = @"";
LOGW(@"Missing Machine Owner.");
}
if (arguments.count == 2 && [[arguments firstObject] isEqual:@"singleevent"]) {
[s eventUploadSingleEvent:arguments[1]];

View File

@@ -143,6 +143,9 @@
ADDKEY(newEvent, @"file_bundle_version", event.fileBundleVersion);
ADDKEY(newEvent, @"file_bundle_version_string", event.fileBundleVersionString);
ADDKEY(newEvent, @"pid", event.pid);
ADDKEY(newEvent, @"ppid", event.ppid);
NSMutableArray *signingChain = [NSMutableArray arrayWithCapacity:event.signingChain.count];
for (int i = 0; i < event.signingChain.count; i++) {
SNTCertificate *cert = [event.signingChain objectAtIndex:i];

View File

@@ -14,12 +14,13 @@
#import "SNTCommandSyncLogUpload.h"
#import "NSData+Zlib.h"
#include "SNTCommonEnums.h"
#include "SNTLogging.h"
#import "SNTCommandSyncStatus.h"
@implementation SNTCommandSyncLogUpload
+ (void)performSyncInSession:(NSURLSession *)session
@@ -29,12 +30,47 @@
NSURL *url = progress.uploadLogURL;
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:url];
[req setHTTPMethod:@"POST"];
NSString *boundary = @"santa-sync-upload-boundary";
NSString *boundary = @"----santa-sync-upload-boundary";
NSString *contentType =
[NSString stringWithFormat:@"multipart/form-data; charset=UTF-8; boundary=%@", boundary];
[req setValue:contentType forHTTPHeaderField:@"Content-Type"];
// Prepare the body of the request, encoded as a multipart/form-data.
// Along the way, gzip the individual log files and append .gz to their filenames.
NSMutableData *reqBody = [[NSMutableData alloc] init];
NSArray *logsToUpload = [SNTCommandSyncLogUpload logsToUpload];
for (NSString *log in logsToUpload) {
[reqBody appendData:
[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[reqBody appendData:
[[NSString stringWithFormat:@"Content-Disposition: form-data; "
@"name=\"files\"; "
@"filename=\"%@.gz\"\r\n", [log lastPathComponent]]
dataUsingEncoding:NSUTF8StringEncoding]];
[reqBody appendData:
[@"Content-Type: application/x-gzip\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[reqBody appendData:[[NSData dataWithContentsOfFile:log] gzipCompressed]];
[reqBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}
[reqBody appendData:
[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// Upload the logs
[[session uploadTaskWithRequest:req
fromData:reqBody
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if ([(NSHTTPURLResponse *)response statusCode] != 200) {
LOGD(@"HTTP Response Code: %d", [(NSHTTPURLResponse *)response statusCode]);
handler(NO);
} else {
LOGI(@"Uploaded %d logs", [logsToUpload count]);
handler(YES);
}
}] resume];
}
+ (NSArray *)logsToUpload {
// General logs
NSMutableArray *logsToUpload = [@[ @"/var/log/santa.log",
@"/var/log/system.log" ] mutableCopy];
@@ -51,38 +87,7 @@
}
}
// Prepare the body of the request, encoded as a multipart/form-data.
// Along the way, gzip the individual log files (they'll be stored in blobstore gzipped, which is
// what we want) and append .gz to their filenames.
NSMutableData *reqBody = [[NSMutableData alloc] init];
for (NSString *log in logsToUpload) {
[reqBody appendData:
[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[reqBody appendData:
[[NSString stringWithFormat:@"Content-Disposition: multipart/form-data; "
@"name=\"files\"; "
@"filename=\"%@.gz\"\r\n", [log lastPathComponent]]
dataUsingEncoding:NSUTF8StringEncoding]];
[reqBody appendData:
[@"Content-Type: application/x-gzip\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[reqBody appendData:[NSData dataWithContentsOfFile:log]];
[reqBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}
[reqBody appendData:
[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// Upload the logs
[[session uploadTaskWithRequest:req
fromData:reqBody
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if ([(NSHTTPURLResponse *)response statusCode] != 200) {
LOGD(@"HTTP Response Code: %d", [(NSHTTPURLResponse *)response statusCode]);
handler(NO);
} else {
LOGI(@"Uploaded %d logs", [logsToUpload count]);
handler(YES);
}
}] resume];
return logsToUpload;
}
@end

View File

@@ -70,18 +70,31 @@
}
NSArray *receivedRules = resp[@"rules"];
for (NSDictionary *rule in receivedRules) {
if (![rule isKindOfClass:[NSDictionary class]]) continue;
SNTRule *newRule = [[SNTRule alloc] init];
newRule.shasum = rule[@"shasum"];
newRule.shasum = rule[@"sha256"];
newRule.state = [rule[@"state"] intValue];
if (newRule.state <= RULESTATE_UNKNOWN || newRule.state >= RULESTATE_MAX) continue;
if ([rule[@"policy"] isEqual:@"WHITELIST"]) {
newRule.state = RULESTATE_WHITELIST;
} else if ([rule[@"policy"] isEqual:@"BLACKLIST"]) {
newRule.state = RULESTATE_BLACKLIST;
} else if ([rule[@"policy"] isEqual:@"SILENT_BLACKLIST"]) {
newRule.state = RULESTATE_SILENT_BLACKLIST;
} else if ([rule[@"policy"] isEqual:@"REMOVE"]) {
newRule.state = RULESTATE_REMOVE;
} else {
continue;
}
newRule.type = [rule[@"type"] intValue];
if (newRule.type <= RULETYPE_UNKNOWN || newRule.type >= RULETYPE_MAX) continue;
if ([rule[@"rule_type"] isEqual:@"BINARY"]) {
newRule.type = RULETYPE_BINARY;
} else if ([rule[@"rule_type"] isEqual:@"CERTIFICATE"]) {
newRule.type = RULETYPE_CERT;
} else {
continue;
}
NSString *customMsg = rule[@"custom_msg"];
if (customMsg) {
@@ -100,7 +113,9 @@
completionHandler:handler];
} else {
[[daemonConn remoteObjectProxy] databaseRuleAddRules:progress.downloadedRules withReply:^{
LOGI(@"Added %d rule(s)", progress.downloadedRules.count);
if (progress.downloadedRules.count) {
LOGI(@"Added %d rule(s)", progress.downloadedRules.count);
}
handler(YES);
}];
}

View File

@@ -1,3 +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.
///
/// This is a simple ASN.1 decoder that utilizes Apple's SecAsn1Decode
/// to parse the @c distinguishedNames property of NSURLProtectionSpace.

View File

@@ -1,3 +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.
#import "SNTDERDecoder.h"
#import <Security/SecAsn1Coder.h>

View File

@@ -0,0 +1,88 @@
/// 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.
#import "SNTCommandController.h"
#include <IOKit/kext/KextManager.h>
#import "SNTFileInfo.h"
#import "SNTKernelCommon.h"
#import "SNTXPCConnection.h"
@interface SNTCommandVersion : NSObject<SNTCommand>
@end
@implementation SNTCommandVersion
REGISTER_COMMAND_NAME(@"version");
+ (BOOL)requiresRoot {
return NO;
}
+ (BOOL)requiresDaemonConn {
return NO;
}
+ (NSString *)shortHelpText {
return @"Show Santa component versions.";
}
+ (NSString *)longHelpText {
return nil;
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
printf("%-15s | %s\n", "santa-driver", [[self santaKextVersion] UTF8String]);
printf("%-15s | %s\n", "santad", [[self santadVersion] UTF8String]);
printf("%-15s | %s\n", "santactl", [[self santactlVersion] UTF8String]);
printf("%-15s | %s\n", "SantaGUI", [[self santaAppVersion] UTF8String]);
exit(0);
}
+ (NSString *)santaKextVersion {
NSDictionary *loadedKexts = CFBridgingRelease(
KextManagerCopyLoadedKextInfo((__bridge CFArrayRef)@[ @(USERCLIENT_ID) ],
(__bridge CFArrayRef)@[ @"CFBundleVersion" ])
);
if (loadedKexts[@(USERCLIENT_ID)] && loadedKexts[@(USERCLIENT_ID)][@"CFBundleVersion"]) {
return loadedKexts[@(USERCLIENT_ID)][@"CFBundleVersion"];
}
SNTFileInfo *driverInfo =
[[SNTFileInfo alloc] initWithPath:@"/Library/Extensions/santa-driver.kext"];
if (driverInfo) {
return [driverInfo.bundleVersion stringByAppendingString:@" (unloaded)"];
}
return @"not found";
}
+ (NSString *)santadVersion {
SNTFileInfo *daemonInfo = [[SNTFileInfo alloc] initWithPath:@"/usr/libexec/santad"];
return daemonInfo.bundleVersion;
}
+ (NSString *)santaAppVersion {
SNTFileInfo *guiInfo =
[[SNTFileInfo alloc] initWithPath:@"/Applications/Santa.app/Contents/MacOS/Santa"];
return guiInfo.bundleVersion;
}
+ (NSString *)santactlVersion {
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
}
@end

View File

@@ -82,19 +82,10 @@
[[SNTDaemonControlController alloc] initWithDriverManager:_driverManager];
[_controlConnection resume];
// Get client mode and begin observing for updates
SNTConfigurator *configurator = [SNTConfigurator configurator];
santa_clientmode_t clientMode = [configurator clientMode];
[configurator addObserver:self
forKeyPath:@"clientMode"
options:NSKeyValueObservingOptionNew
context:NULL];
// Initialize the binary checker object
_execController = [[SNTExecutionController alloc] initWithDriverManager:_driverManager
ruleTable:_ruleTable
eventTable:_eventTable
operatingMode:clientMode
notifierConnection:_notifierConnection];
if (!_execController) return nil;
}
@@ -102,20 +93,13 @@
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if ([keyPath isEqual:@"clientMode"]) {
self.execController.operatingMode = [change[NSKeyValueChangeNewKey] intValue];
}
}
- (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));
[self.driverManager listenWithBlock:^(santa_message_t message) {
@autoreleasepool {
@@ -138,6 +122,7 @@
[self.execController validateBinaryWithPath:@(message.path)
userName:userName
pid:@(message.pid)
ppid:@(message.ppid)
vnodeId:message.vnode_id];
});
break;

View File

@@ -21,6 +21,13 @@
///
@interface SNTDriverManager : NSObject
///
/// Handles locating and connecting to the driver. If driver is not loaded, will
/// sleep until it is. If driver is loaded but connection fails (like if a client is
/// already connected), will return nil.
///
- (instancetype)init;
///
/// Handles requests from the kernel using the given block.
/// @note Loops indefinitely unless there is an error trying to read data from the data queue.

View File

@@ -27,6 +27,8 @@
@implementation SNTDriverManager
static const int MAX_DELAY = 15;
#pragma mark init/dealloc
- (instancetype)init {
@@ -42,13 +44,15 @@
}
// Locate driver. Wait for it if necessary.
int delay = 1;
do {
CFRetain(classToMatch); // this ref is released by IOServiceGetMatchingService
serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, classToMatch);
if (!serviceObject) {
LOGD(@"Waiting for Santa driver to become available");
sleep(5);
sleep(delay);
if (delay < MAX_DELAY) delay *= 2;
}
} while (!serviceObject);
CFRelease(classToMatch);
@@ -104,8 +108,9 @@
return;
}
// This will call clientMemoryForType() inside our user client class,
// which activates the Kauth listeners.
// This will call clientMemoryForType() inside our user client class.
// The Kauth listener will start intercepting at this point and sending requests
// to our queue.
kr = IOConnectMapMemory(self.connection, kIODefaultMemoryType, mach_task_self(),
&address, &size, kIOMapAnywhere);
if (kr != kIOReturnSuccess) {

View File

@@ -37,12 +37,10 @@
@property SNTRuleTable *ruleTable;
@property SNTEventTable *eventTable;
@property SNTXPCConnection *notifierConnection;
@property santa_clientmode_t operatingMode;
- (instancetype)initWithDriverManager:(SNTDriverManager *)driverManager
ruleTable:(SNTRuleTable *)ruleTable
eventTable:(SNTEventTable *)eventTable
operatingMode:(santa_clientmode_t)operating_mode
notifierConnection:(SNTXPCConnection *)notifierConn;
///
@@ -53,11 +51,13 @@
/// @param path the binary that's being executed
/// @param userName the user who's executing the binary
/// @param pid the process id being executed
/// @param ppid the parent process id
/// @param vnoteId the id of the vnode being executed
///
- (void)validateBinaryWithPath:(NSString *)path
userName:(NSString *)userName
pid:(NSNumber *)pid
ppid:(NSNumber *)ppid
vnodeId:(uint64_t)vnodeId;

View File

@@ -20,6 +20,7 @@
#import "SNTCertificate.h"
#import "SNTCodesignChecker.h"
#import "SNTConfigurator.h"
#import "SNTDriverManager.h"
#import "SNTDropRootPrivs.h"
#import "SNTEventTable.h"
@@ -37,14 +38,12 @@
- (instancetype)initWithDriverManager:(SNTDriverManager *)driverManager
ruleTable:(SNTRuleTable *)ruleTable
eventTable:(SNTEventTable *)eventTable
operatingMode:(santa_clientmode_t)operatingMode
notifierConnection:(SNTXPCConnection *)notifier {
self = [super init];
if (self) {
_driverManager = driverManager;
_ruleTable = ruleTable;
_eventTable = eventTable;
_operatingMode = operatingMode;
_notifierConnection = notifier;
LOGI(@"Log format: Decision (A|D), Reason (B|C|S|?), SHA-256, Path, Cert SHA-256, Cert CN");
@@ -61,6 +60,7 @@
- (void)validateBinaryWithPath:(NSString *)path
userName:(NSString *)userName
pid:(NSNumber *)pid
ppid:(NSNumber *)ppid
vnodeId:(uint64_t)vnodeId {
SNTFileInfo *binInfo = [[SNTFileInfo alloc] initWithPath:path];
NSString *sha256 = [binInfo SHA256];
@@ -101,7 +101,9 @@
}
// Step 5 - log to database and potentially alert user
if (respondedAction == ACTION_RESPOND_CHECKBW_DENY || !rule) {
if (respondedAction == ACTION_RESPOND_CHECKBW_DENY ||
!rule ||
[[SNTConfigurator configurator] logAllEvents]) {
SNTStoredEvent *se = [[SNTStoredEvent alloc] init];
se.fileSHA256 = sha256;
se.filePath = path;
@@ -121,6 +123,7 @@
se.occurrenceDate = [[NSDate alloc] init];
se.decision = [self eventStateForDecision:respondedAction type:rule.type];
se.pid = pid;
se.ppid = ppid;
NSArray *loggedInUsers, *currentSessions;
[self loggedInUsers:&loggedInUsers sessions:&currentSessions];
@@ -263,7 +266,7 @@
}
- (santa_action_t)defaultDecision {
switch (self.operatingMode) {
switch ([[SNTConfigurator configurator] clientMode]) {
case CLIENTMODE_MONITOR:
return ACTION_RESPOND_CHECKBW_ALLOW;
case CLIENTMODE_LOCKDOWN:

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<data>
MIGcMQswCQYDVQQGEwJVUzERMA8GA1UECAwIVGhlIE1vb24xEjAQBgNVBAcMCU1vb24g
QmFzZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMSkwJwYDVQQLDCBB
d2Vzb21lIEF1dGhlbnRpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAwwPYXV0aC5zZXJ2
ZXIuY29t
</data>
</array>
</plist>

View File

@@ -80,9 +80,11 @@
XCTAssertEqualObjects(sut.commonName, @"Google Internet Authority G2");
XCTAssertEqualObjects(sut.orgUnit, nil);
XCTAssertEqualObjects(sut.orgName, @"Google Inc");
XCTAssertEqualObjects(sut.countryName, @"US");
XCTAssertEqualObjects(sut.issuerCommonName, @"GeoTrust Global CA");
XCTAssertEqualObjects(sut.issuerOrgName, @"GeoTrust Inc.");
XCTAssertEqualObjects(sut.issuerOrgUnit, nil);
XCTAssertEqualObjects(sut.issuerCountryName, @"US");
XCTAssertEqualObjects(sut.SHA1, @"d83c1a7f4d0446bb2081b81a1670f8183451ca24");
XCTAssertEqualObjects(sut.SHA256,
@"a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d");
@@ -97,6 +99,7 @@
@"Ulusal Elektronik ve Kriptoloji Araştırma Enstitüsü - UEKAE");
XCTAssertEqualObjects(sut.orgName,
@"Türkiye Bilimsel ve Teknolojik Araştırma Kurumu - TÜBİTAK");
XCTAssertEqualObjects(sut.countryName, @"TR");
}
- (void)testInitWithValidPEM {
@@ -219,14 +222,18 @@
(void)sut.orgName;
(void)sut.issuerCommonName;
(void)sut.validFrom;
(void)sut.countryName;
(void)sut.issuerCountryName;
// Now break some of the properties
OCMStub([sutMock x509ValueForLabel:OCMOCK_ANY fromDictionary:OCMOCK_ANY]);
OCMStub([sutMock dateForX509Key:OCMOCK_ANY]);
OCMExpect([sutMock x509ValueForLabel:OCMOCK_ANY fromDictionary:OCMOCK_ANY]);
OCMExpect([sutMock dateForX509Key:OCMOCK_ANY]);
XCTAssertEqualObjects(sut.orgName, @"Google Inc");
XCTAssertEqualObjects(sut.issuerCommonName, @"GeoTrust Global CA");
XCTAssertEqualObjects(sut.validFrom, [NSDate dateWithString:@"2013-04-05 15:15:55 +0000"]);
XCTAssertEqualObjects(sut.countryName, @"US");
XCTAssertEqualObjects(sut.issuerCountryName, @"US");
}
@end

View File

@@ -33,6 +33,17 @@
[super tearDown];
}
- (void)testAllFields {
NSString *file = [[NSBundle bundleForClass:[self class]] pathForResource:@"dn" ofType:@"plist"];
NSArray *distinguishedNames = [NSArray arrayWithContentsOfFile:file];
SNTDERDecoder *sut = [[SNTDERDecoder alloc] initWithData:[distinguishedNames firstObject]];
XCTAssertEqualObjects(sut.commonName, @"auth.server.com");
XCTAssertEqualObjects(sut.organizationName, @"Internet Widgits Pty Ltd");
XCTAssertEqualObjects(sut.organizationalUnit, @"Awesome Authentication Authority");
XCTAssertEqualObjects(sut.countryName, @"US");
}
- (void)testOIDDecoding {
unsigned char oidBytes1[] = {0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x14};
NSString *oidStr = [SNTDERDecoder decodeOIDWithBytes:oidBytes1 length:sizeof(oidBytes1)];

View File

@@ -19,6 +19,7 @@
#import "SNTCertificate.h"
#import "SNTCodesignChecker.h"
#import "SNTConfigurator.h"
#import "SNTDriverManager.h"
#import "SNTEventTable.h"
#import "SNTFileInfo.h"
@@ -30,6 +31,7 @@
@end
@interface SNTExecutionControllerTest : XCTestCase
@property id mockConfigurator;
@property id mockCodesignChecker;
@property id mockDriverManager;
@property id mockFileInfo;
@@ -47,15 +49,25 @@
fclose(stdout);
self.mockCodesignChecker = OCMClassMock([SNTCodesignChecker class]);
OCMStub([self.mockCodesignChecker alloc]).andReturn(self.mockCodesignChecker);
OCMStub([self.mockCodesignChecker initWithBinaryPath:OCMOCK_ANY])
.andReturn(self.mockCodesignChecker);
self.mockConfigurator = OCMClassMock([SNTConfigurator class]);
OCMStub([self.mockConfigurator configurator]).andReturn(self.mockConfigurator);
self.mockDriverManager = OCMClassMock([SNTDriverManager class]);
self.mockFileInfo = OCMClassMock([SNTFileInfo class]);
self.mockFileInfo = OCMClassMock([SNTFileInfo class]);
OCMStub([self.mockFileInfo alloc]).andReturn(self.mockFileInfo);
OCMStub([self.mockFileInfo initWithPath:OCMOCK_ANY]).andReturn(self.mockFileInfo);
self.mockRuleDatabase = OCMClassMock([SNTRuleTable class]);
self.mockEventDatabase = OCMClassMock([SNTEventTable class]);
self.sut = [[SNTExecutionController alloc] initWithDriverManager:self.mockDriverManager
ruleTable:self.mockRuleDatabase
eventTable:self.mockEventDatabase
operatingMode:CLIENTMODE_MONITOR
notifierConnection:nil];
}
@@ -73,13 +85,16 @@
id mockSut = OCMPartialMock(self.sut);
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(YES);
OCMExpect([self.mockFileInfo SHA256]).andReturn(@"a");
SNTRule *rule = [[SNTRule alloc] init];
rule.state = RULESTATE_WHITELIST;
OCMStub([self.mockRuleDatabase binaryRuleForSHA256:@"a"]).andReturn(rule);
OCMExpect([self.mockRuleDatabase binaryRuleForSHA256:@"a"]).andReturn(rule);
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
@@ -90,17 +105,16 @@
id mockSut = OCMPartialMock(self.sut);
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(YES);
[[[self.mockFileInfo stub] andReturn:self.mockFileInfo] alloc];
(void)[[[self.mockFileInfo stub] andReturn:self.mockFileInfo] initWithPath:[OCMArg any]];
[[[self.mockFileInfo stub] andReturn:@"a"] SHA256];
OCMExpect([self.mockFileInfo SHA256]).andReturn(@"a");
SNTRule *rule = [[SNTRule alloc] init];
rule.state = RULESTATE_BLACKLIST;
OCMStub([self.mockRuleDatabase binaryRuleForSHA256:@"a"]).andReturn(rule);
OCMExpect([self.mockRuleDatabase binaryRuleForSHA256:@"a"]).andReturn(rule);
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_DENY
@@ -112,19 +126,17 @@
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(YES);
id cert = OCMClassMock([SNTCertificate class]);
OCMStub([self.mockCodesignChecker alloc]).andReturn(self.mockCodesignChecker);
OCMStub([self.mockCodesignChecker initWithBinaryPath:OCMOCK_ANY])
.andReturn(self.mockCodesignChecker);
OCMStub([self.mockCodesignChecker leafCertificate]).andReturn(cert);
OCMStub([cert SHA256]).andReturn(@"a");
OCMExpect([self.mockCodesignChecker leafCertificate]).andReturn(cert);
OCMExpect([cert SHA256]).andReturn(@"a");
SNTRule *rule = [[SNTRule alloc] init];
rule.state = RULESTATE_WHITELIST;
OCMStub([self.mockRuleDatabase certificateRuleForSHA256:@"a"]).andReturn(rule);
OCMExpect([self.mockRuleDatabase certificateRuleForSHA256:@"a"]).andReturn(rule);
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
@@ -136,19 +148,17 @@
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(YES);
id cert = OCMClassMock([SNTCertificate class]);
OCMStub([self.mockCodesignChecker alloc]).andReturn(self.mockCodesignChecker);
OCMStub([self.mockCodesignChecker initWithBinaryPath:OCMOCK_ANY])
.andReturn(self.mockCodesignChecker);
OCMStub([self.mockCodesignChecker leafCertificate]).andReturn(cert);
OCMStub([cert SHA256]).andReturn(@"a");
OCMExpect([self.mockCodesignChecker leafCertificate]).andReturn(cert);
OCMExpect([cert SHA256]).andReturn(@"a");
SNTRule *rule = [[SNTRule alloc] init];
rule.state = RULESTATE_BLACKLIST;
OCMStub([self.mockRuleDatabase certificateRuleForSHA256:@"a"]).andReturn(rule);
OCMExpect([self.mockRuleDatabase certificateRuleForSHA256:@"a"]).andReturn(rule);
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_DENY
@@ -159,15 +169,20 @@
id mockSut = OCMPartialMock(self.sut);
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(YES);
[self.sut setOperatingMode:CLIENTMODE_MONITOR];
[self.sut validateBinaryWithPath:@"/a/file" userName:@"nobody" pid:@(12) vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
forVnodeID:1234]);
[self.sut setOperatingMode:CLIENTMODE_LOCKDOWN];
OCMExpect([self.mockConfigurator clientMode]).andReturn(CLIENTMODE_MONITOR);
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
forVnodeID:1234]);
OCMExpect([self.mockConfigurator clientMode]).andReturn(CLIENTMODE_LOCKDOWN);
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_DENY
forVnodeID:1234]);
@@ -177,8 +192,12 @@
id mockSut = OCMPartialMock(self.sut);
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(NO);
[self.sut setOperatingMode:CLIENTMODE_LOCKDOWN];
[self.sut validateBinaryWithPath:@"/a/file" userName:@"nobody" pid:@(24) vnodeId:1234];
OCMExpect([self.mockConfigurator clientMode]).andReturn(CLIENTMODE_LOCKDOWN);
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(24)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
forVnodeID:1234]);
}

View File

@@ -52,8 +52,8 @@
}
- (void)testInitClient {
OCMStub([self.mockConnection initWithMachServiceName:@"TestClient"
options:NSXPCConnectionPrivileged])
OCMExpect([self.mockConnection initWithMachServiceName:@"TestClient"
options:NSXPCConnectionPrivileged])
.andReturn(self.mockConnection);
SNTXPCConnection *sut = [[SNTXPCConnection alloc] initClientWithName:@"TestClient"
@@ -63,14 +63,14 @@
}
- (void)testInitServer {
OCMStub([self.mockListener initWithMachServiceName:@"TestServer"]).andReturn(self.mockListener);
OCMExpect([self.mockListener initWithMachServiceName:@"TestServer"]).andReturn(self.mockListener);
SNTXPCConnection *sut = [[SNTXPCConnection alloc] initServerWithName:@"TestServer"];
XCTAssertNotNil(sut);
OCMVerifyAll(self.mockListener);
}
- (void)testResume {
OCMStub([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
OCMExpect([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
SNTXPCConnection *sut = [[SNTXPCConnection alloc] initServerWithName:@"TestServer"];
[sut resume];
@@ -80,7 +80,7 @@
}
- (void)testListenerShouldAcceptNewConnection {
OCMStub([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
OCMExpect([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
SNTXPCConnection *sut = [[SNTXPCConnection alloc] initServerWithName:@"TestServer"];
XCTAssertTrue([sut listener:self.mockListener shouldAcceptNewConnection:self.mockConnection]);
@@ -93,16 +93,16 @@
}
- (void)testIsConnectionValidFalse {
OCMStub([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
OCMExpect([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
SNTXPCConnection *sut = [[SNTXPCConnection alloc] initServerWithName:@"TestServer"];
[sut setCurrentConnection:self.mockConnection];
OCMStub([self.mockConnection processIdentifier]).andReturn(1);
OCMExpect([self.mockConnection processIdentifier]).andReturn(1);
id mockCodesignChecker = OCMClassMock([SNTCodesignChecker class]);
OCMStub([mockCodesignChecker alloc]).andReturn(mockCodesignChecker);
OCMStub([mockCodesignChecker signingInformationMatches:OCMOCK_ANY]).andReturn(NO);
OCMExpect([mockCodesignChecker alloc]).andReturn(mockCodesignChecker);
OCMExpect([mockCodesignChecker signingInformationMatches:OCMOCK_ANY]).andReturn(NO);
[sut isConnectionValidWithBlock:^(BOOL input) {
XCTAssertFalse(input);
@@ -115,13 +115,13 @@
}
- (void)testIsConnectionValidTrue {
OCMStub([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
OCMExpect([self.mockListener initWithMachServiceName:OCMOCK_ANY]).andReturn(self.mockListener);
SNTXPCConnection *sut = [[SNTXPCConnection alloc] initServerWithName:@"TestServer"];
[sut setCurrentConnection:self.mockConnection];
pid_t mypid = [[NSProcessInfo processInfo] processIdentifier];
OCMStub([self.mockConnection processIdentifier]).andReturn(mypid);
OCMExpect([self.mockConnection processIdentifier]).andReturn(mypid);
[sut isConnectionValidWithBlock:^(BOOL input) {
XCTAssertTrue(input);