mirror of
https://github.com/google/santa.git
synced 2026-01-21 03:58:11 -05:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3b3d722b4 | ||
|
|
a82428958b | ||
|
|
b185632bda | ||
|
|
e7a0c3d25b | ||
|
|
ab33de2c15 | ||
|
|
a1031cdc27 | ||
|
|
e3ab3ca506 | ||
|
|
b4cd1ccbee | ||
|
|
14573a5714 | ||
|
|
96150a9668 | ||
|
|
c10c1303ed | ||
|
|
7852e69685 |
@@ -1,6 +1,6 @@
|
||||
# Copy this file to /etc/asl to log all messages from santa-driver to the log file
|
||||
> /var/log/santa.log format="[$((Time)(ISO8601Z.3))] $Message" mode=0644 rotate=seq compress file_max=25M all_max=100M uid=0 gid=0
|
||||
> /var/db/santa/santa.log format="[$((Time)(ISO8601Z.3))] $Message" mode=0644 rotate=seq compress file_max=25M all_max=100M uid=0 gid=0
|
||||
? [= Sender kernel] [S= Message santa-driver:] claim
|
||||
? [= Sender kernel] [S= Message santa-driver:] file /var/log/santa.log
|
||||
? [= Sender kernel] [S= Message santa-driver:] file /var/db/santa/santa.log
|
||||
? [= Facility com.google.santa] claim
|
||||
? [= Facility com.google.santa] file /var/log/santa.log
|
||||
? [= Facility com.google.santa] file /var/db/santa/santa.log
|
||||
|
||||
5
Podfile
5
Podfile
@@ -11,6 +11,11 @@ target :santad do
|
||||
pod 'FMDB'
|
||||
pod 'MOLCertificate'
|
||||
pod 'MOLCodesignChecker'
|
||||
target :santabs do
|
||||
pod 'FMDB'
|
||||
pod 'MOLCertificate'
|
||||
pod 'MOLCodesignChecker'
|
||||
end
|
||||
end
|
||||
|
||||
target :santactl do
|
||||
|
||||
@@ -27,6 +27,6 @@ SPEC CHECKSUMS:
|
||||
MOLFCMClient: 13d8b42db9d750e772f09cc38fc453922fece09f
|
||||
OCMock: 35ae71d6a8fcc1b59434d561d1520b9dd4f15765
|
||||
|
||||
PODFILE CHECKSUM: 1728b86e95e7cdb481dd91ab9c38af38e060a023
|
||||
PODFILE CHECKSUM: acd378b3727c923d912e09812da344f7375c14fe
|
||||
|
||||
COCOAPODS: 1.2.0
|
||||
COCOAPODS: 1.2.1
|
||||
|
||||
1
Rakefile
1
Rakefile
@@ -106,6 +106,7 @@ namespace :install do
|
||||
system 'sudo cp conf/com.google.santad.plist /Library/LaunchDaemons'
|
||||
system 'sudo cp conf/com.google.santagui.plist /Library/LaunchAgents'
|
||||
system 'sudo cp conf/com.google.santa.asl.conf /etc/asl'
|
||||
system '/usr/bin/killall -HUP syslogd'
|
||||
Rake::Task['build:build'].invoke(config)
|
||||
puts "Installing with configuration: #{config}"
|
||||
Rake::Task['remove_existing'].invoke()
|
||||
|
||||
@@ -154,23 +154,40 @@
|
||||
0DEFB7C81ACF0BFE00B92AAE /* SNTFileWatcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DEFB7C71ACF0BFE00B92AAE /* SNTFileWatcherTest.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 */; };
|
||||
168A4E09A2A5E0B7DF8A2F1A /* libPods-santad.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C11A10A5D6E112788769CF70 /* libPods-santad.a */; };
|
||||
4092327A1A51B66400A04527 /* SNTCommandRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 409232791A51B65D00A04527 /* SNTCommandRule.m */; };
|
||||
42805FED981952EC9F0E4272 /* libPods-santactl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC914D8DD0F5C0E21DA45150 /* libPods-santactl.a */; };
|
||||
7E396F5897B914399A568D27 /* libPods-Santa.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8FE66FA803110026A2A57C59 /* libPods-Santa.a */; };
|
||||
8E6BE2EABCDF090F0FCEA980 /* libPods-santad.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E57A355BC439804E082B9C0A /* libPods-santad.a */; };
|
||||
C4F8326EEB58061C1A579F0D /* libPods-LogicTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EAD1E725C5F299F58F754D7 /* libPods-LogicTests.a */; };
|
||||
59D56CF2D9C5BD9B7E3CC56D /* libPods-santad-santabs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14B98F4051188ECB7D024331 /* libPods-santad-santabs.a */; };
|
||||
B352A545B76783D568A6D0C5 /* libPods-Santa.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90E9D568200AB9B642E06272 /* libPods-Santa.a */; };
|
||||
C714F8B11D8044D400700EDF /* SNTCommandFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */; };
|
||||
C714F8B21D8044FE00700EDF /* SNTCommandController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDAB18FD7CFD00921A21 /* SNTCommandController.m */; };
|
||||
C72E8D941D7F399900C86DD3 /* SNTCommandFileInfoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = C72E8D931D7F399900C86DD3 /* SNTCommandFileInfoTest.m */; };
|
||||
C73A4B9A1DC10753007B6789 /* SNTSyncdQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56FF1DBFC213004E14EF /* SNTSyncdQueue.m */; };
|
||||
C73A4B9B1DC10758007B6789 /* SNTXPCSyncdInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56F51DBFB480004E14EF /* SNTXPCSyncdInterface.m */; };
|
||||
C7479F051E53704E0054C1CF /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; };
|
||||
C7479F071E5374BF0054C1CF /* SNTXPCControlInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD605419115D17006B445C /* SNTXPCControlInterface.m */; };
|
||||
C7479F091E5374E50054C1CF /* SNTRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE50F671912716A007B2B0C /* SNTRule.m */; };
|
||||
C74D6CC61EEB3B9B00BB5A33 /* BundleExample.app in Resources */ = {isa = PBXBuildFile; fileRef = C74D6CC51EEB3B9B00BB5A33 /* BundleExample.app */; };
|
||||
C76614EC1D142D3C00D150C1 /* SNTCommandCheckCache.m in Sources */ = {isa = PBXBuildFile; fileRef = C76614EB1D142D3C00D150C1 /* SNTCommandCheckCache.m */; };
|
||||
C776A1071DEE160500A56616 /* SNTCommandSyncManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C776A1061DEE160500A56616 /* SNTCommandSyncManager.m */; };
|
||||
C78227631E1C3C7D006EB2D6 /* santabs.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = C78227541E1C3C58006EB2D6 /* santabs.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
C795ED901D80A5BE007CFF42 /* SNTPolicyProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */; };
|
||||
C795ED911D80B66B007CFF42 /* SNTPolicyProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */; };
|
||||
C79A23581E23F7E80037AFA8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C79A23561E23F7E80037AFA8 /* main.m */; };
|
||||
C7BBA67E1E54C7E200F1E6A8 /* SNTXPCNotifierInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604E19115A06006B445C /* SNTXPCNotifierInterface.m */; };
|
||||
C7C721AE1E23FCB50051FAA6 /* SNTBundleService.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721AD1E23FCB50051FAA6 /* SNTBundleService.m */; };
|
||||
C7C721B11E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; };
|
||||
C7C721B21E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; };
|
||||
C7C721B31E2400310051FAA6 /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; };
|
||||
C7C721B41E24042B0051FAA6 /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
|
||||
C7C721B51E2408BE0051FAA6 /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
|
||||
C7C721B61E2408C30051FAA6 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; };
|
||||
C7DA62F71E241938009BDF2C /* SNTXPCBundleServiceInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */; };
|
||||
C7DA62F91E241A02009BDF2C /* SNTCommandBundleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = C7DA62F81E241A02009BDF2C /* SNTCommandBundleInfo.m */; };
|
||||
C7FB56F61DBFB480004E14EF /* SNTXPCSyncdInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56F51DBFB480004E14EF /* SNTXPCSyncdInterface.m */; };
|
||||
C7FB56F71DBFB480004E14EF /* SNTXPCSyncdInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56F51DBFB480004E14EF /* SNTXPCSyncdInterface.m */; };
|
||||
C7FB57001DBFC213004E14EF /* SNTSyncdQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = C7FB56FF1DBFC213004E14EF /* SNTSyncdQueue.m */; };
|
||||
D1761D2DAE8C790F29AFE6C9 /* libPods-LogicTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D949AA996AEAC326A4F6596 /* libPods-LogicTests.a */; };
|
||||
D6D356C5BC8709C2E355C113 /* libPods-santactl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E3B4B2438711ACD7D560014 /* libPods-santactl.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -230,6 +247,13 @@
|
||||
remoteGlobalIDString = 0D35BD9D18FD71CE00921A21;
|
||||
remoteInfo = santactl;
|
||||
};
|
||||
C7089E801EA1404900D0E1DC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0D91BCA8174E8A6500131A7D /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = C78227531E1C3C58006EB2D6;
|
||||
remoteInfo = santabs;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@@ -244,10 +268,19 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C78227621E1C3C70006EB2D6 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
C78227631E1C3C7D006EB2D6 /* santabs.xpc in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
07B44952FAAF4CA056FC4A62 /* 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>"; };
|
||||
0D0016A2192BCD3C005E7FCD /* KernelTests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KernelTests; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0D0016A5192BCD3C005E7FCD /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
|
||||
0D0A1EC1191998C900B8450F /* SNTCommandSyncRuleDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncRuleDownload.h; sourceTree = "<group>"; };
|
||||
@@ -386,28 +419,41 @@
|
||||
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; };
|
||||
3EAD1E725C5F299F58F754D7 /* libPods-LogicTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LogicTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
14B98F4051188ECB7D024331 /* libPods-santad-santabs.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santad-santabs.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
29DEB147E07B3D5E61674D49 /* Pods-santad.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad.release.xcconfig"; path = "Pods/Target Support Files/Pods-santad/Pods-santad.release.xcconfig"; sourceTree = "<group>"; };
|
||||
351CEE7AC20DDB0345A706BE /* Pods-LogicTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LogicTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-LogicTests/Pods-LogicTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
409232791A51B65D00A04527 /* SNTCommandRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandRule.m; sourceTree = "<group>"; };
|
||||
5123AB484639A3640D62CB67 /* Pods-santactl.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santactl.release.xcconfig"; path = "Pods/Target Support Files/Pods-santactl/Pods-santactl.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5B0D17672432F610DE7F14EA /* 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>"; };
|
||||
6519E416CC4D06EE85DDB34B /* Pods-Santa.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Santa.release.xcconfig"; path = "Pods/Target Support Files/Pods-Santa/Pods-Santa.release.xcconfig"; sourceTree = "<group>"; };
|
||||
6A947802FC1698EC37A47F5C /* Pods-santactl.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santactl.debug.xcconfig"; path = "Pods/Target Support Files/Pods-santactl/Pods-santactl.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
8FE66FA803110026A2A57C59 /* libPods-Santa.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Santa.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A5C68436912C0F98A7DE3BFA /* Pods-LogicTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LogicTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-LogicTests/Pods-LogicTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
4E3B4B2438711ACD7D560014 /* libPods-santactl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santactl.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
670AD2EB5E3572321B058D02 /* Pods-Santa.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Santa.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Santa/Pods-Santa.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
6C489E087A247B24480DB954 /* 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>"; };
|
||||
7D949AA996AEAC326A4F6596 /* libPods-LogicTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LogicTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8EF10E4B8C86CED022C72F1B /* Pods-santactl.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santactl.debug.xcconfig"; path = "Pods/Target Support Files/Pods-santactl/Pods-santactl.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
90E9D568200AB9B642E06272 /* libPods-Santa.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Santa.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A6A91785C40257CC156B4F05 /* Pods-Santa.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Santa.release.xcconfig"; path = "Pods/Target Support Files/Pods-Santa/Pods-Santa.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C11A10A5D6E112788769CF70 /* libPods-santad.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santad.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C72E8D931D7F399900C86DD3 /* SNTCommandFileInfoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandFileInfoTest.m; sourceTree = "<group>"; };
|
||||
C74D6CC51EEB3B9B00BB5A33 /* BundleExample.app */ = {isa = PBXFileReference; lastKnownFileType = wrapper.application; path = BundleExample.app; sourceTree = "<group>"; };
|
||||
C76614EB1D142D3C00D150C1 /* SNTCommandCheckCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandCheckCache.m; sourceTree = "<group>"; };
|
||||
C776A1051DEE160500A56616 /* SNTCommandSyncManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncManager.h; sourceTree = "<group>"; };
|
||||
C776A1061DEE160500A56616 /* SNTCommandSyncManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandSyncManager.m; sourceTree = "<group>"; };
|
||||
C78227541E1C3C58006EB2D6 /* santabs.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = santabs.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C795ED8E1D80A5BE007CFF42 /* SNTPolicyProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTPolicyProcessor.h; sourceTree = "<group>"; };
|
||||
C795ED8F1D80A5BE007CFF42 /* SNTPolicyProcessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTPolicyProcessor.m; sourceTree = "<group>"; };
|
||||
C79A23561E23F7E80037AFA8 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
C79A235A1E23F8820037AFA8 /* santabs-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "santabs-Info.plist"; sourceTree = "<group>"; };
|
||||
C7C721AC1E23FCB50051FAA6 /* SNTBundleService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTBundleService.h; sourceTree = "<group>"; };
|
||||
C7C721AD1E23FCB50051FAA6 /* SNTBundleService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTBundleService.m; sourceTree = "<group>"; };
|
||||
C7C721AF1E23FF300051FAA6 /* SNTXPCBundleServiceInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCBundleServiceInterface.h; sourceTree = "<group>"; };
|
||||
C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCBundleServiceInterface.m; sourceTree = "<group>"; };
|
||||
C7DA62F81E241A02009BDF2C /* SNTCommandBundleInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandBundleInfo.m; sourceTree = "<group>"; };
|
||||
C7FB56F41DBFB480004E14EF /* SNTXPCSyncdInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCSyncdInterface.h; sourceTree = "<group>"; };
|
||||
C7FB56F51DBFB480004E14EF /* SNTXPCSyncdInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCSyncdInterface.m; sourceTree = "<group>"; };
|
||||
C7FB56FE1DBFC213004E14EF /* SNTSyncdQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTSyncdQueue.h; sourceTree = "<group>"; };
|
||||
C7FB56FF1DBFC213004E14EF /* SNTSyncdQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTSyncdQueue.m; sourceTree = "<group>"; };
|
||||
DC914D8DD0F5C0E21DA45150 /* libPods-santactl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santactl.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E57A355BC439804E082B9C0A /* libPods-santad.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santad.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F1E491F3C201A2362E04FF81 /* Pods-santad.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad.release.xcconfig"; path = "Pods/Target Support Files/Pods-santad/Pods-santad.release.xcconfig"; sourceTree = "<group>"; };
|
||||
F25BED2D82EB26743AD59464 /* Pods-Santa.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Santa.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Santa/Pods-Santa.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D7DEE68F05C49966396A2F10 /* Pods-santad-santabs.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad-santabs.release.xcconfig"; path = "Pods/Target Support Files/Pods-santad-santabs/Pods-santad-santabs.release.xcconfig"; sourceTree = "<group>"; };
|
||||
D9B2D7095028D87E12E63EF7 /* Pods-santad-santabs.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad-santabs.debug.xcconfig"; path = "Pods/Target Support Files/Pods-santad-santabs/Pods-santad-santabs.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
DF5FE88E12AB307864A53CE7 /* Pods-santactl.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santactl.release.xcconfig"; path = "Pods/Target Support Files/Pods-santactl/Pods-santactl.release.xcconfig"; sourceTree = "<group>"; };
|
||||
E9FBFC5E3E1B268E4B453C9D /* 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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -423,7 +469,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0D202D1E1CDD479400A88F16 /* libz.tbd in Frameworks */,
|
||||
C4F8326EEB58061C1A579F0D /* libPods-LogicTests.a in Frameworks */,
|
||||
D1761D2DAE8C790F29AFE6C9 /* libPods-LogicTests.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -432,7 +478,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0DF395661AB76ABC00CBC520 /* libz.dylib in Frameworks */,
|
||||
42805FED981952EC9F0E4272 /* libPods-santactl.a in Frameworks */,
|
||||
D6D356C5BC8709C2E355C113 /* libPods-santactl.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -440,7 +486,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7E396F5897B914399A568D27 /* libPods-Santa.a in Frameworks */,
|
||||
B352A545B76783D568A6D0C5 /* libPods-Santa.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -448,7 +494,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8E6BE2EABCDF090F0FCEA980 /* libPods-santad.a in Frameworks */,
|
||||
168A4E09A2A5E0B7DF8A2F1A /* libPods-santad.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -459,6 +505,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C78227511E1C3C58006EB2D6 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
59D56CF2D9C5BD9B7E3CC56D /* libPods-santad-santabs.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@@ -491,6 +545,7 @@
|
||||
0D260DB018B68E12002A0B55 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C74D6CC51EEB3B9B00BB5A33 /* BundleExample.app */,
|
||||
0D536ED51B8E7A2E0039A26D /* bad_pagezero */,
|
||||
0D2CD4601A81C7B100C9C910 /* dn.plist */,
|
||||
0D536ED61B8E7A2E0039A26D /* missing_pagezero */,
|
||||
@@ -608,8 +663,8 @@
|
||||
0DB77FDC1CD262F5004DF060 /* Source */,
|
||||
0D789F9F1940F26D0036F7C4 /* Tests */,
|
||||
0D91BCB5174E8A7E00131A7D /* Products */,
|
||||
32B59E26727EF7DC0FC6A1C2 /* Pods */,
|
||||
8ADEC8FA6FDD43E921A3E0D6 /* Frameworks */,
|
||||
F6A64BBF2D62B24B58B2051B /* Pods */,
|
||||
65ABB276038B07159901CE5B /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -622,6 +677,7 @@
|
||||
0D260DAC18B68E12002A0B55 /* LogicTests.xctest */,
|
||||
0D35BD9E18FD71CE00921A21 /* santactl */,
|
||||
0D0016A2192BCD3C005E7FCD /* KernelTests */,
|
||||
C78227541E1C3C58006EB2D6 /* santabs.xpc */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -682,6 +738,8 @@
|
||||
0D5058CF1CB70123008784BA /* SNTStrengthify.h */,
|
||||
0D42D2B319D1D98A00955F08 /* SNTSystemInfo.h */,
|
||||
0D42D2B419D1D98A00955F08 /* SNTSystemInfo.m */,
|
||||
C7C721AF1E23FF300051FAA6 /* SNTXPCBundleServiceInterface.h */,
|
||||
C7C721B01E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m */,
|
||||
0D6FDC9418C93A020044685C /* SNTXPCConnection.h */,
|
||||
0D6FDC9518C93A020044685C /* SNTXPCConnection.m */,
|
||||
0DCD605319115D17006B445C /* SNTXPCControlInterface.h */,
|
||||
@@ -748,6 +806,7 @@
|
||||
0DAF01141C1B794B00F5B6C3 /* Commands */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C7DA62F81E241A02009BDF2C /* SNTCommandBundleInfo.m */,
|
||||
C76614EB1D142D3C00D150C1 /* SNTCommandCheckCache.m */,
|
||||
0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */,
|
||||
0DE4C8A518FF3B1700466D04 /* SNTCommandFlushCache.m */,
|
||||
@@ -765,6 +824,7 @@
|
||||
0D91BCD5174E8AAB00131A7D /* common */,
|
||||
0D91BCB9174E8A7E00131A7D /* santa-driver */,
|
||||
0D9A7F401759330500035EB5 /* santad */,
|
||||
C79A23541E23F7E80037AFA8 /* santabs */,
|
||||
0D35BDA018FD71CE00921A21 /* santactl */,
|
||||
0D385DBD180DE4A900418BC6 /* SantaGUI */,
|
||||
0D2429471E787655005C6FC9 /* DevelopmentTeam.xcconfig */,
|
||||
@@ -772,32 +832,54 @@
|
||||
path = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
32B59E26727EF7DC0FC6A1C2 /* Pods */ = {
|
||||
65ABB276038B07159901CE5B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B0D17672432F610DE7F14EA /* Pods-LogicTests.debug.xcconfig */,
|
||||
A5C68436912C0F98A7DE3BFA /* Pods-LogicTests.release.xcconfig */,
|
||||
F25BED2D82EB26743AD59464 /* Pods-Santa.debug.xcconfig */,
|
||||
6519E416CC4D06EE85DDB34B /* Pods-Santa.release.xcconfig */,
|
||||
6A947802FC1698EC37A47F5C /* Pods-santactl.debug.xcconfig */,
|
||||
5123AB484639A3640D62CB67 /* Pods-santactl.release.xcconfig */,
|
||||
07B44952FAAF4CA056FC4A62 /* Pods-santad.debug.xcconfig */,
|
||||
F1E491F3C201A2362E04FF81 /* Pods-santad.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8ADEC8FA6FDD43E921A3E0D6 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EAD1E725C5F299F58F754D7 /* libPods-LogicTests.a */,
|
||||
8FE66FA803110026A2A57C59 /* libPods-Santa.a */,
|
||||
DC914D8DD0F5C0E21DA45150 /* libPods-santactl.a */,
|
||||
E57A355BC439804E082B9C0A /* libPods-santad.a */,
|
||||
7D949AA996AEAC326A4F6596 /* libPods-LogicTests.a */,
|
||||
90E9D568200AB9B642E06272 /* libPods-Santa.a */,
|
||||
4E3B4B2438711ACD7D560014 /* libPods-santactl.a */,
|
||||
C11A10A5D6E112788769CF70 /* libPods-santad.a */,
|
||||
14B98F4051188ECB7D024331 /* libPods-santad-santabs.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C79A23541E23F7E80037AFA8 /* santabs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C79A23561E23F7E80037AFA8 /* main.m */,
|
||||
C7C721AC1E23FCB50051FAA6 /* SNTBundleService.h */,
|
||||
C7C721AD1E23FCB50051FAA6 /* SNTBundleService.m */,
|
||||
C79A23591E23F8820037AFA8 /* Resources */,
|
||||
);
|
||||
path = santabs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C79A23591E23F8820037AFA8 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C79A235A1E23F8820037AFA8 /* santabs-Info.plist */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F6A64BBF2D62B24B58B2051B /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C489E087A247B24480DB954 /* Pods-LogicTests.debug.xcconfig */,
|
||||
351CEE7AC20DDB0345A706BE /* Pods-LogicTests.release.xcconfig */,
|
||||
670AD2EB5E3572321B058D02 /* Pods-Santa.debug.xcconfig */,
|
||||
A6A91785C40257CC156B4F05 /* Pods-Santa.release.xcconfig */,
|
||||
8EF10E4B8C86CED022C72F1B /* Pods-santactl.debug.xcconfig */,
|
||||
DF5FE88E12AB307864A53CE7 /* Pods-santactl.release.xcconfig */,
|
||||
E9FBFC5E3E1B268E4B453C9D /* Pods-santad.debug.xcconfig */,
|
||||
29DEB147E07B3D5E61674D49 /* Pods-santad.release.xcconfig */,
|
||||
D9B2D7095028D87E12E63EF7 /* Pods-santad-santabs.debug.xcconfig */,
|
||||
D7DEE68F05C49966396A2F10 /* Pods-santad-santabs.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@@ -835,13 +917,13 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0D260DBC18B68E12002A0B55 /* Build configuration list for PBXNativeTarget "LogicTests" */;
|
||||
buildPhases = (
|
||||
C22A218D691E062A00781563 /* [CP] Check Pods Manifest.lock */,
|
||||
9BF8830B1029605A497F13D5 /* [CP] Check Pods Manifest.lock */,
|
||||
0D673DAD18FC9017009C5B06 /* Delete existing coverage files */,
|
||||
0D260DA818B68E12002A0B55 /* Sources */,
|
||||
0D260DA918B68E12002A0B55 /* Frameworks */,
|
||||
0D260DAA18B68E12002A0B55 /* Resources */,
|
||||
9F946EAD2A73FDCBE3FA3454 /* [CP] Embed Pods Frameworks */,
|
||||
43EC969A89E13A43B4161035 /* [CP] Copy Pods Resources */,
|
||||
D49A3AB950AFD99741E9AF89 /* [CP] Embed Pods Frameworks */,
|
||||
23869BA352E2C86DEFE62819 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -856,11 +938,11 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0D35BDA918FD71CE00921A21 /* Build configuration list for PBXNativeTarget "santactl" */;
|
||||
buildPhases = (
|
||||
8EF1E72D9F742F663ABE8DCD /* [CP] Check Pods Manifest.lock */,
|
||||
C936E88DFEEB9D1ED552BA97 /* [CP] Check Pods Manifest.lock */,
|
||||
0DD98E671A5DD02000A754C6 /* Update Version Info */,
|
||||
0D35BD9A18FD71CE00921A21 /* Sources */,
|
||||
0D35BD9B18FD71CE00921A21 /* Frameworks */,
|
||||
3AA84DD536CCE6A50E24E85E /* [CP] Copy Pods Resources */,
|
||||
2737FE8516A33567D3449943 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -875,13 +957,13 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0D385DE3180DE4A900418BC6 /* Build configuration list for PBXNativeTarget "Santa" */;
|
||||
buildPhases = (
|
||||
D5EF20F46A8F8B36E63D1709 /* [CP] Check Pods Manifest.lock */,
|
||||
B193461D3612BCB47C16E407 /* [CP] Check Pods Manifest.lock */,
|
||||
0DD98E681A5DD03E00A754C6 /* Update Version Info */,
|
||||
0D385DB2180DE4A900418BC6 /* Sources */,
|
||||
0D385DB3180DE4A900418BC6 /* Frameworks */,
|
||||
0D385DB4180DE4A900418BC6 /* Resources */,
|
||||
50E59E61A01D3126C43D49BB /* [CP] Embed Pods Frameworks */,
|
||||
F1D2415B87633FA13FC7AA29 /* [CP] Copy Pods Resources */,
|
||||
BA20035148DDEF5808B2C7EF /* [CP] Embed Pods Frameworks */,
|
||||
DDE76075391100F3BCE3634E /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -901,6 +983,7 @@
|
||||
0D91BCAE174E8A7E00131A7D /* Sources */,
|
||||
0D91BCB0174E8A7E00131A7D /* Headers */,
|
||||
0DC765E91B28D9CB00BAE651 /* CopyFiles */,
|
||||
C78227621E1C3C70006EB2D6 /* CopyFiles */,
|
||||
73FE93AEAAFA579D63B26D43 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
@@ -918,21 +1001,42 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0D9A7F471759330500035EB5 /* Build configuration list for PBXNativeTarget "santad" */;
|
||||
buildPhases = (
|
||||
828CFA7B34B9061FAFA68503 /* [CP] Check Pods Manifest.lock */,
|
||||
2146C1274A8C11B3755A8A67 /* [CP] Check Pods Manifest.lock */,
|
||||
0DD98E661A5DCED300A754C6 /* Update Version Info */,
|
||||
0D9A7F391759330400035EB5 /* Sources */,
|
||||
0D9A7F3A1759330400035EB5 /* Frameworks */,
|
||||
999D3C0A9B06CC3DFFB45CEA /* [CP] Copy Pods Resources */,
|
||||
531BBB5BA4BF953D628D29AB /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
C7089E811EA1404900D0E1DC /* PBXTargetDependency */,
|
||||
);
|
||||
name = santad;
|
||||
productName = santad;
|
||||
productReference = 0D9A7F3D1759330500035EB5 /* santad */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
C78227531E1C3C58006EB2D6 /* santabs */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C782275F1E1C3C58006EB2D6 /* Build configuration list for PBXNativeTarget "santabs" */;
|
||||
buildPhases = (
|
||||
1F3C2264A3EADEFC0DBE283E /* [CP] Check Pods Manifest.lock */,
|
||||
C7F95F971E23F9E7007A6BF5 /* Update bundle version */,
|
||||
C78227501E1C3C58006EB2D6 /* Sources */,
|
||||
C78227511E1C3C58006EB2D6 /* Frameworks */,
|
||||
C78227521E1C3C58006EB2D6 /* Resources */,
|
||||
FCF4BDAA180BD63C32AC85DE /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = santabs;
|
||||
productName = santabs;
|
||||
productReference = C78227541E1C3C58006EB2D6 /* santabs.xpc */;
|
||||
productType = "com.apple.product-type.xpc-service";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@@ -944,6 +1048,9 @@
|
||||
0D260DAB18B68E12002A0B55 = {
|
||||
TestTargetID = 0D385DB5180DE4A900418BC6;
|
||||
};
|
||||
C78227531E1C3C58006EB2D6 = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 0D91BCAB174E8A6500131A7D /* Build configuration list for PBXProject "Santa" */;
|
||||
@@ -963,6 +1070,7 @@
|
||||
0D91BCB3174E8A7E00131A7D /* santa-driver */,
|
||||
0D9A7F3C1759330400035EB5 /* santad */,
|
||||
0D35BD9D18FD71CE00921A21 /* santactl */,
|
||||
C78227531E1C3C58006EB2D6 /* santabs */,
|
||||
0D385DB5180DE4A900418BC6 /* Santa */,
|
||||
0D260DAB18B68E12002A0B55 /* LogicTests */,
|
||||
0D0016A1192BCD3C005E7FCD /* KernelTests */,
|
||||
@@ -977,6 +1085,7 @@
|
||||
files = (
|
||||
0DEA5F761CF6482E00704398 /* sync_eventupload_input_basic.plist in Resources */,
|
||||
0D536ED71B8E7A2E0039A26D /* bad_pagezero in Resources */,
|
||||
C74D6CC61EEB3B9B00BB5A33 /* BundleExample.app in Resources */,
|
||||
0DEA5F7A1CF64C9200704398 /* sync_ruledownload_batch1.json in Resources */,
|
||||
0DEA5F741CF63B9600704398 /* sync_eventupload_input_quarantine.plist in Resources */,
|
||||
0D2CD4611A81C7B100C9C910 /* dn.plist in Resources */,
|
||||
@@ -997,6 +1106,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C78227521E1C3C58006EB2D6 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
@@ -1093,22 +1209,37 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nsed -i '' \"s/TO.BE.FILLED/${GIT_TAG}/\" ${DERIVED_FILE_DIR}/santa-driver_info.c";
|
||||
};
|
||||
3AA84DD536CCE6A50E24E85E /* [CP] Copy Pods Resources */ = {
|
||||
1F3C2264A3EADEFC0DBE283E /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-santactl/Pods-santactl-resources.sh\"\n";
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
43EC969A89E13A43B4161035 /* [CP] Copy Pods Resources */ = {
|
||||
2146C1274A8C11B3755A8A67 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
23869BA352E2C86DEFE62819 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -1123,52 +1254,22 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LogicTests/Pods-LogicTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
50E59E61A01D3126C43D49BB /* [CP] Embed Pods Frameworks */ = {
|
||||
2737FE8516A33567D3449943 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Santa/Pods-Santa-frameworks.sh\"\n";
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-santactl/Pods-santactl-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
828CFA7B34B9061FAFA68503 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
8EF1E72D9F742F663ABE8DCD /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
999D3C0A9B06CC3DFFB45CEA /* [CP] Copy Pods Resources */ = {
|
||||
531BBB5BA4BF953D628D29AB /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -1183,7 +1284,84 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-santad/Pods-santad-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9F946EAD2A73FDCBE3FA3454 /* [CP] Embed Pods Frameworks */ = {
|
||||
9BF8830B1029605A497F13D5 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
B193461D3612BCB47C16E407 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
BA20035148DDEF5808B2C7EF /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Santa/Pods-Santa-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C7F95F971E23F9E7007A6BF5 /* Update bundle version */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/Source/santabs/Resources/santabs-Info.plist",
|
||||
);
|
||||
name = "Update bundle version";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/santabs-Info.plist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\nnewVersion=\"${GIT_TAG}d ${GIT_COMMIT}\"\nelse\nnewVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C936E88DFEEB9D1ED552BA97 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D49A3AB950AFD99741E9AF89 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -1198,37 +1376,7 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LogicTests/Pods-LogicTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C22A218D691E062A00781563 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D5EF20F46A8F8B36E63D1709 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F1D2415B87633FA13FC7AA29 /* [CP] Copy Pods Resources */ = {
|
||||
DDE76075391100F3BCE3634E /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -1243,6 +1391,21 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Santa/Pods-Santa-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FCF4BDAA180BD63C32AC85DE /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-santad-santabs/Pods-santad-santabs-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -1259,6 +1422,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C714F8B21D8044FE00700EDF /* SNTCommandController.m in Sources */,
|
||||
C7DA62F71E241938009BDF2C /* SNTXPCBundleServiceInterface.m in Sources */,
|
||||
C714F8B11D8044D400700EDF /* SNTCommandFileInfo.m in Sources */,
|
||||
0D88680C1AC48A1400B86659 /* SNTSystemInfo.m in Sources */,
|
||||
0D536EDC1B94E9230039A26D /* SNTEventLog.m in Sources */,
|
||||
@@ -1335,6 +1499,7 @@
|
||||
0D0A1EC3191998C900B8450F /* SNTCommandSyncRuleDownload.m in Sources */,
|
||||
0DB390991AB1E11400614002 /* SNTCommandVersion.m in Sources */,
|
||||
0D42D2B519D1D98A00955F08 /* SNTSystemInfo.m in Sources */,
|
||||
C7DA62F91E241A02009BDF2C /* SNTCommandBundleInfo.m in Sources */,
|
||||
0D827E6719DF3C74006EC811 /* SNTCommandStatus.m in Sources */,
|
||||
0D0A1EC6191AB9B000B8450F /* SNTCommandSyncPostflight.m in Sources */,
|
||||
0D35BDAC18FD7CFD00921A21 /* SNTCommandController.m in Sources */,
|
||||
@@ -1360,6 +1525,7 @@
|
||||
0D668E8118D1121700E29A8B /* SNTMessageWindow.m in Sources */,
|
||||
0DA73CA11934F8100056D7C4 /* SNTLogging.m in Sources */,
|
||||
0DEFB7C51ACDD80100B92AAE /* SNTFileWatcher.m in Sources */,
|
||||
C7479F051E53704E0054C1CF /* SNTXPCBundleServiceInterface.m in Sources */,
|
||||
0D20710E1A7C4A86008B0A9A /* SNTStoredEvent.m in Sources */,
|
||||
0DE2CE561CA05561002B649A /* SNTAccessibleTextField.m in Sources */,
|
||||
);
|
||||
@@ -1388,6 +1554,7 @@
|
||||
0DB8ACC1185662DC00FEF9C7 /* SNTApplication.m in Sources */,
|
||||
0D9A7F421759330500035EB5 /* main.m in Sources */,
|
||||
0DA73C9F1934F8100056D7C4 /* SNTLogging.m in Sources */,
|
||||
C7C721B11E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m in Sources */,
|
||||
0DE71A751B95F7F900518526 /* SNTCachedDecision.m in Sources */,
|
||||
C7FB56F61DBFB480004E14EF /* SNTXPCSyncdInterface.m in Sources */,
|
||||
0DCD6042190ACCB8006B445C /* SNTFileInfo.m in Sources */,
|
||||
@@ -1409,6 +1576,23 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C78227501E1C3C58006EB2D6 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C7C721B21E23FF300051FAA6 /* SNTXPCBundleServiceInterface.m in Sources */,
|
||||
C7C721B31E2400310051FAA6 /* SNTXPCConnection.m in Sources */,
|
||||
C7C721B61E2408C30051FAA6 /* SNTLogging.m in Sources */,
|
||||
C7C721B41E24042B0051FAA6 /* SNTStoredEvent.m in Sources */,
|
||||
C7C721B51E2408BE0051FAA6 /* SNTFileInfo.m in Sources */,
|
||||
C7BBA67E1E54C7E200F1E6A8 /* SNTXPCNotifierInterface.m in Sources */,
|
||||
C7479F071E5374BF0054C1CF /* SNTXPCControlInterface.m in Sources */,
|
||||
C7479F091E5374E50054C1CF /* SNTRule.m in Sources */,
|
||||
C79A23581E23F7E80037AFA8 /* main.m in Sources */,
|
||||
C7C721AE1E23FCB50051FAA6 /* SNTBundleService.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
@@ -1452,6 +1636,11 @@
|
||||
target = 0D35BD9D18FD71CE00921A21 /* santactl */;
|
||||
targetProxy = 0DC765E71B28D9C600BAE651 /* PBXContainerItemProxy */;
|
||||
};
|
||||
C7089E811EA1404900D0E1DC /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = C78227531E1C3C58006EB2D6 /* santabs */;
|
||||
targetProxy = C7089E801EA1404900D0E1DC /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
@@ -1530,7 +1719,7 @@
|
||||
};
|
||||
0D260DBA18B68E12002A0B55 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5B0D17672432F610DE7F14EA /* Pods-LogicTests.debug.xcconfig */;
|
||||
baseConfigurationReference = 6C489E087A247B24480DB954 /* Pods-LogicTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1578,7 +1767,7 @@
|
||||
};
|
||||
0D260DBB18B68E12002A0B55 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = A5C68436912C0F98A7DE3BFA /* Pods-LogicTests.release.xcconfig */;
|
||||
baseConfigurationReference = 351CEE7AC20DDB0345A706BE /* Pods-LogicTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1621,7 +1810,7 @@
|
||||
};
|
||||
0D35BDA718FD71CE00921A21 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 6A947802FC1698EC37A47F5C /* Pods-santactl.debug.xcconfig */;
|
||||
baseConfigurationReference = 8EF10E4B8C86CED022C72F1B /* Pods-santactl.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1659,7 +1848,7 @@
|
||||
};
|
||||
0D35BDA818FD71CE00921A21 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5123AB484639A3640D62CB67 /* Pods-santactl.release.xcconfig */;
|
||||
baseConfigurationReference = DF5FE88E12AB307864A53CE7 /* Pods-santactl.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1692,7 +1881,7 @@
|
||||
};
|
||||
0D385DE4180DE4A900418BC6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F25BED2D82EB26743AD59464 /* Pods-Santa.debug.xcconfig */;
|
||||
baseConfigurationReference = 670AD2EB5E3572321B058D02 /* Pods-Santa.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
@@ -1712,6 +1901,7 @@
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"SANTAGUI=1",
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
@@ -1731,7 +1921,7 @@
|
||||
};
|
||||
0D385DE5180DE4A900418BC6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 6519E416CC4D06EE85DDB34B /* Pods-Santa.release.xcconfig */;
|
||||
baseConfigurationReference = A6A91785C40257CC156B4F05 /* Pods-Santa.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
@@ -1750,6 +1940,11 @@
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"SANTAGUI=1",
|
||||
"$(inherited)",
|
||||
"COCOAPODS=1",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@@ -1907,7 +2102,7 @@
|
||||
};
|
||||
0D9A7F481759330500035EB5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 07B44952FAAF4CA056FC4A62 /* Pods-santad.debug.xcconfig */;
|
||||
baseConfigurationReference = E9FBFC5E3E1B268E4B453C9D /* Pods-santad.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1941,7 +2136,7 @@
|
||||
};
|
||||
0D9A7F491759330500035EB5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F1E491F3C201A2362E04FF81 /* Pods-santad.release.xcconfig */;
|
||||
baseConfigurationReference = 29DEB147E07B3D5E61674D49 /* Pods-santad.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1967,6 +2162,89 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C782275D1E1C3C58006EB2D6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D9B2D7095028D87E12E63EF7 /* Pods-santad-santabs.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santabs-Info.plist";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.google.santabs;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C782275E1E1C3C58006EB2D6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D7DEE68F05C49966396A2F10 /* Pods-santad-santabs.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santabs-Info.plist";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.google.santabs;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@@ -2042,6 +2320,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C782275F1E1C3C58006EB2D6 /* Build configuration list for PBXNativeTarget "santabs" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C782275D1E1C3C58006EB2D6 /* Debug */,
|
||||
C782275E1E1C3C58006EB2D6 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 0D91BCA8174E8A6500131A7D /* Project object */;
|
||||
|
||||
80
Santa.xcodeproj/xcshareddata/xcschemes/santabs.xcscheme
Normal file
80
Santa.xcodeproj/xcshareddata/xcschemes/santabs.xcscheme
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0730"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C78227531E1C3C58006EB2D6"
|
||||
BuildableName = "santabs.xpc"
|
||||
BlueprintName = "santabs"
|
||||
ReferencedContainer = "container:Santa.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C78227531E1C3C58006EB2D6"
|
||||
BuildableName = "santabs.xpc"
|
||||
BlueprintName = "santabs"
|
||||
ReferencedContainer = "container:Santa.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C78227531E1C3C58006EB2D6"
|
||||
BuildableName = "santabs.xpc"
|
||||
BlueprintName = "santabs"
|
||||
ReferencedContainer = "container:Santa.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="16D32" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="SNTAboutWindowController">
|
||||
@@ -16,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" closable="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="480" height="200"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1577"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="200"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<development version="6300" identifier="xcode"/>
|
||||
@@ -9,6 +9,9 @@
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="SNTMessageWindowController">
|
||||
<connections>
|
||||
<outlet property="applicationNameLabel" destination="qgf-Jf-cJr" id="1JX-X8-03v"/>
|
||||
<outlet property="bundleHashLabel" destination="xP7-jE-NF8" id="i8B-Gs-2E3"/>
|
||||
<outlet property="foundFileCountLabel" destination="LHV-gV-vyf" id="Sr0-T2-xGx"/>
|
||||
<outlet property="hashingIndicator" destination="VyY-Yg-JOe" id="Yq4-tZ-9ep"/>
|
||||
<outlet property="openEventButton" destination="7ua-5a-uSd" id="9s4-ZA-Vlo"/>
|
||||
<outlet property="window" destination="9Bq-yh-54f" id="Uhs-WF-TV9"/>
|
||||
</connections>
|
||||
@@ -17,14 +20,14 @@
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Santa Blocked Execution" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="none" id="9Bq-yh-54f" customClass="SNTMessageWindow">
|
||||
<windowStyleMask key="styleMask" utility="YES"/>
|
||||
<rect key="contentRect" x="167" y="107" width="497" height="439"/>
|
||||
<rect key="contentRect" x="167" y="107" width="540" height="479"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="Iwq-Lx-rLv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="497" height="439"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="540" height="479"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kiB-jZ-69S">
|
||||
<rect key="frame" x="-6" y="411" width="37" height="32"/>
|
||||
<rect key="frame" x="16" y="451" width="37" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Hidden Button" alternateTitle="This button exists so neither of the other two buttons is pre-selected when the dialog opens." bezelStyle="rounded" alignment="center" borderStyle="border" focusRingType="none" transparent="YES" imageScaling="proportionallyDown" inset="2" id="XGa-Sl-F4t">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -37,7 +40,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="t8c-Fx-e5h">
|
||||
<rect key="frame" x="206" y="368" width="85" height="41"/>
|
||||
<rect key="frame" x="228" y="408" width="85" height="41"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" refusesFirstResponder="YES" sendsActionOnEndEditing="YES" title="Santa" id="7YA-iB-Zma">
|
||||
<font key="font" metaFont="systemUltraLight" size="34"/>
|
||||
<color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
@@ -51,7 +54,7 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cD5-Su-lXR" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="22" y="329" width="454" height="17"/>
|
||||
<rect key="frame" x="43" y="369" width="454" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="450" id="XgJ-EV-tBa"/>
|
||||
</constraints>
|
||||
@@ -65,58 +68,10 @@
|
||||
<outlet property="nextKeyView" destination="7ua-5a-uSd" id="VC7-bE-uHc"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<box horizontalHuggingPriority="750" title="Line" boxType="custom" borderType="line" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="4Li-ul-zIi">
|
||||
<rect key="frame" x="146" y="132" width="1" height="167"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="1" id="0o1-Jh-epf"/>
|
||||
</constraints>
|
||||
<color key="borderColor" white="0.0" alpha="0.17999999999999999" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pDa-fA-vnC" userLabel="Label: Application">
|
||||
<rect key="frame" x="8" y="282" width="120" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="116" id="8mA-zi-Ev7"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Application" id="Hy7-WF-6xW">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.event.fileBundleName" id="r2Q-hh-Uy5">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSIsNil</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField toolTip="Application Name" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qgf-Jf-cJr" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="165" y="282" width="294" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="290" id="Pav-ZA-iAu"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Application Name" id="3UG-ca-d1k">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.event.fileBundleName" id="enC-Cl-UWt">
|
||||
<dictionary key="options">
|
||||
<string key="NSNullPlaceholder">Unknown</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d9e-Wv-Y5H" userLabel="Label: Path">
|
||||
<rect key="frame" x="8" y="257" width="120" height="17"/>
|
||||
<rect key="frame" x="8" y="297" width="142" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="116" id="Kqd-nX-7df"/>
|
||||
<constraint firstAttribute="width" constant="138" id="Kqd-nX-7df"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Filename" id="KgY-X1-ESG">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
@@ -128,9 +83,9 @@
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YNz-ka-cBi" userLabel="Label: Path">
|
||||
<rect key="frame" x="8" y="232" width="120" height="17"/>
|
||||
<rect key="frame" x="8" y="272" width="142" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="116" id="3wU-P0-gAC"/>
|
||||
<constraint firstAttribute="width" constant="138" id="3wU-P0-gAC"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Path" id="adC-be-Beh">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
@@ -141,10 +96,10 @@
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField toolTip="Binary Path" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pc8-G9-4pJ" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="165" y="257" width="294" height="17"/>
|
||||
<textField toolTip="Binary Name" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pc8-G9-4pJ" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="187" y="297" width="315" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="290" id="xVR-j3-dLw"/>
|
||||
<constraint firstAttribute="width" constant="311" id="xVR-j3-dLw"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Binary Name" id="E7T-9h-ofr">
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -156,7 +111,7 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lvJ-Rk-UT5" userLabel="Label: Publisher">
|
||||
<rect key="frame" x="8" y="207" width="120" height="17"/>
|
||||
<rect key="frame" x="8" y="247" width="142" 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"/>
|
||||
@@ -167,9 +122,9 @@
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField toolTip="Publisher" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C3G-wL-u7w" userLabel="Publisher" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="165" y="207" width="294" height="17"/>
|
||||
<rect key="frame" x="187" y="247" width="315" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="290" id="Dem-wH-KHm"/>
|
||||
<constraint firstAttribute="width" constant="311" id="Dem-wH-KHm"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Code signing information" placeholderString="" id="ztA-La-XgT">
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -185,7 +140,7 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<button toolTip="Show code signing certificate chain" translatesAutoresizingMaskIntoConstraints="NO" id="cJf-k6-OxS" userLabel="Publisher Certs Button">
|
||||
<rect key="frame" x="40" y="208" width="15" height="15"/>
|
||||
<rect key="frame" x="62" y="248" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="15" id="QTm-Iv-m5p"/>
|
||||
<constraint firstAttribute="height" constant="15" id="YwG-0s-jop"/>
|
||||
@@ -207,7 +162,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KEB-eH-x2Y" userLabel="Label: Identifier">
|
||||
<rect key="frame" x="8" y="182" width="120" height="17"/>
|
||||
<rect key="frame" x="8" y="222" width="142" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Identifier" id="eKN-Ic-5zy">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -217,8 +172,8 @@
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PXc-xv-A28">
|
||||
<rect key="frame" x="165" y="182" width="219" height="17"/>
|
||||
<textField toolTip="SHA-256" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PXc-xv-A28">
|
||||
<rect key="frame" x="187" y="222" width="219" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="215" id="4hh-R2-86s"/>
|
||||
</constraints>
|
||||
@@ -234,8 +189,26 @@
|
||||
<binding destination="-2" name="value" keyPath="self.event.fileSHA256" id="9KB-0b-qLV"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MhO-U0-MLR" userLabel="Label: Bundle Identifier">
|
||||
<rect key="frame" x="8" y="197" width="142" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Bundle Identifier" id="LEe-u0-52o">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.event.needsBundleHash" id="2kb-3z-Kyn">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="eQb-0a-76J" userLabel="Label: Parent">
|
||||
<rect key="frame" x="8" y="157" width="120" height="17"/>
|
||||
<rect key="frame" x="8" y="157" width="142" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Parent" id="gze-4A-1w5">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -246,7 +219,7 @@
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField toolTip="Parent Process" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="f1p-GL-O3o" userLabel="Parent" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="165" y="157" width="294" height="17"/>
|
||||
<rect key="frame" x="187" y="157" width="294" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="290" id="h3Y-mO-38F"/>
|
||||
</constraints>
|
||||
@@ -269,7 +242,7 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="oFj-ol-xpL" userLabel="Label: User">
|
||||
<rect key="frame" x="8" y="132" width="120" height="17"/>
|
||||
<rect key="frame" x="8" y="132" width="142" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="User" id="1ut-uT-hQD">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -279,26 +252,8 @@
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField toolTip="Executing User" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="h6f-PY-cc0" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="165" y="132" width="294" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="290" id="on6-pj-m2k"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Executing User" id="HRT-Be-ePf">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.event.executingUser" id="IcM-Lt-xTT">
|
||||
<dictionary key="options">
|
||||
<string key="NSNullPlaceholder">Unknown</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="7ua-5a-uSd">
|
||||
<rect key="frame" x="132" y="33" width="112" height="25"/>
|
||||
<rect key="frame" x="154" y="33" width="112" height="25"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" priority="900" constant="112" id="Pec-Pa-4aZ"/>
|
||||
</constraints>
|
||||
@@ -315,8 +270,35 @@ DQ
|
||||
<outlet property="nextKeyView" destination="BbV-3h-mmL" id="Xkz-va-iGc"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField toolTip="Binary Path" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bDE-Tl-UHg" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="187" y="272" width="315" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="311" id="p1W-f9-KBX"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Binary Path" id="H1b-Ui-CYo">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.event.filePath" id="Sry-KY-HDb"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="5D8-GP-a4l">
|
||||
<rect key="frame" x="113" y="80" width="315" height="29"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="25" id="KvD-X6-CsO"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="check" title="Prevent future notifications for this application for a day" bezelStyle="regularSquare" imagePosition="left" alignment="center" inset="2" id="R5Y-Uc-rEP">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.silenceFutureNotifications" id="tEb-2A-sht"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="BbV-3h-mmL" userLabel="Dismiss Button">
|
||||
<rect key="frame" x="256" y="33" width="110" height="25"/>
|
||||
<rect key="frame" x="278" 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"/>
|
||||
@@ -335,61 +317,138 @@ DQ
|
||||
<outlet property="nextKeyView" destination="7ua-5a-uSd" id="4KL-Z2-1op"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField toolTip="Binary Path" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bDE-Tl-UHg" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="165" y="232" width="294" height="17"/>
|
||||
<textField toolTip="Executing User" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="h6f-PY-cc0" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="187" y="132" width="294" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="290" id="p1W-f9-KBX"/>
|
||||
<constraint firstAttribute="width" constant="290" id="on6-pj-m2k"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Binary Path" id="H1b-Ui-CYo">
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Executing User" id="HRT-Be-ePf">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.event.filePath" id="Sry-KY-HDb"/>
|
||||
<binding destination="-2" name="value" keyPath="self.event.executingUser" id="IcM-Lt-xTT">
|
||||
<dictionary key="options">
|
||||
<string key="NSNullPlaceholder">Unknown</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="5D8-GP-a4l">
|
||||
<rect key="frame" x="91" y="80" width="315" height="29"/>
|
||||
<progressIndicator wantsLayer="YES" canDrawConcurrently="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" maxValue="1" bezeled="NO" controlSize="small" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="VyY-Yg-JOe">
|
||||
<rect key="frame" x="187" y="199" width="217" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="25" id="KvD-X6-CsO"/>
|
||||
<constraint firstAttribute="width" constant="217" id="M22-Dv-KIP"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="check" title="Prevent future notifications for this application for a day" bezelStyle="regularSquare" imagePosition="left" alignment="center" inset="2" id="R5Y-Uc-rEP">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
</buttonCell>
|
||||
</progressIndicator>
|
||||
<textField toolTip="Bundle SHA-256" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xP7-jE-NF8">
|
||||
<rect key="frame" x="187" y="197" width="219" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="215" id="s7W-o9-2nN"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" lineBreakMode="charWrapping" selectable="YES" sendsActionOnEndEditing="YES" title="Calculating..." id="yJa-yL-X9a">
|
||||
<font key="font" metaFont="fixedUser" size="11"/>
|
||||
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.silenceFutureNotifications" id="tEb-2A-sht"/>
|
||||
<binding destination="-2" name="value" keyPath="self.event.fileBundleHash" id="CnT-q6-bot"/>
|
||||
</connections>
|
||||
</button>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LHV-gV-vyf">
|
||||
<rect key="frame" x="187" y="182" width="219" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="215" id="LUu-Vd-peN"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1000 related binaries" id="AVM-vB-hB8">
|
||||
<font key="font" metaFont="fixedUser" size="11"/>
|
||||
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<box horizontalHuggingPriority="750" title="Line" boxType="custom" borderType="line" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="4Li-ul-zIi">
|
||||
<rect key="frame" x="168" y="132" width="1" height="207"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="1" id="0o1-Jh-epf"/>
|
||||
</constraints>
|
||||
<color key="borderColor" white="0.0" alpha="0.17999999999999999" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<textField toolTip="Application Name" verticalHuggingPriority="900" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qgf-Jf-cJr" customClass="SNTAccessibleTextField">
|
||||
<rect key="frame" x="187" y="322" width="315" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="311" id="Pav-ZA-iAu"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Application Name" id="3UG-ca-d1k">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.event.fileBundleName" id="enC-Cl-UWt">
|
||||
<dictionary key="options">
|
||||
<string key="NSNullPlaceholder">Unknown</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pDa-fA-vnC" userLabel="Label: Application">
|
||||
<rect key="frame" x="8" y="322" width="142" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="138" id="8mA-zi-Ev7"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Application" id="Hy7-WF-6xW">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.event.fileBundleName" id="r2Q-hh-Uy5">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSIsNil</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="0AD-PS-5V1"/>
|
||||
<constraint firstItem="f1p-GL-O3o" firstAttribute="centerY" secondItem="eQb-0a-76J" secondAttribute="centerY" id="2Aq-1E-Ybz"/>
|
||||
<constraint firstItem="BbV-3h-mmL" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" priority="500" constant="193" id="2uo-Cm-Tfp"/>
|
||||
<constraint firstItem="h6f-PY-cc0" firstAttribute="top" secondItem="f1p-GL-O3o" secondAttribute="bottom" constant="8" id="496-VQ-Fx5"/>
|
||||
<constraint firstItem="xP7-jE-NF8" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="5Mr-By-PAU"/>
|
||||
<constraint firstItem="pDa-fA-vnC" firstAttribute="centerY" secondItem="qgf-Jf-cJr" secondAttribute="centerY" id="AKX-pe-hEX"/>
|
||||
<constraint firstItem="C3G-wL-u7w" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="ALv-0v-szi"/>
|
||||
<constraint firstItem="f1p-GL-O3o" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="bottom" constant="8" id="E6D-7P-17g"/>
|
||||
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="FPe-Rd-G4n"/>
|
||||
<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="oFj-ol-xpL" firstAttribute="bottom" secondItem="4Li-ul-zIi" secondAttribute="bottom" id="G0I-O2-S91"/>
|
||||
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="leading" secondItem="cJf-k6-OxS" secondAttribute="trailing" constant="-45" id="GD2-Ka-deo"/>
|
||||
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="leading" secondItem="cJf-k6-OxS" secondAttribute="trailing" constant="-67" id="GD2-Ka-deo"/>
|
||||
<constraint firstItem="BbV-3h-mmL" firstAttribute="top" secondItem="5D8-GP-a4l" secondAttribute="bottom" priority="900" constant="25" id="GT2-tO-2td"/>
|
||||
<constraint firstItem="h6f-PY-cc0" firstAttribute="centerY" secondItem="oFj-ol-xpL" secondAttribute="centerY" id="GXI-pT-FM1"/>
|
||||
<constraint firstItem="4Li-ul-zIi" firstAttribute="top" secondItem="pDa-fA-vnC" secondAttribute="top" id="Gd4-Nr-n5G"/>
|
||||
<constraint firstItem="xP7-jE-NF8" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="bottom" constant="8" id="HUT-MI-jsR"/>
|
||||
<constraint firstItem="qgf-Jf-cJr" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="Ht4-Lg-U5N"/>
|
||||
<constraint firstItem="LHV-gV-vyf" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="IA0-dy-2be"/>
|
||||
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="IwX-ja-ZIs"/>
|
||||
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="top" secondItem="4Li-ul-zIi" secondAttribute="top" priority="500" id="JY4-N1-j8e"/>
|
||||
<constraint firstItem="YNz-ka-cBi" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="KmX-kX-VCN"/>
|
||||
<constraint firstItem="5D8-GP-a4l" firstAttribute="centerX" secondItem="Iwq-Lx-rLv" secondAttribute="centerX" id="LkH-F4-Ncm"/>
|
||||
<constraint firstItem="pc8-G9-4pJ" firstAttribute="top" secondItem="cD5-Su-lXR" secondAttribute="bottom" priority="950" constant="30" id="Nsl-zf-poH"/>
|
||||
<constraint firstItem="pc8-G9-4pJ" firstAttribute="top" secondItem="cD5-Su-lXR" secondAttribute="bottom" priority="950" constant="55" id="Nsl-zf-poH"/>
|
||||
<constraint firstItem="YNz-ka-cBi" firstAttribute="centerY" secondItem="bDE-Tl-UHg" secondAttribute="centerY" id="ObQ-RA-S5V"/>
|
||||
<constraint firstItem="pc8-G9-4pJ" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="SCl-Ky-VmT"/>
|
||||
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="centerY" secondItem="pc8-G9-4pJ" secondAttribute="centerY" id="SLv-F7-w5k"/>
|
||||
<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="LHV-gV-vyf" firstAttribute="top" secondItem="VyY-Yg-JOe" secondAttribute="bottom" id="Vjr-NX-j8V"/>
|
||||
<constraint firstItem="MhO-U0-MLR" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="Vly-VE-BwU"/>
|
||||
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="lvJ-Rk-UT5" secondAttribute="leading" priority="999" id="Z6G-l9-G4a"/>
|
||||
<constraint firstItem="C3G-wL-u7w" firstAttribute="top" secondItem="bDE-Tl-UHg" secondAttribute="bottom" constant="8" id="ZoS-xV-2WA"/>
|
||||
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="aMJ-Wb-vRS"/>
|
||||
@@ -401,22 +460,28 @@ DQ
|
||||
<constraint firstItem="qgf-Jf-cJr" firstAttribute="top" secondItem="cD5-Su-lXR" secondAttribute="bottom" constant="30" id="esg-lX-BAT"/>
|
||||
<constraint firstItem="f1p-GL-O3o" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="fGd-YS-phP"/>
|
||||
<constraint firstAttribute="centerX" secondItem="t8c-Fx-e5h" secondAttribute="centerX" id="h3d-Kc-q88"/>
|
||||
<constraint firstItem="f1p-GL-O3o" firstAttribute="top" secondItem="LHV-gV-vyf" secondAttribute="bottom" constant="8" id="h4h-K3-BTd"/>
|
||||
<constraint firstItem="f1p-GL-O3o" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="bottom" priority="700" constant="8" id="hXw-6Z-lb2"/>
|
||||
<constraint firstItem="BbV-3h-mmL" firstAttribute="leading" secondItem="7ua-5a-uSd" secondAttribute="trailing" constant="12" id="ioO-NJ-Jqo"/>
|
||||
<constraint firstItem="bDE-Tl-UHg" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="jdk-ak-soQ"/>
|
||||
<constraint firstItem="C3G-wL-u7w" firstAttribute="centerY" secondItem="lvJ-Rk-UT5" secondAttribute="centerY" id="jfs-YI-7Ae"/>
|
||||
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="oFj-ol-xpL" secondAttribute="trailing" constant="20" id="kOG-Cj-hFG"/>
|
||||
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="MhO-U0-MLR" secondAttribute="trailing" constant="20" id="ke9-wW-5fr"/>
|
||||
<constraint firstItem="pc8-G9-4pJ" firstAttribute="top" secondItem="qgf-Jf-cJr" secondAttribute="bottom" constant="8" id="lWU-tC-vWg"/>
|
||||
<constraint firstItem="5D8-GP-a4l" firstAttribute="top" secondItem="h6f-PY-cc0" secondAttribute="bottom" constant="25" id="lYd-VZ-lBs"/>
|
||||
<constraint firstItem="VyY-Yg-JOe" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="18" id="lei-uP-T8m"/>
|
||||
<constraint firstItem="f1p-GL-O3o" firstAttribute="top" secondItem="xP7-jE-NF8" secondAttribute="bottom" priority="701" constant="8" id="oY4-e7-lsz"/>
|
||||
<constraint firstItem="7ua-5a-uSd" firstAttribute="top" secondItem="5D8-GP-a4l" secondAttribute="bottom" priority="900" constant="25" id="pCX-eX-erN"/>
|
||||
<constraint firstAttribute="centerX" secondItem="7ua-5a-uSd" secondAttribute="centerX" constant="61" id="phL-j9-rPq"/>
|
||||
<constraint firstItem="xP7-jE-NF8" firstAttribute="centerY" secondItem="MhO-U0-MLR" secondAttribute="centerY" id="pdC-x8-Nao"/>
|
||||
<constraint firstAttribute="centerX" secondItem="7ua-5a-uSd" secondAttribute="centerX" constant="60" id="phL-j9-rPq"/>
|
||||
<constraint firstItem="bDE-Tl-UHg" firstAttribute="top" secondItem="pc8-G9-4pJ" secondAttribute="bottom" constant="8" id="pis-of-f93"/>
|
||||
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="lvJ-Rk-UT5" secondAttribute="trailing" constant="20" id="qKi-KT-jzJ"/>
|
||||
<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 firstItem="eQb-0a-76J" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="u1y-6V-moc"/>
|
||||
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="width" secondItem="eQb-0a-76J" secondAttribute="width" id="u4p-1B-x5B"/>
|
||||
<constraint firstAttribute="bottom" secondItem="BbV-3h-mmL" secondAttribute="bottom" constant="35" id="ukF-FH-DE8"/>
|
||||
<constraint firstItem="VyY-Yg-JOe" firstAttribute="centerY" secondItem="MhO-U0-MLR" secondAttribute="centerY" id="vB8-c5-pfO"/>
|
||||
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="YNz-ka-cBi" secondAttribute="trailing" constant="20" id="vfq-83-tKI"/>
|
||||
<constraint firstItem="pDa-fA-vnC" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="z6s-ga-iAk"/>
|
||||
</constraints>
|
||||
@@ -424,8 +489,9 @@ DQ
|
||||
<connections>
|
||||
<outlet property="initialFirstResponder" destination="kiB-jZ-69S" id="I96-dS-lq5"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="302.5" y="304.5"/>
|
||||
<point key="canvasLocation" x="274" y="326.5"/>
|
||||
</window>
|
||||
<userDefaultsController representsSharedInstance="YES" id="iXx-cu-WYe"/>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSInfo" width="32" height="32"/>
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
@property SNTAboutWindowController *aboutWindowController;
|
||||
@property SNTFileWatcher *configFileWatcher;
|
||||
@property SNTNotificationManager *notificationManager;
|
||||
@property SNTXPCConnection *listener;
|
||||
@property SNTXPCConnection *daemonListener;
|
||||
@property SNTXPCConnection *bundleListener;
|
||||
@end
|
||||
|
||||
@implementation SNTAppDelegate
|
||||
@@ -49,18 +50,19 @@
|
||||
object:nil
|
||||
queue:[NSOperationQueue currentQueue]
|
||||
usingBlock:^(NSNotification *note) {
|
||||
self.listener.invalidationHandler = nil;
|
||||
[self.listener invalidate];
|
||||
self.listener = nil;
|
||||
self.daemonListener.invalidationHandler = nil;
|
||||
[self.daemonListener invalidate];
|
||||
self.daemonListener = nil;
|
||||
}];
|
||||
[workspaceNotifications addObserverForName:NSWorkspaceSessionDidBecomeActiveNotification
|
||||
object:nil
|
||||
queue:[NSOperationQueue currentQueue]
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[self attemptReconnection];
|
||||
[self attemptDaemonReconnection];
|
||||
}];
|
||||
|
||||
[self createConnection];
|
||||
[self createDaemonConnection];
|
||||
[self createBundleConnection];
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag {
|
||||
@@ -71,24 +73,24 @@
|
||||
|
||||
#pragma mark Connection handling
|
||||
|
||||
- (void)createConnection {
|
||||
- (void)createDaemonConnection {
|
||||
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
|
||||
|
||||
WEAKIFY(self);
|
||||
|
||||
// Create listener for return connection from daemon.
|
||||
NSXPCListener *listener = [NSXPCListener anonymousListener];
|
||||
self.listener = [[SNTXPCConnection alloc] initServerWithListener:listener];
|
||||
self.listener.exportedInterface = [SNTXPCNotifierInterface notifierInterface];
|
||||
self.listener.exportedObject = self.notificationManager;
|
||||
self.listener.acceptedHandler = ^{
|
||||
self.daemonListener = [[SNTXPCConnection alloc] initServerWithListener:listener];
|
||||
self.daemonListener.exportedInterface = [SNTXPCNotifierInterface notifierInterface];
|
||||
self.daemonListener.exportedObject = self.notificationManager;
|
||||
self.daemonListener.acceptedHandler = ^{
|
||||
dispatch_semaphore_signal(sema);
|
||||
};
|
||||
self.listener.invalidationHandler = ^{
|
||||
self.daemonListener.invalidationHandler = ^{
|
||||
STRONGIFY(self);
|
||||
[self attemptReconnection];
|
||||
[self attemptDaemonReconnection];
|
||||
};
|
||||
[self.listener resume];
|
||||
[self.daemonListener resume];
|
||||
|
||||
// Tell daemon to connect back to the above listener.
|
||||
SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
|
||||
@@ -97,12 +99,46 @@
|
||||
|
||||
// Now wait for the connection to come in.
|
||||
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
|
||||
[self attemptReconnection];
|
||||
[self attemptDaemonReconnection];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)attemptReconnection {
|
||||
[self performSelectorInBackground:@selector(createConnection) withObject:nil];
|
||||
- (void)attemptDaemonReconnection {
|
||||
[self performSelectorInBackground:@selector(createDaemonConnection) withObject:nil];
|
||||
}
|
||||
|
||||
- (void)createBundleConnection {
|
||||
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
|
||||
|
||||
WEAKIFY(self);
|
||||
|
||||
// Create listener for return connection from the bundle service.
|
||||
NSXPCListener *listener = [NSXPCListener anonymousListener];
|
||||
self.bundleListener = [[SNTXPCConnection alloc] initServerWithListener:listener];
|
||||
self.bundleListener.exportedInterface = [SNTXPCNotifierInterface bundleNotifierInterface];
|
||||
self.bundleListener.exportedObject = self.notificationManager;
|
||||
self.bundleListener.acceptedHandler = ^{
|
||||
dispatch_semaphore_signal(sema);
|
||||
};
|
||||
self.bundleListener.invalidationHandler = ^{
|
||||
STRONGIFY(self);
|
||||
[self attemptBundleReconnection];
|
||||
};
|
||||
[self.bundleListener resume];
|
||||
|
||||
// Tell santabs to connect back to the above listener.
|
||||
SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
|
||||
[daemonConn resume];
|
||||
[[daemonConn remoteObjectProxy] setBundleNotificationListener:listener.endpoint];
|
||||
|
||||
// Now wait for the connection to come in.
|
||||
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
|
||||
[self attemptBundleReconnection];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)attemptBundleReconnection {
|
||||
[self performSelectorInBackground:@selector(createBundleConnection) withObject:nil];
|
||||
}
|
||||
|
||||
#pragma mark Menu Management
|
||||
|
||||
@@ -31,6 +31,36 @@
|
||||
- (IBAction)closeWindow:(id)sender;
|
||||
- (IBAction)showCertInfo:(id)sender;
|
||||
|
||||
/// Reference to the "Bundle Hash" label in the XIB. Used to remove if application
|
||||
/// doesn't have a bundle hash.
|
||||
@property(weak) IBOutlet NSTextField *bundleHashLabel;
|
||||
|
||||
///
|
||||
/// Is displayed if calculating the bundle hash is taking a bit.
|
||||
///
|
||||
@property(weak) IBOutlet NSProgressIndicator *hashingIndicator;
|
||||
|
||||
///
|
||||
/// Is displayed if calculating the bundle hash is taking a bit.
|
||||
///
|
||||
@property(weak) IBOutlet NSTextField *foundFileCountLabel;
|
||||
|
||||
///
|
||||
/// 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(weak) IBOutlet NSButton *openEventButton;
|
||||
|
||||
///
|
||||
/// The execution event that this window is for
|
||||
///
|
||||
@property(readonly) SNTStoredEvent *event;
|
||||
|
||||
///
|
||||
/// The root progress object. Child nodes are vended to santad to report on work being done.
|
||||
///
|
||||
@property NSProgress *progress;
|
||||
|
||||
///
|
||||
/// The delegate to inform when the notification is dismissed
|
||||
///
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#import "SNTStoredEvent.h"
|
||||
|
||||
@interface SNTMessageWindowController ()
|
||||
/// The execution event that this window is for
|
||||
@property SNTStoredEvent *event;
|
||||
|
||||
/// The custom message to display for this event
|
||||
@property(copy) NSString *customMessage;
|
||||
|
||||
@@ -36,13 +33,9 @@
|
||||
/// An optional message to display with this block.
|
||||
@property(readonly, nonatomic) 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;
|
||||
|
||||
/// Reference to the "Application Name" label in the XIB. Used to remove if application
|
||||
/// doesn't have a CFBundleName.
|
||||
@property IBOutlet NSTextField *applicationNameLabel;
|
||||
@property(weak) IBOutlet NSTextField *applicationNameLabel;
|
||||
|
||||
/// Linked to checkbox in UI to prevent future notifications for this binary.
|
||||
@property BOOL silenceFutureNotifications;
|
||||
@@ -55,10 +48,35 @@
|
||||
if (self) {
|
||||
_event = event;
|
||||
_customMessage = message;
|
||||
_progress = [NSProgress discreteProgressWithTotalUnitCount:1];
|
||||
[_progress addObserver:self
|
||||
forKeyPath:@"fractionCompleted"
|
||||
options:NSKeyValueObservingOptionNew
|
||||
context:NULL];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_progress removeObserver:self forKeyPath:@"fractionCompleted"];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context {
|
||||
if ([keyPath isEqualToString:@"fractionCompleted"]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSProgress *progress = object;
|
||||
if (progress.fractionCompleted != 0.0) {
|
||||
self.hashingIndicator.indeterminate = NO;
|
||||
[self.foundFileCountLabel removeFromSuperview];
|
||||
}
|
||||
self.hashingIndicator.doubleValue = progress.fractionCompleted;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadWindow {
|
||||
[super loadWindow];
|
||||
[self.window setLevel:NSPopUpMenuWindowLevel];
|
||||
@@ -73,6 +91,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.event.needsBundleHash) {
|
||||
[self.bundleHashLabel removeFromSuperview];
|
||||
[self.hashingIndicator removeFromSuperview];
|
||||
[self.foundFileCountLabel removeFromSuperview];
|
||||
} else {
|
||||
self.openEventButton.enabled = NO;
|
||||
self.hashingIndicator.indeterminate = YES;
|
||||
[self.hashingIndicator startAnimation:self];
|
||||
self.bundleHashLabel.hidden = YES;
|
||||
self.foundFileCountLabel.stringValue = @"";
|
||||
}
|
||||
|
||||
if (!self.event.fileBundleName) {
|
||||
[self.applicationNameLabel removeFromSuperview];
|
||||
}
|
||||
@@ -83,6 +113,7 @@
|
||||
}
|
||||
|
||||
- (IBAction)closeWindow:(id)sender {
|
||||
[self.progress cancel];
|
||||
[(SNTMessageWindow *)self.window fadeOut:sender];
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
///
|
||||
/// Keeps track of pending notifications and ensures only one is presented to the user at a time.
|
||||
///
|
||||
@interface SNTNotificationManager : NSObject<SNTMessageWindowControllerDelegate, SNTNotifierXPC>
|
||||
@interface SNTNotificationManager : NSObject<SNTMessageWindowControllerDelegate,
|
||||
SNTNotifierXPC, SNTBundleNotifierXPC>
|
||||
|
||||
@end
|
||||
|
||||
@@ -18,13 +18,27 @@
|
||||
#import "SNTConfigurator.h"
|
||||
#import "SNTLogging.h"
|
||||
#import "SNTStoredEvent.h"
|
||||
#import "SNTStrengthify.h"
|
||||
#import "SNTXPCConnection.h"
|
||||
#import "SNTXPCControlInterface.h"
|
||||
|
||||
@interface SNTNotificationManager ()
|
||||
|
||||
/// The currently displayed notification
|
||||
@property SNTMessageWindowController *currentWindowController;
|
||||
|
||||
/// The queue of pending notifications
|
||||
@property(readonly) NSMutableArray *pendingNotifications;
|
||||
|
||||
/// The connection to the bundle service
|
||||
@property SNTXPCConnection *bundleServiceConnection;
|
||||
|
||||
/// A semaphore to block bundle hashing until a connection is established
|
||||
@property dispatch_semaphore_t bundleServiceSema;
|
||||
|
||||
// A serial queue for holding hashBundleBinaries requests
|
||||
@property dispatch_queue_t hashBundleBinariesQueue;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SNTNotificationManager
|
||||
@@ -35,6 +49,9 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_pendingNotifications = [[NSMutableArray alloc] init];
|
||||
_bundleServiceSema = dispatch_semaphore_create(0);
|
||||
_hashBundleBinariesQueue = dispatch_queue_create("com.google.santagui.hashbundlebinaries",
|
||||
DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -48,7 +65,16 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
|
||||
if ([self.pendingNotifications count]) {
|
||||
self.currentWindowController = [self.pendingNotifications firstObject];
|
||||
[self.currentWindowController showWindow:self];
|
||||
if (self.currentWindowController.event.needsBundleHash) {
|
||||
dispatch_async(self.hashBundleBinariesQueue, ^{
|
||||
[self hashBundleBinariesForEvent:self.currentWindowController.event];
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Tear down the bundle service
|
||||
self.bundleServiceSema = dispatch_semaphore_create(0);
|
||||
[self.bundleServiceConnection invalidate];
|
||||
self.bundleServiceConnection = nil;
|
||||
[NSApp hide:self];
|
||||
}
|
||||
}
|
||||
@@ -65,7 +91,7 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
|
||||
[ud setObject:d forKey:silencedNotificationsKey];
|
||||
}
|
||||
|
||||
#pragma mark SNTNotifierXPC protocol method
|
||||
#pragma mark SNTNotifierXPC protocol methods
|
||||
|
||||
- (void)postClientModeNotification:(SNTClientMode)clientmode {
|
||||
NSUserNotification *un = [[NSUserNotification alloc] init];
|
||||
@@ -131,6 +157,11 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
|
||||
if (!self.currentWindowController) {
|
||||
self.currentWindowController = pendingMsg;
|
||||
[pendingMsg showWindow:nil];
|
||||
if (self.currentWindowController.event.needsBundleHash) {
|
||||
dispatch_async(self.hashBundleBinariesQueue, ^{
|
||||
[self hashBundleBinariesForEvent:self.currentWindowController.event];
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -143,4 +174,85 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:un];
|
||||
}
|
||||
|
||||
#pragma mark SNTBundleNotifierXPC protocol methods
|
||||
|
||||
- (void)updateCountsForEvent:(SNTStoredEvent *)event
|
||||
binaryCount:(uint64_t)binaryCount
|
||||
fileCount:(uint64_t)fileCount {
|
||||
if ([self.currentWindowController.event.idx isEqual:event.idx]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.currentWindowController.foundFileCountLabel.stringValue =
|
||||
[NSString stringWithFormat:@"%llu binaries / %llu files", binaryCount, fileCount];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setBundleServiceListener:(NSXPCListenerEndpoint *)listener {
|
||||
SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener];
|
||||
c.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface];
|
||||
[c resume];
|
||||
self.bundleServiceConnection = c;
|
||||
dispatch_semaphore_signal(self.bundleServiceSema);
|
||||
}
|
||||
|
||||
#pragma mark SNTBundleNotifierXPC helper methods
|
||||
|
||||
- (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event {
|
||||
// Wait a max of 6 secs for the bundle service. Should the bundle service fall over, it will
|
||||
// reconnect within 5 secs. Otherwise abandon bundle hashing and display the blockable event.
|
||||
if (dispatch_semaphore_wait(self.bundleServiceSema,
|
||||
dispatch_time(DISPATCH_TIME_NOW, 6 * NSEC_PER_SEC))) {
|
||||
[self updateBlockNotification:event withBundleHash:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
// Let all future requests flow, until the connection is terminated and we go back to waiting.
|
||||
dispatch_semaphore_signal(self.bundleServiceSema);
|
||||
|
||||
// NSProgress becomes current for this thread. XPC messages vend a child node to the receiver.
|
||||
[self.currentWindowController.progress becomeCurrentWithPendingUnitCount:1];
|
||||
|
||||
// Start hashing. Progress is reported to the root NSProgress (currentWindowController.progress).
|
||||
[[self.bundleServiceConnection remoteObjectProxy]
|
||||
hashBundleBinariesForEvent:event
|
||||
reply:^(NSString *bh, NSArray<SNTStoredEvent *> *events, NSNumber *ms) {
|
||||
// Revert to displaying the blockable event if we fail to calculate the bundle hash
|
||||
if (!bh) return [self updateBlockNotification:event withBundleHash:nil];
|
||||
|
||||
event.fileBundleHash = bh;
|
||||
event.fileBundleBinaryCount = @(events.count);
|
||||
event.fileBundleHashMilliseconds = ms;
|
||||
for (SNTStoredEvent *se in events) {
|
||||
se.fileBundleHash = bh;
|
||||
se.fileBundleBinaryCount = @(events.count);
|
||||
se.fileBundleHashMilliseconds = ms;
|
||||
}
|
||||
|
||||
// Send the results to santad. It will decide if they need to be synced.
|
||||
SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
|
||||
[daemonConn resume];
|
||||
[[daemonConn remoteObjectProxy] syncBundleEvent:event relatedEvents:events];
|
||||
|
||||
// Update the UI with the bundle hash. Also make the openEventButton available.
|
||||
[self updateBlockNotification:event withBundleHash:bh];
|
||||
}];
|
||||
[self.currentWindowController.progress resignCurrent];
|
||||
}
|
||||
|
||||
- (void)updateBlockNotification:(SNTStoredEvent *)event withBundleHash:(NSString *)bundleHash {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([self.currentWindowController.event.idx isEqual:event.idx]) {
|
||||
if (bundleHash) {
|
||||
[self.currentWindowController.bundleHashLabel setHidden:NO];
|
||||
} else {
|
||||
[self.currentWindowController.bundleHashLabel removeFromSuperview];
|
||||
}
|
||||
self.currentWindowController.event.fileBundleHash = bundleHash;
|
||||
[self.currentWindowController.foundFileCountLabel removeFromSuperview];
|
||||
[self.currentWindowController.hashingIndicator setHidden:YES];
|
||||
[self.currentWindowController.openEventButton setEnabled:YES];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,7 +12,11 @@
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
|
||||
#ifdef SANTAGUI
|
||||
@import Cocoa;
|
||||
#else
|
||||
@import Foundation;
|
||||
#endif
|
||||
|
||||
@class SNTStoredEvent;
|
||||
|
||||
|
||||
@@ -109,8 +109,9 @@
|
||||
if (!formatStr.length) return nil;
|
||||
|
||||
if (event.fileSHA256) {
|
||||
formatStr = [formatStr stringByReplacingOccurrencesOfString:@"%file_sha%"
|
||||
withString:event.fileSHA256];
|
||||
formatStr =
|
||||
[formatStr stringByReplacingOccurrencesOfString:@"%file_sha%"
|
||||
withString:event.fileBundleHash ?: event.fileSHA256];
|
||||
}
|
||||
if (event.executingUser) {
|
||||
formatStr = [formatStr stringByReplacingOccurrencesOfString:@"%username%"
|
||||
|
||||
@@ -133,12 +133,6 @@ extern NSString *const kDefaultConfigFilePath;
|
||||
///
|
||||
@property(readonly, nonatomic) NSURL *syncBaseURL;
|
||||
|
||||
///
|
||||
/// If YES, mid-execution event uploads are skipped.
|
||||
/// This property is never stored on disk.
|
||||
///
|
||||
@property BOOL syncBackOff;
|
||||
|
||||
///
|
||||
/// The machine owner.
|
||||
///
|
||||
@@ -165,22 +159,10 @@ extern NSString *const kDefaultConfigFilePath;
|
||||
@property(readonly, nonatomic) NSString *machineID;
|
||||
|
||||
///
|
||||
/// The number of seconds in-between full syncs while connected to FCM
|
||||
/// If YES, enables bundle detection for blocked events. This property is not stored on disk.
|
||||
/// Its value is set by a sync server that supports bundles. Defaults to NO.
|
||||
///
|
||||
/// @note The default value is 14400.
|
||||
/// @note The minimum value is 600.
|
||||
///
|
||||
@property(readonly, nonatomic) NSInteger FCMFullSyncInterval;
|
||||
|
||||
///
|
||||
/// The maximum number of seconds to wait before a rule sync when
|
||||
/// receiving a global rule sync message. Each client will choose a random
|
||||
/// number of seconds between 0 and FCMGlobalRuleLeeway.
|
||||
///
|
||||
/// @note The default value is 600.
|
||||
/// @note The minimum value is 60.
|
||||
///
|
||||
@property(readonly, nonatomic) NSInteger FCMGlobalRuleLeeway;
|
||||
@property BOOL bundlesEnabled;
|
||||
|
||||
#pragma mark Server Auth Settings
|
||||
|
||||
|
||||
@@ -71,9 +71,6 @@ static NSString *const kMachineOwnerPlistKeyKey = @"MachineOwnerKey";
|
||||
static NSString *const kMachineIDPlistFileKey = @"MachineIDPlist";
|
||||
static NSString *const kMachineIDPlistKeyKey = @"MachineIDKey";
|
||||
|
||||
static NSString *const kFCMFullSyncInterval = @"FCMFullSyncInterval";
|
||||
static NSString *const kFCMGlobalRuleLeeway = @"FCMGlobalRuleLeeway";
|
||||
|
||||
- (instancetype)initWithFilePath:(NSString *)filePath {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
@@ -329,16 +326,6 @@ static NSString *const kFCMGlobalRuleLeeway = @"FCMGlobalRuleLeeway";
|
||||
return machineId;
|
||||
}
|
||||
|
||||
- (NSInteger)FCMFullSyncInterval {
|
||||
NSInteger interval = [self.configData[kFCMFullSyncInterval] integerValue];
|
||||
return (interval < 600) ? 1440 : interval;
|
||||
}
|
||||
|
||||
- (NSInteger)FCMGlobalRuleLeeway {
|
||||
NSInteger leeway = [self.configData[kFCMGlobalRuleLeeway] integerValue];
|
||||
return (leeway < 60) ? 600 : leeway;
|
||||
}
|
||||
|
||||
- (void)reloadConfigData {
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
if (![fm fileExistsAtPath:self.configFilePath]) {
|
||||
|
||||
@@ -116,6 +116,21 @@
|
||||
///
|
||||
- (BOOL)isMissingPageZero;
|
||||
|
||||
///
|
||||
/// If set to YES, the bundle* and infoPlist methods will search for and use the highest NSBundle
|
||||
/// found in the tree. Defaults to NO, which uses the first found bundle, if any.
|
||||
///
|
||||
/// @example:
|
||||
/// An SNTFileInfo object that represents
|
||||
/// /Applications/Photos.app/Contents/XPCServices/com.apple.Photos.librarychooserservice.xpc
|
||||
/// useAncestorBundle is set to YES
|
||||
/// /Applications/Photos.app will be used to get data backing all the bundle methods
|
||||
///
|
||||
/// @note: The NSBundle object backing the bundle* and infoPlist methods is cached once found.
|
||||
/// Setting the useAncestorBundle propery will clear this cache and force a re-search.
|
||||
///
|
||||
@property(nonatomic) BOOL useAncestorBundle;
|
||||
|
||||
///
|
||||
/// @return An NSBundle if this file is part of a bundle.
|
||||
///
|
||||
|
||||
@@ -280,34 +280,34 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
|
||||
///
|
||||
/// Rationale: An NSBundle has a method executablePath for discovering the main binary within a
|
||||
/// bundle but provides no way to get an NSBundle object when only the executablePath is known.
|
||||
/// Also a bundle can contain multiple binaries within the MacOS folder and we want any of these
|
||||
/// Also a bundle can contain multiple binaries within its subdirectories and we want any of these
|
||||
/// to count as being part of the bundle.
|
||||
///
|
||||
/// This method relies on executable bundles being laid out as follows:
|
||||
/// This method walks up the path until a bundle is found, if any.
|
||||
///
|
||||
/// @code
|
||||
/// Bundle.app/
|
||||
/// Contents/
|
||||
/// MacOS/
|
||||
/// executable
|
||||
/// @endcode
|
||||
///
|
||||
/// If @c self.path is the full path to @c executable above, this method would return an
|
||||
/// NSBundle reference for Bundle.app.
|
||||
/// @param ancestor YES this will return the highest NSBundle found in the tree. No will return the
|
||||
/// the lowest.
|
||||
///
|
||||
-(NSBundle *)findBundleWithAncestor:(BOOL)ancestor {
|
||||
NSBundle *bundle;
|
||||
NSMutableArray *pathComponents = [[self.path pathComponents] mutableCopy];
|
||||
|
||||
// Ignore the root path "/", for some reason this is considered a bundle.
|
||||
while (pathComponents.count > 1) {
|
||||
NSBundle *bndl = [NSBundle bundleWithPath:[NSString pathWithComponents:pathComponents]];
|
||||
if (bndl && [bndl objectForInfoDictionaryKey:@"CFBundleIdentifier"]) {
|
||||
bundle = bndl;
|
||||
if (!ancestor) break;
|
||||
}
|
||||
[pathComponents removeLastObject];
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
- (NSBundle *)bundle {
|
||||
if (!self.bundleRef) {
|
||||
self.bundleRef = (NSBundle *)[NSNull null];
|
||||
|
||||
// Check that the full path is at least 4-levels deep:
|
||||
// e.g: /Calendar.app/Contents/MacOS/Calendar
|
||||
NSArray *pathComponents = [self.path pathComponents];
|
||||
NSUInteger pathComponentsCount = pathComponents.count;
|
||||
if (pathComponentsCount < 4) return nil;
|
||||
|
||||
pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, pathComponentsCount - 3)];
|
||||
NSBundle *bndl = [NSBundle bundleWithPath:[NSString pathWithComponents:pathComponents]];
|
||||
if (bndl && [bndl objectForInfoDictionaryKey:@"CFBundleIdentifier"]) self.bundleRef = bndl;
|
||||
self.bundleRef =
|
||||
[self findBundleWithAncestor:self.useAncestorBundle] ?: (NSBundle *)[NSNull null];
|
||||
}
|
||||
return self.bundleRef == (NSBundle *)[NSNull null] ? nil : self.bundleRef;
|
||||
}
|
||||
@@ -316,6 +316,14 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
|
||||
return [self.bundle bundlePath];
|
||||
}
|
||||
|
||||
- (void)setUseAncestorBundle:(BOOL)useAncestorBundle {
|
||||
if (self.useAncestorBundle != useAncestorBundle) {
|
||||
self.bundleRef = nil;
|
||||
self.infoDict = nil;
|
||||
}
|
||||
_useAncestorBundle = useAncestorBundle;
|
||||
}
|
||||
|
||||
- (NSDictionary *)infoPlist {
|
||||
if (!self.infoDict) {
|
||||
NSDictionary *d = [self embeddedPlist];
|
||||
@@ -638,7 +646,7 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
|
||||
BOOL directory;
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&directory]) {
|
||||
return nil;
|
||||
} else if (directory) {
|
||||
} else if (directory && ![path isEqualToString:@"/"]) {
|
||||
NSBundle *bndl = [NSBundle bundleWithPath:path];
|
||||
if (bundle) *bundle = bndl;
|
||||
return [bndl executablePath];
|
||||
|
||||
@@ -36,6 +36,28 @@
|
||||
///
|
||||
@property NSString *filePath;
|
||||
|
||||
///
|
||||
/// Set to YES if the event is a part of a bundle. When an event is passed to SantaGUI this propery
|
||||
/// will be used as an indicator to to kick off bundle hashing as necessary. Default value is NO.
|
||||
///
|
||||
@property BOOL needsBundleHash;
|
||||
|
||||
///
|
||||
/// If the executed file was part of a bundle, this is the calculated hash of all the nested
|
||||
/// executables within the bundle.
|
||||
///
|
||||
@property NSString *fileBundleHash;
|
||||
|
||||
///
|
||||
/// If the executed file was part of a bundle, this is the time in ms it took to hash the bundle.
|
||||
///
|
||||
@property NSNumber *fileBundleHashMilliseconds;
|
||||
|
||||
///
|
||||
/// If the executed file was part of a bundle, this is the total count of related mach-o binaries.
|
||||
///
|
||||
@property NSNumber *fileBundleBinaryCount;
|
||||
|
||||
///
|
||||
/// If the executed file was part of the bundle, this is the CFBundleDisplayName, if it exists
|
||||
/// or the CFBundleName if not.
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
ENCODE(self.fileSHA256, @"fileSHA256");
|
||||
ENCODE(self.filePath, @"filePath");
|
||||
|
||||
ENCODE(@(self.needsBundleHash), @"needsBundleHash");
|
||||
ENCODE(self.fileBundleHash, @"fileBundleHash");
|
||||
ENCODE(self.fileBundleHashMilliseconds, @"fileBundleHashMilliseconds");
|
||||
ENCODE(self.fileBundleBinaryCount, @"fileBundleBinaryCount");
|
||||
ENCODE(self.fileBundleName, @"fileBundleName");
|
||||
ENCODE(self.fileBundlePath, @"fileBundlePath");
|
||||
ENCODE(self.fileBundleID, @"fileBundleID");
|
||||
@@ -72,6 +76,10 @@
|
||||
_fileSHA256 = DECODE(NSString, @"fileSHA256");
|
||||
_filePath = DECODE(NSString, @"filePath");
|
||||
|
||||
_needsBundleHash = [DECODE(NSNumber, @"needsBundleHash") boolValue];
|
||||
_fileBundleHash = DECODE(NSString, @"fileBundleHash");
|
||||
_fileBundleHashMilliseconds = DECODE(NSNumber, @"fileBundleHashMilliseconds");
|
||||
_fileBundleBinaryCount = DECODE(NSNumber, @"fileBundleBinaryCount");
|
||||
_fileBundleName = DECODE(NSString, @"fileBundleName");
|
||||
_fileBundlePath = DECODE(NSString, @"fileBundlePath");
|
||||
_fileBundleID = DECODE(NSString, @"fileBundleID");
|
||||
|
||||
56
Source/common/SNTXPCBundleServiceInterface.h
Normal file
56
Source/common/SNTXPCBundleServiceInterface.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/// Copyright 2017 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 Foundation;
|
||||
|
||||
@class SNTStoredEvent;
|
||||
|
||||
/// A block that takes the calculated bundle hash, associated events and hashing time in ms.
|
||||
typedef void (^SNTBundleHashBlock)(NSString *, NSArray<SNTStoredEvent *> *, NSNumber *);
|
||||
|
||||
/// Protocol implemented by santabs and utilized by SantaGUI for bundle hashing
|
||||
@protocol SNTBundleServiceXPC
|
||||
|
||||
///
|
||||
/// @param listener The listener to connect back to the SantaGUI.
|
||||
///
|
||||
- (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener;
|
||||
|
||||
///
|
||||
/// Hash a bundle for an event. The SNTBundleHashBlock will be called with nil parameters if a
|
||||
/// failure or cancellation occurs.
|
||||
///
|
||||
/// @param event The event that includes the fileBundlePath to be hashed.
|
||||
/// @param reply A SNTBundleHashBlock to be executed upon completion or cancellation.
|
||||
///
|
||||
/// @note If there is a current NSProgress when called this method will report back its progress.
|
||||
///
|
||||
- (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event reply:(SNTBundleHashBlock)reply;
|
||||
|
||||
@end
|
||||
|
||||
@interface SNTXPCBundleServiceInterface : NSObject
|
||||
|
||||
///
|
||||
/// Returns an initialized NSXPCInterface for the SNTBundleServiceXPC protocol.
|
||||
/// Ensures any methods that accept custom classes as arguments are set-up before returning.
|
||||
///
|
||||
+ (NSXPCInterface *)bundleServiceInterface;
|
||||
|
||||
///
|
||||
/// Returns the MachService ID for this service.
|
||||
///
|
||||
+ (NSString *)serviceId;
|
||||
|
||||
@end
|
||||
36
Source/common/SNTXPCBundleServiceInterface.m
Normal file
36
Source/common/SNTXPCBundleServiceInterface.m
Normal file
@@ -0,0 +1,36 @@
|
||||
/// Copyright 2017 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 "SNTXPCBundleServiceInterface.h"
|
||||
|
||||
#import "SNTStoredEvent.h"
|
||||
|
||||
@implementation SNTXPCBundleServiceInterface
|
||||
|
||||
+ (NSXPCInterface *)bundleServiceInterface {
|
||||
NSXPCInterface *r = [NSXPCInterface interfaceWithProtocol:@protocol(SNTBundleServiceXPC)];
|
||||
|
||||
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
|
||||
forSelector:@selector(hashBundleBinariesForEvent:reply:)
|
||||
argumentIndex:1
|
||||
ofReply:YES];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+ (NSString *)serviceId {
|
||||
return @"com.google.santabs";
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -65,13 +65,20 @@
|
||||
- (nullable instancetype)initServerWithName:(nonnull NSString *)name;
|
||||
|
||||
/**
|
||||
Initializer a new client to a service exported by a LaunchDaemon.
|
||||
Initialize a new client to a service exported by a LaunchDaemon.
|
||||
|
||||
@param name MachService name
|
||||
@param privileged Use YES if the server is running as root.
|
||||
*/
|
||||
- (nullable instancetype)initClientWithName:(nonnull NSString *)name privileged:(BOOL)privileged;
|
||||
|
||||
/**
|
||||
Initialize a new client to a service within a bundle.
|
||||
|
||||
@param name service name
|
||||
*/
|
||||
- (nullable instancetype)initClientWithServiceName:(nonnull NSString *)name;
|
||||
|
||||
/**
|
||||
Initialize a new client with a listener endpoint sent from another process.
|
||||
|
||||
|
||||
@@ -95,6 +95,17 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initClientWithServiceName:(NSString *)name {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_currentConnection = [[NSXPCConnection alloc] initWithServiceName:name];
|
||||
if (!_currentConnection) return nil;
|
||||
_validationInterface =
|
||||
[NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
[self doesNotRecognizeSelector:_cmd];
|
||||
return nil;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#import "SNTCachedDecision.h"
|
||||
#import "SNTCommonEnums.h"
|
||||
#import "SNTKernelCommon.h"
|
||||
#import "SNTXPCBundleServiceInterface.h"
|
||||
|
||||
@class SNTRule;
|
||||
@class SNTStoredEvent;
|
||||
@@ -57,13 +58,13 @@
|
||||
/// @param filePath A Path to the file, can be nil.
|
||||
/// @param fileSHA256 The pre-calculated SHA256 hash for the file, can be nil. If nil the hash will
|
||||
/// be calculated by this method from the filePath.
|
||||
/// @param signingCertificate A MOLCertificate object, can be nil.
|
||||
/// @param certificateSHA256 A SHA256 hash of the signing certificate, can be nil.
|
||||
/// @note If fileInfo and signingCertificate are both passed in, the most specific rule will be
|
||||
/// returned. Binary rules take precedence over cert rules.
|
||||
///
|
||||
- (void)decisionForFilePath:(NSString *)filePath
|
||||
fileSHA256:(NSString *)fileSHA256
|
||||
signingCertificate:(MOLCertificate *)signingCertificate
|
||||
certificateSHA256:(NSString *)certificateSHA256
|
||||
reply:(void (^)(SNTEventState))reply;
|
||||
|
||||
///
|
||||
@@ -79,20 +80,28 @@
|
||||
- (void)setSyncCleanRequired:(BOOL)cleanReqd reply:(void (^)())reply;
|
||||
- (void)setWhitelistPathRegex:(NSString *)pattern reply:(void (^)())reply;
|
||||
- (void)setBlacklistPathRegex:(NSString *)pattern reply:(void (^)())reply;
|
||||
- (void)bundlesEnabled:(void (^)(BOOL))reply;
|
||||
- (void)setBundlesEnabled:(BOOL)bundlesEnabled reply:(void (^)())reply;
|
||||
|
||||
///
|
||||
/// GUI Ops
|
||||
///
|
||||
- (void)setNotificationListener:(NSXPCListenerEndpoint *)listener;
|
||||
- (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener;
|
||||
|
||||
///
|
||||
/// Syncd Ops
|
||||
///
|
||||
- (void)setSyncdListener:(NSXPCListenerEndpoint *)listener;
|
||||
- (void)setNextSyncInterval:(uint64_t)seconds reply:(void (^)())reply;
|
||||
- (void)pushNotifications:(void (^)(BOOL))reply;
|
||||
- (void)postRuleSyncNotificationWithCustomMessage:(NSString *)message reply:(void (^)())reply;
|
||||
|
||||
///
|
||||
/// Bundle Ops
|
||||
///
|
||||
- (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event reply:(SNTBundleHashBlock)reply;
|
||||
- (void)syncBundleEvent:(SNTStoredEvent *)event relatedEvents:(NSArray<SNTStoredEvent *> *)events;
|
||||
|
||||
@end
|
||||
|
||||
@interface SNTXPCControlInterface : NSObject
|
||||
|
||||
@@ -37,6 +37,16 @@
|
||||
argumentIndex:0
|
||||
ofReply:NO];
|
||||
|
||||
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
|
||||
forSelector:@selector(hashBundleBinariesForEvent:reply:)
|
||||
argumentIndex:1
|
||||
ofReply:YES];
|
||||
|
||||
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
|
||||
forSelector:@selector(syncBundleEvent:relatedEvents:)
|
||||
argumentIndex:1
|
||||
ofReply:NO];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
@import Foundation;
|
||||
|
||||
#import "SNTCommonEnums.h"
|
||||
#import "SNTXPCBundleServiceInterface.h"
|
||||
|
||||
@class SNTStoredEvent;
|
||||
|
||||
@@ -25,6 +26,14 @@
|
||||
- (void)postRuleSyncNotificationWithCustomMessage:(NSString *)message;
|
||||
@end
|
||||
|
||||
/// Protocol implemented by SantaGUI and utilized by santabs
|
||||
@protocol SNTBundleNotifierXPC
|
||||
- (void)updateCountsForEvent:(SNTStoredEvent *)event
|
||||
binaryCount:(uint64_t)binaryCount
|
||||
fileCount:(uint64_t)fileCount;
|
||||
- (void)setBundleServiceListener:(NSXPCListenerEndpoint *)listener;
|
||||
@end
|
||||
|
||||
@interface SNTXPCNotifierInterface : NSObject
|
||||
|
||||
///
|
||||
@@ -33,4 +42,10 @@
|
||||
///
|
||||
+ (NSXPCInterface *)notifierInterface;
|
||||
|
||||
///
|
||||
/// @return an initialized NSXPCInterface for the SNTBundleNotifierXPC protocol.
|
||||
/// Ensures any methods that accept custom classes as arguments are set-up before returning
|
||||
///
|
||||
+ (NSXPCInterface *)bundleNotifierInterface;
|
||||
|
||||
@end
|
||||
|
||||
@@ -20,4 +20,8 @@
|
||||
return [NSXPCInterface interfaceWithProtocol:@protocol(SNTNotifierXPC)];
|
||||
}
|
||||
|
||||
+ (NSXPCInterface *)bundleNotifierInterface {
|
||||
return [NSXPCInterface interfaceWithProtocol:@protocol(SNTBundleNotifierXPC)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
/// Protocol implemented by santactl and utilized by santad
|
||||
@protocol SNTSyncdXPC
|
||||
- (void)postEventToSyncServer:(SNTStoredEvent *)event;
|
||||
- (void)rescheduleSyncSecondsFromNow:(uint64_t)seconds;
|
||||
- (void)postBundleEventToSyncServer:(SNTStoredEvent *)event reply:(void (^)(BOOL))reply;
|
||||
- (void)postBundleEventsToSyncServer:(NSArray<SNTStoredEvent *> *)events;
|
||||
- (void)isFCMListening:(void (^)(BOOL))reply;
|
||||
@end
|
||||
|
||||
|
||||
@@ -14,10 +14,19 @@
|
||||
|
||||
#import "SNTXPCSyncdInterface.h"
|
||||
|
||||
#import "SNTStoredEvent.h"
|
||||
|
||||
@implementation SNTXPCSyncdInterface
|
||||
|
||||
+ (NSXPCInterface *)syncdInterface {
|
||||
return [NSXPCInterface interfaceWithProtocol:@protocol(SNTSyncdXPC)];
|
||||
NSXPCInterface *r = [NSXPCInterface interfaceWithProtocol:@protocol(SNTSyncdXPC)];
|
||||
|
||||
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
|
||||
forSelector:@selector(postBundleEventsToSyncServer:)
|
||||
argumentIndex:0
|
||||
ofReply:NO];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -247,7 +247,7 @@ template<class T> class SantaCache {
|
||||
/**
|
||||
Holder for a 'zero' entry for the current type
|
||||
*/
|
||||
const T zero_ = T(0);
|
||||
const T zero_ = T();
|
||||
|
||||
/**
|
||||
Special bucket used when automatically clearing due to size
|
||||
|
||||
@@ -206,11 +206,13 @@ void SantaDecisionManager::AddToCache(
|
||||
decision_cache_->remove(identifier);
|
||||
}
|
||||
|
||||
if (unlikely(!identifier)) return;
|
||||
wakeup((void *)identifier);
|
||||
}
|
||||
|
||||
void SantaDecisionManager::RemoveFromCache(uint64_t identifier) {
|
||||
decision_cache_->remove(identifier);
|
||||
if (unlikely(!identifier)) return;
|
||||
wakeup((void *)identifier);
|
||||
}
|
||||
|
||||
@@ -237,13 +239,8 @@ santa_action_t SantaDecisionManager::GetFromCache(uint64_t identifier) {
|
||||
|
||||
if (RESPONSE_VALID(result)) {
|
||||
if (result == ACTION_RESPOND_DENY) {
|
||||
auto diff_time = GetCurrentUptime();
|
||||
if ((kMaxDenyCacheTimeMilliseconds * 1000) > diff_time) {
|
||||
diff_time = 0;
|
||||
} else {
|
||||
diff_time -= (kMaxDenyCacheTimeMilliseconds * 1000);
|
||||
}
|
||||
if (decision_time < diff_time) {
|
||||
auto expiry_time = decision_time + (kMaxDenyCacheTimeMilliseconds * 1000);
|
||||
if (expiry_time < GetCurrentUptime()) {
|
||||
decision_cache_->remove(identifier);
|
||||
return ACTION_UNSET;
|
||||
}
|
||||
|
||||
31
Source/santabs/Resources/santabs-Info.plist
Normal file
31
Source/santabs/Resources/santabs-Info.plist
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>santabs</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>XPCService</key>
|
||||
<dict>
|
||||
<key>ServiceType</key>
|
||||
<string>Application</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
20
Source/santabs/SNTBundleService.h
Normal file
20
Source/santabs/SNTBundleService.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/// Copyright 2017 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 Foundation;
|
||||
|
||||
#import "SNTXPCBundleServiceInterface.h"
|
||||
|
||||
@interface SNTBundleService : NSObject<SNTBundleServiceXPC>
|
||||
@end
|
||||
313
Source/santabs/SNTBundleService.m
Normal file
313
Source/santabs/SNTBundleService.m
Normal file
@@ -0,0 +1,313 @@
|
||||
/// Copyright 2017 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 "SNTBundleService.h"
|
||||
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import <pthread/pthread.h>
|
||||
|
||||
#import "MOLCertificate.h"
|
||||
#import "MOLCodesignChecker.h"
|
||||
#import "SNTFileInfo.h"
|
||||
#import "SNTLogging.h"
|
||||
#import "SNTStoredEvent.h"
|
||||
#import "SNTXPCConnection.h"
|
||||
#import "SNTXPCNotifierInterface.h"
|
||||
|
||||
@interface SNTBundleService ()
|
||||
@property SNTXPCConnection *notifierConnection;
|
||||
@property SNTXPCConnection *listener;
|
||||
@end
|
||||
|
||||
@implementation SNTBundleService
|
||||
|
||||
#pragma mark Connection handling
|
||||
|
||||
// Create a listener for SantaGUI to connect
|
||||
- (void)createConnection {
|
||||
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
|
||||
|
||||
// Create listener for return connection from SantaGUI.
|
||||
NSXPCListener *listener = [NSXPCListener anonymousListener];
|
||||
self.listener = [[SNTXPCConnection alloc] initServerWithListener:listener];
|
||||
self.listener.exportedInterface = [SNTXPCBundleServiceInterface bundleServiceInterface];
|
||||
self.listener.exportedObject = self;
|
||||
self.listener.acceptedHandler = ^{
|
||||
dispatch_semaphore_signal(sema);
|
||||
};
|
||||
|
||||
// Exit when SantaGUI is done with us.
|
||||
self.listener.invalidationHandler = ^{
|
||||
exit(0);
|
||||
};
|
||||
|
||||
[self.listener resume];
|
||||
|
||||
// Tell SantaGUI to connect back to the above listener.
|
||||
[[self.notifierConnection remoteObjectProxy] setBundleServiceListener:listener.endpoint];
|
||||
|
||||
// Now wait for the connection to come in.
|
||||
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
|
||||
[self attemptReconnection];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)attemptReconnection {
|
||||
[self performSelectorInBackground:@selector(createConnection) withObject:nil];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark SNTBundleServiceXPC Methods
|
||||
|
||||
// Connect to the SantaGUI
|
||||
- (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener {
|
||||
SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener];
|
||||
c.remoteInterface = [SNTXPCNotifierInterface bundleNotifierInterface];
|
||||
[c resume];
|
||||
self.notifierConnection = c;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
[self createConnection];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event
|
||||
reply:(SNTBundleHashBlock)reply {
|
||||
NSProgress *progress =
|
||||
[NSProgress currentProgress] ? [NSProgress progressWithTotalUnitCount:1] : nil;
|
||||
|
||||
NSDate *startTime = [NSDate date];
|
||||
|
||||
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
// Use the highest bundle we can find. Save and reuse the bundle infomation when creating
|
||||
// the related binary events.
|
||||
SNTFileInfo *b = [[SNTFileInfo alloc] initWithPath:event.fileBundlePath];
|
||||
b.useAncestorBundle = YES;
|
||||
event.fileBundlePath = b.bundlePath;
|
||||
event.fileBundleID = b.bundleIdentifier;
|
||||
event.fileBundleName = b.bundleName;
|
||||
event.fileBundleVersion = b.bundleVersion;
|
||||
event.fileBundleVersionString = b.bundleShortVersionString;
|
||||
|
||||
NSArray *relatedBinaries = [self findRelatedBinaries:event progress:progress];
|
||||
NSString *bundleHash = [self calculateBundleHashFromEvents:relatedBinaries];
|
||||
NSNumber *ms = [NSNumber numberWithDouble:[startTime timeIntervalSinceNow] * -1000.0];
|
||||
if (bundleHash) LOGD(@"hashed %@ in %@ ms", event.fileBundlePath, ms);
|
||||
reply(bundleHash, relatedBinaries, ms);
|
||||
dispatch_semaphore_signal(sema);
|
||||
});
|
||||
|
||||
// Master timeout of 10 min. Don't block the calling thread. NSProgress updates will be coming
|
||||
// in over this thread.
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 600 * NSEC_PER_SEC))) {
|
||||
LOGD(@"hashBundleBinariesForEvent timeout");
|
||||
[progress cancel];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark Internal Methods
|
||||
|
||||
/**
|
||||
Find binaries within a bundle given the bundle's event. It will run until a timeout occurs,
|
||||
or until the NSProgress is cancelled. Search is done within the bundle concurrently.
|
||||
|
||||
@param event The SNTStoredEvent to begin searching underneath
|
||||
@return An array of SNTStoredEvent's
|
||||
|
||||
@note The first stage gathers a set of executables. 60 sec / max thread timeout.
|
||||
@note The second stage hashes the executables. 300 sec / max thread timeout.
|
||||
*/
|
||||
- (NSArray *)findRelatedBinaries:(SNTStoredEvent *)event progress:(NSProgress *)progress {
|
||||
// For storing the generated events, with a simple lock for writing.
|
||||
NSMutableArray *relatedEvents = [NSMutableArray array];
|
||||
|
||||
// For storing files to be hashed
|
||||
NSMutableSet<SNTFileInfo *> *fis = [NSMutableSet set];
|
||||
|
||||
// Limit the number of threads that can process files at once to keep CPU usage down.
|
||||
dispatch_semaphore_t sema =
|
||||
dispatch_semaphore_create([[NSProcessInfo processInfo] processorCount] / 2);
|
||||
|
||||
// Group the processing into a single group so we can wait on the whole group after each stage.
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
|
||||
// Directory enumerator
|
||||
NSDirectoryEnumerator *dirEnum =
|
||||
[[NSFileManager defaultManager] enumeratorAtPath:event.fileBundlePath];
|
||||
|
||||
// Locks for accessing the enumerator and adding file and events between threads.
|
||||
__block pthread_mutex_t enumeratorMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
__block pthread_mutex_t eventsMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// Counts used as additional progress information in SantaGUI
|
||||
__block uint64_t binaryCount = 0;
|
||||
__block uint64_t sentBinaryCount = 0;
|
||||
__block uint64_t fileCount = 0;
|
||||
|
||||
__block BOOL breakDir = NO;
|
||||
|
||||
// In the first stage iterate over every file in the tree checking if it is a binary. If so add
|
||||
// it to the fis set for the second stage. Hashing the file while iterating over the filesystem
|
||||
// causes performance issues. Do them separately.
|
||||
while (1) {
|
||||
@autoreleasepool {
|
||||
if (breakDir || progress.isCancelled) break;
|
||||
|
||||
// Wait for a processing thread to become available. At this stage we are only reading the
|
||||
// mach_header. If all processing threads are blocking for more than 60 sec bail.
|
||||
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC))) {
|
||||
LOGD(@"isExecutable processing threads timeout");
|
||||
return nil;
|
||||
}
|
||||
|
||||
dispatch_group_async(group,
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
pthread_mutex_lock(&enumeratorMutex);
|
||||
NSString *file = [dirEnum nextObject];
|
||||
fileCount++;
|
||||
pthread_mutex_unlock(&enumeratorMutex);
|
||||
|
||||
if (!file) {
|
||||
breakDir = YES;
|
||||
dispatch_semaphore_signal(sema);
|
||||
return;
|
||||
}
|
||||
|
||||
if ([dirEnum fileAttributes][NSFileType] != NSFileTypeRegular) {
|
||||
dispatch_semaphore_signal(sema);
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *newFile = [event.fileBundlePath stringByAppendingPathComponent:file];
|
||||
SNTFileInfo *fi = [[SNTFileInfo alloc] initWithPath:newFile];
|
||||
if (!fi.isExecutable) {
|
||||
dispatch_semaphore_signal(sema);
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&eventsMutex);
|
||||
[fis addObject:fi];
|
||||
binaryCount++;
|
||||
pthread_mutex_unlock(&eventsMutex);
|
||||
|
||||
dispatch_semaphore_signal(sema);
|
||||
});
|
||||
if (progress && ((fileCount % 500) == 0 || binaryCount > sentBinaryCount)) {
|
||||
sentBinaryCount = binaryCount;
|
||||
[[self.notifierConnection remoteObjectProxy] updateCountsForEvent:event
|
||||
binaryCount:binaryCount
|
||||
fileCount:fileCount];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (progress.isCancelled) return nil;
|
||||
|
||||
// Wait for all the processing threads to finish
|
||||
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
||||
|
||||
NSProgress *p;
|
||||
if (progress) {
|
||||
[progress becomeCurrentWithPendingUnitCount:1];
|
||||
p = [NSProgress progressWithTotalUnitCount:fis.count];
|
||||
}
|
||||
|
||||
// In the second stage perform SHA256 hashing on all of the found binaries.
|
||||
for (SNTFileInfo *fi in fis) {
|
||||
@autoreleasepool {
|
||||
if (progress.isCancelled) break;
|
||||
|
||||
// Wait for a processing thread to become available. Here we are hashing the entire file.
|
||||
// If all processing threads are blocking for more than 5 min bail.
|
||||
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 300 * NSEC_PER_SEC))) {
|
||||
LOGD(@"SHA256 processing threads timeout");
|
||||
return nil;
|
||||
}
|
||||
|
||||
dispatch_group_async(group,
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
@autoreleasepool {
|
||||
SNTStoredEvent *se = [[SNTStoredEvent alloc] init];
|
||||
se.filePath = fi.path;
|
||||
se.fileSHA256 = fi.SHA256;
|
||||
se.occurrenceDate = [NSDate distantFuture];
|
||||
se.decision = SNTEventStateBundleBinary;
|
||||
|
||||
se.fileBundlePath = event.fileBundlePath;
|
||||
se.fileBundleID = event.fileBundleID;
|
||||
se.fileBundleName = event.fileBundleName;
|
||||
se.fileBundleVersion = event.fileBundleVersion;
|
||||
se.fileBundleVersionString = event.fileBundleVersionString;
|
||||
|
||||
MOLCodesignChecker *cs = [[MOLCodesignChecker alloc] initWithBinaryPath:se.filePath];
|
||||
se.signingChain = cs.certificates;
|
||||
|
||||
pthread_mutex_lock(&eventsMutex);
|
||||
[relatedEvents addObject:se];
|
||||
p.completedUnitCount++;
|
||||
pthread_mutex_unlock(&eventsMutex);
|
||||
|
||||
dispatch_semaphore_signal(sema);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all the processing threads to finish
|
||||
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
||||
|
||||
pthread_mutex_destroy(&enumeratorMutex);
|
||||
pthread_mutex_destroy(&eventsMutex);
|
||||
|
||||
return progress.isCancelled ? nil : relatedEvents;
|
||||
}
|
||||
|
||||
- (NSString *)calculateBundleHashFromEvents:(NSArray<SNTStoredEvent *> *)events {
|
||||
if (!events) return nil;
|
||||
NSMutableArray *eventSHA256Hashes = [NSMutableArray arrayWithCapacity:events.count];
|
||||
for (SNTStoredEvent *event in events) {
|
||||
if (!event.fileSHA256) return nil;
|
||||
[eventSHA256Hashes addObject:event.fileSHA256];
|
||||
}
|
||||
|
||||
[eventSHA256Hashes sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
|
||||
NSString *sha256Hashes = [eventSHA256Hashes componentsJoinedByString:@""];
|
||||
|
||||
CC_SHA256_CTX c256;
|
||||
CC_SHA256_Init(&c256);
|
||||
CC_SHA256_Update(&c256, (const void *)sha256Hashes.UTF8String, (CC_LONG)sha256Hashes.length);
|
||||
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
|
||||
CC_SHA256_Final(digest, &c256);
|
||||
|
||||
NSString *const SHA256FormatString =
|
||||
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x";
|
||||
|
||||
NSString *sha256 = [[NSString alloc] initWithFormat:SHA256FormatString,
|
||||
digest[0], digest[1], digest[2], digest[3],
|
||||
digest[4], digest[5], digest[6], digest[7],
|
||||
digest[8], digest[9], digest[10], digest[11],
|
||||
digest[12], digest[13], digest[14], digest[15],
|
||||
digest[16], digest[17], digest[18], digest[19],
|
||||
digest[20], digest[21], digest[22], digest[23],
|
||||
digest[24], digest[25], digest[26], digest[27],
|
||||
digest[28], digest[29], digest[30], digest[31]];
|
||||
|
||||
return sha256;
|
||||
}
|
||||
|
||||
@end
|
||||
27
Source/santabs/main.m
Normal file
27
Source/santabs/main.m
Normal file
@@ -0,0 +1,27 @@
|
||||
/// Copyright 2017 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 Foundation;
|
||||
|
||||
#import "SNTBundleService.h"
|
||||
#import "SNTXPCBundleServiceInterface.h"
|
||||
#import "SNTXPCConnection.h"
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
SNTXPCConnection *c =
|
||||
[[SNTXPCConnection alloc] initServerWithListener:[NSXPCListener serviceListener]];
|
||||
c.exportedInterface = [SNTXPCBundleServiceInterface bundleServiceInterface];
|
||||
c.exportedObject = [[SNTBundleService alloc] init];
|
||||
[c resume];
|
||||
}
|
||||
79
Source/santactl/Commands/SNTCommandBundleInfo.m
Normal file
79
Source/santactl/Commands/SNTCommandBundleInfo.m
Normal file
@@ -0,0 +1,79 @@
|
||||
/// Copyright 2017 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"
|
||||
|
||||
#import "SNTFileInfo.h"
|
||||
#import "SNTLogging.h"
|
||||
#import "SNTStoredEvent.h"
|
||||
#import "SNTXPCConnection.h"
|
||||
#import "SNTXPCControlInterface.h"
|
||||
|
||||
@interface SNTCommandBundleInfo : NSObject<SNTCommand>
|
||||
@end
|
||||
|
||||
@implementation SNTCommandBundleInfo
|
||||
|
||||
#ifdef DEBUG
|
||||
REGISTER_COMMAND_NAME(@"bundleinfo")
|
||||
#endif
|
||||
|
||||
+ (BOOL)requiresRoot {
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)requiresDaemonConn {
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (NSString *)shortHelpText {
|
||||
return @"Searches a bundle for binaries";
|
||||
}
|
||||
|
||||
+ (NSString *)longHelpText {
|
||||
return @"Searches a bundle for binaries";
|
||||
}
|
||||
|
||||
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
|
||||
NSError *error;
|
||||
SNTFileInfo *fi = [[SNTFileInfo alloc] initWithPath:arguments.firstObject error:&error];
|
||||
if (!fi) {
|
||||
printf("%s\n", error.description.UTF8String);
|
||||
exit(1);
|
||||
} else if (!fi.bundle) {
|
||||
printf("Not a bundle\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
SNTStoredEvent *se = [[SNTStoredEvent alloc] init];
|
||||
se.fileBundlePath = fi.bundlePath;
|
||||
|
||||
[[daemonConn remoteObjectProxy] hashBundleBinariesForEvent:se
|
||||
reply:^(NSString *hash,
|
||||
NSArray<SNTStoredEvent *> *events,
|
||||
NSNumber *time) {
|
||||
|
||||
printf("Hashing time: %llu ms\n", time.unsignedLongLongValue);
|
||||
printf("%lu events found\n", events.count);
|
||||
printf("BundleHash: %s\n", hash.UTF8String);
|
||||
|
||||
for (SNTStoredEvent *event in events) {
|
||||
printf("BundleID: %s \n\tSHA-256: %s \n\tPath: %s\n",
|
||||
event.fileBundleID.UTF8String, event.fileSHA256.UTF8String, event.filePath.UTF8String);
|
||||
}
|
||||
exit(0);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -281,7 +281,7 @@ REGISTER_COMMAND_NAME(@"fileinfo")
|
||||
}
|
||||
[[fi.daemonConn remoteObjectProxy] decisionForFilePath:fi.path(fi)
|
||||
fileSHA256:fi.propertyMap[kSHA256](fi)
|
||||
signingCertificate:fi.csc.leafCertificate
|
||||
certificateSHA256:fi.csc.leafCertificate.SHA256
|
||||
reply:^(SNTEventState state) {
|
||||
if (state) s = state;
|
||||
dispatch_semaphore_signal(sema);
|
||||
|
||||
@@ -44,7 +44,7 @@ REGISTER_COMMAND_NAME(@"rule")
|
||||
}
|
||||
|
||||
+ (NSString *)shortHelpText {
|
||||
return @"Manually add/remove rules.";
|
||||
return @"Manually add/remove/check rules.";
|
||||
}
|
||||
|
||||
+ (NSString *)longHelpText {
|
||||
@@ -54,14 +54,17 @@ REGISTER_COMMAND_NAME(@"rule")
|
||||
@" --blacklist: add to blacklist\n"
|
||||
@" --silent-blacklist: add to silent blacklist\n"
|
||||
@" --remove: remove existing rule\n"
|
||||
@" --check: check for an existing rule\n"
|
||||
@"\n"
|
||||
@" One of:\n"
|
||||
@" --path {path}: path of binary/bundle to add/remove.\n"
|
||||
@" Will add the hash of the file currently at that path.\n"
|
||||
@" --sha256 {sha256}: hash to add/remove\n"
|
||||
@" Does not work with --check. Use the fileinfo verb to check.\n"
|
||||
@" the rule state of a file.\n"
|
||||
@" --sha256 {sha256}: hash to add/remove/check\n"
|
||||
@"\n"
|
||||
@" Optionally:\n"
|
||||
@" --certificate: add certificate rule instead of binary\n"
|
||||
@" --certificate: add or check a certificate sha256 rule instead of binary\n"
|
||||
@" --message {message}: custom message\n");
|
||||
}
|
||||
|
||||
@@ -73,7 +76,7 @@ REGISTER_COMMAND_NAME(@"rule")
|
||||
|
||||
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
|
||||
SNTConfigurator *config = [SNTConfigurator configurator];
|
||||
if ([config syncBaseURL] != nil) {
|
||||
if ([config syncBaseURL] && ![arguments containsObject:@"--check"]) {
|
||||
printf("SyncBaseURL is set, rules are managed centrally.\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -83,6 +86,7 @@ REGISTER_COMMAND_NAME(@"rule")
|
||||
newRule.type = SNTRuleTypeBinary;
|
||||
|
||||
NSString *path;
|
||||
BOOL check = NO;
|
||||
|
||||
// Parse arguments
|
||||
for (NSUInteger i = 0; i < arguments.count; ++i) {
|
||||
@@ -96,6 +100,8 @@ REGISTER_COMMAND_NAME(@"rule")
|
||||
newRule.state = SNTRuleStateSilentBlacklist;
|
||||
} else if ([arg caseInsensitiveCompare:@"--remove"] == NSOrderedSame) {
|
||||
newRule.state = SNTRuleStateRemove;
|
||||
} else if ([arg caseInsensitiveCompare:@"--check"] == NSOrderedSame) {
|
||||
check = YES;
|
||||
} else if ([arg caseInsensitiveCompare:@"--certificate"] == NSOrderedSame) {
|
||||
newRule.type = SNTRuleTypeCertificate;
|
||||
} else if ([arg caseInsensitiveCompare:@"--path"] == NSOrderedSame) {
|
||||
@@ -121,6 +127,11 @@ REGISTER_COMMAND_NAME(@"rule")
|
||||
}
|
||||
}
|
||||
|
||||
if (check) {
|
||||
if (!newRule.shasum) return [self printErrorUsageAndExit:@"--check requires --sha256"];
|
||||
return [self printStateOfRule:newRule daemonConnection:daemonConn];
|
||||
}
|
||||
|
||||
if (path) {
|
||||
SNTFileInfo *fi = [[SNTFileInfo alloc] initWithPath:path];
|
||||
if (!fi.path) {
|
||||
@@ -159,4 +170,58 @@ REGISTER_COMMAND_NAME(@"rule")
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)printStateOfRule:(SNTRule *)rule daemonConnection:(SNTXPCConnection *)daemonConn {
|
||||
NSString *fileSHA256 = (rule.type == SNTRuleTypeBinary) ? rule.shasum : nil;
|
||||
NSString *certificateSHA256 = (rule.type == SNTRuleTypeCertificate) ? rule.shasum : nil;
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
dispatch_group_enter(group);
|
||||
__block NSMutableString *output;
|
||||
[[daemonConn remoteObjectProxy] decisionForFilePath:nil
|
||||
fileSHA256:fileSHA256
|
||||
certificateSHA256:certificateSHA256
|
||||
reply:^(SNTEventState s) {
|
||||
output = (SNTEventStateAllow & s) ? @"Whitelisted".mutableCopy : @"Blacklisted".mutableCopy;
|
||||
switch (s) {
|
||||
case SNTEventStateAllowUnknown:
|
||||
case SNTEventStateBlockUnknown:
|
||||
[output appendString:@" (Unknown)"];
|
||||
break;
|
||||
case SNTEventStateAllowBinary:
|
||||
case SNTEventStateBlockBinary:
|
||||
[output appendString:@" (Binary)"];
|
||||
break;
|
||||
case SNTEventStateAllowCertificate:
|
||||
case SNTEventStateBlockCertificate:
|
||||
[output appendString:@" (Certificate)"];
|
||||
break;
|
||||
case SNTEventStateAllowScope:
|
||||
case SNTEventStateBlockScope:
|
||||
[output appendString:@" (Scope)"];
|
||||
break;
|
||||
default:
|
||||
output = @"None".mutableCopy;
|
||||
break;
|
||||
}
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
if ((SNTEventStateAllow & s)) {
|
||||
[output insertString:@"\033[32m" atIndex:0];
|
||||
[output appendString:@"\033[0m"];
|
||||
} else if ((SNTEventStateBlock & s)) {
|
||||
[output insertString:@"\033[31m" atIndex:0];
|
||||
[output appendString:@"\033[0m"];
|
||||
} else {
|
||||
[output insertString:@"\033[33m" atIndex:0];
|
||||
[output appendString:@"\033[0m"];
|
||||
}
|
||||
}
|
||||
dispatch_group_leave(group);
|
||||
}];
|
||||
if (dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
|
||||
printf("Cannot communicate with daemon");
|
||||
exit(1);
|
||||
}
|
||||
printf("%s\n", output.UTF8String);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -120,6 +120,15 @@ REGISTER_COMMAND_NAME(@"status")
|
||||
}];
|
||||
}
|
||||
|
||||
__block BOOL bundlesEnabled = NO;
|
||||
if ([[SNTConfigurator configurator] syncBaseURL]) {
|
||||
dispatch_group_enter(group);
|
||||
[[daemonConn remoteObjectProxy] bundlesEnabled:^(BOOL response) {
|
||||
bundlesEnabled = response;
|
||||
dispatch_group_leave(group);
|
||||
}];
|
||||
}
|
||||
|
||||
// Wait a maximum of 5s for stats collected from daemon to arrive.
|
||||
if (dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5))) {
|
||||
fprintf(stderr, "Failed to retrieve some stats from daemon\n\n");
|
||||
@@ -148,7 +157,8 @@ REGISTER_COMMAND_NAME(@"status")
|
||||
@"clean_required" : @(syncCleanReqd),
|
||||
@"last_successful_full" : lastSyncSuccessStr ?: @"null",
|
||||
@"last_successful_rule" : lastRuleSyncSuccessStr ?: @"null",
|
||||
@"push_notifications" : pushNotifications ? @"Connected" : @"Disconnected"
|
||||
@"push_notifications" : pushNotifications ? @"Connected" : @"Disconnected",
|
||||
@"bundle_scanning" : @(bundlesEnabled)
|
||||
},
|
||||
};
|
||||
NSData *statsData = [NSJSONSerialization dataWithJSONObject:stats
|
||||
@@ -177,6 +187,7 @@ REGISTER_COMMAND_NAME(@"status")
|
||||
printf(" %-25s | %s\n", "Last Successful Rule Sync", [lastRuleSyncSuccessStr UTF8String]);
|
||||
printf(" %-25s | %s\n", "Push Notifications",
|
||||
(pushNotifications ? "Connected" : "Disconnected"));
|
||||
printf(" %-25s | %s\n", "Bundle Scanning", (bundlesEnabled ? "Yes" : "No"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,11 @@ REGISTER_COMMAND_NAME(@"sync")
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (![[SNTConfigurator configurator] syncBaseURL]) {
|
||||
LOGE(@"Missing SyncBaseURL. Exiting.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SNTCommandSync *s = [[self alloc] init];
|
||||
[daemonConn resume];
|
||||
BOOL daemon = [arguments containsObject:@"--daemon"];
|
||||
|
||||
@@ -34,6 +34,9 @@ extern NSString *const kBlacklistRegex;
|
||||
extern NSString *const kBinaryRuleCount;
|
||||
extern NSString *const kCertificateRuleCount;
|
||||
extern NSString *const kFCMToken;
|
||||
extern NSString *const kFCMFullSyncInterval;
|
||||
extern NSString *const kFCMGlobalRuleSyncDeadline;
|
||||
extern NSString *const kBundlesEnabled;
|
||||
|
||||
extern NSString *const kEvents;
|
||||
extern NSString *const kFileSHA256;
|
||||
@@ -59,6 +62,9 @@ extern NSString *const kFileBundlePath;
|
||||
extern NSString *const kFileBundleName;
|
||||
extern NSString *const kFileBundleVersion;
|
||||
extern NSString *const kFileBundleShortVersionString;
|
||||
extern NSString *const kFileBundleHash;
|
||||
extern NSString *const kFileBundleHashMilliseconds;
|
||||
extern NSString *const kFileBundleBinaryCount;
|
||||
extern NSString *const kPID;
|
||||
extern NSString *const kPPID;
|
||||
extern NSString *const kParentName;
|
||||
@@ -96,3 +102,17 @@ extern NSString *const kFullSync;
|
||||
extern NSString *const kRuleSync;
|
||||
extern NSString *const kConfigSync;
|
||||
extern NSString *const kLogSync;
|
||||
|
||||
extern const NSUInteger kDefaultEventBatchSize;
|
||||
|
||||
///
|
||||
/// kDefaultFullSyncInterval
|
||||
/// kDefaultFCMFullSyncInterval
|
||||
/// kDefaultFCMGlobalRuleSyncDeadline
|
||||
///
|
||||
/// Are represented in seconds
|
||||
///
|
||||
extern const NSUInteger kDefaultFullSyncInterval;
|
||||
extern const NSUInteger kDefaultFCMFullSyncInterval;
|
||||
extern const NSUInteger kDefaultFCMGlobalRuleSyncDeadline;
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ NSString *const kBlacklistRegex = @"blacklist_regex";
|
||||
NSString *const kBinaryRuleCount = @"binary_rule_count";
|
||||
NSString *const kCertificateRuleCount = @"certificate_rule_count";
|
||||
NSString *const kFCMToken = @"fcm_token";
|
||||
NSString *const kFCMFullSyncInterval = @"fcm_full_sync_interval";
|
||||
NSString *const kFCMGlobalRuleSyncDeadline = @"fcm_global_rule_sync_deadline";
|
||||
NSString *const kBundlesEnabled = @"bundles_enabled";
|
||||
|
||||
NSString *const kEvents = @"events";
|
||||
NSString *const kFileSHA256 = @"file_sha256";
|
||||
@@ -59,6 +62,9 @@ NSString *const kFileBundlePath = @"file_bundle_path";
|
||||
NSString *const kFileBundleName = @"file_bundle_name";
|
||||
NSString *const kFileBundleVersion = @"file_bundle_version";
|
||||
NSString *const kFileBundleShortVersionString = @"file_bundle_version_string";
|
||||
NSString *const kFileBundleHash = @"file_bundle_hash";
|
||||
NSString *const kFileBundleHashMilliseconds = @"file_bundle_hash_millis";
|
||||
NSString *const kFileBundleBinaryCount = @"file_bundle_binary_count";
|
||||
NSString *const kPID = @"pid";
|
||||
NSString *const kPPID = @"ppid";
|
||||
NSString *const kParentName = @"parent_name";
|
||||
@@ -96,3 +102,8 @@ NSString *const kFullSync = @"full_sync";
|
||||
NSString *const kRuleSync = @"rule_sync";
|
||||
NSString *const kConfigSync = @"config_sync";
|
||||
NSString *const kLogSync = @"log_sync";
|
||||
|
||||
const NSUInteger kDefaultEventBatchSize = 50;
|
||||
const NSUInteger kDefaultFullSyncInterval = 600;
|
||||
const NSUInteger kDefaultFCMFullSyncInterval = 14400;
|
||||
const NSUInteger kDefaultFCMGlobalRuleSyncDeadline = 600;
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
NSDictionary *r = [self performRequest:[self requestWithDictionary:@{ kEvents: uploadEvents }]];
|
||||
if (!r) return NO;
|
||||
|
||||
// A list of bundle hashes that require their related binary events to be uploaded.
|
||||
self.syncState.bundleBinaryRequests = r[kEventUploadBundleBinaries];
|
||||
|
||||
LOGI(@"Uploaded %lu events", uploadEvents.count);
|
||||
|
||||
// Remove event IDs. For Bundle Events the ID is 0 so nothing happens.
|
||||
@@ -97,7 +100,10 @@
|
||||
ADDKEY(newEvent, kDecision, kDecisionBlockCertificate);
|
||||
break;
|
||||
case SNTEventStateBlockScope: ADDKEY(newEvent, kDecision, kDecisionBlockScope); break;
|
||||
case SNTEventStateBundleBinary: ADDKEY(newEvent, kDecision, kDecisionBundleBinary); break;
|
||||
case SNTEventStateBundleBinary:
|
||||
ADDKEY(newEvent, kDecision, kDecisionBundleBinary);
|
||||
[newEvent removeObjectForKey:kExecutionTime];
|
||||
break;
|
||||
default: ADDKEY(newEvent, kDecision, kDecisionUnknown);
|
||||
}
|
||||
|
||||
@@ -106,6 +112,9 @@
|
||||
ADDKEY(newEvent, kFileBundleName, event.fileBundleName);
|
||||
ADDKEY(newEvent, kFileBundleVersion, event.fileBundleVersion);
|
||||
ADDKEY(newEvent, kFileBundleShortVersionString, event.fileBundleVersionString);
|
||||
ADDKEY(newEvent, kFileBundleHash, event.fileBundleHash);
|
||||
ADDKEY(newEvent, kFileBundleHashMilliseconds, event.fileBundleHashMilliseconds);
|
||||
ADDKEY(newEvent, kFileBundleBinaryCount, event.fileBundleBinaryCount);
|
||||
|
||||
ADDKEY(newEvent, kPID, event.pid);
|
||||
ADDKEY(newEvent, kPPID, event.ppid);
|
||||
|
||||
@@ -28,31 +28,40 @@
|
||||
#import "SNTCommandSyncRuleDownload.h"
|
||||
#import "SNTCommandSyncState.h"
|
||||
#import "SNTLogging.h"
|
||||
#import "SNTStoredEvent.h"
|
||||
#import "SNTStrengthify.h"
|
||||
#import "SNTXPCConnection.h"
|
||||
#import "SNTXPCControlInterface.h"
|
||||
#import "SNTXPCSyncdInterface.h"
|
||||
|
||||
// Syncing time constant
|
||||
const uint64_t kFullSyncInterval = 600;
|
||||
|
||||
@interface SNTCommandSyncManager () {
|
||||
SCNetworkReachabilityRef _reachability;
|
||||
}
|
||||
|
||||
@property(nonatomic) dispatch_source_t fullSyncTimer;
|
||||
@property(nonatomic) dispatch_source_t ruleSyncTimer;
|
||||
|
||||
@property(nonatomic) NSCache *dispatchLock;
|
||||
@property(nonatomic) NSCache *ruleSyncCache;
|
||||
|
||||
@property NSUInteger FCMFullSyncInterval;
|
||||
@property NSUInteger FCMGlobalRuleSyncDeadline;
|
||||
@property NSUInteger eventBatchSize;
|
||||
|
||||
@property MOLFCMClient *FCMClient;
|
||||
|
||||
@property(nonatomic) SNTXPCConnection *daemonConn;
|
||||
|
||||
@property BOOL targetedRuleSync;
|
||||
|
||||
@property(nonatomic) BOOL reachable;
|
||||
|
||||
@end
|
||||
|
||||
// Called when the network state changes
|
||||
static void reachabilityHandler(
|
||||
SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) {
|
||||
// Ensure state changes are processed in order.
|
||||
// Put this check and set on the main thread to ensure serial access.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
SNTCommandSyncManager *commandSyncManager = (__bridge SNTCommandSyncManager *)info;
|
||||
// Only call the setter when there is a change. This will filter out the redundant calls to this
|
||||
@@ -73,8 +82,7 @@ static void reachabilityHandler(
|
||||
_daemonConn = daemonConn;
|
||||
_daemon = daemon;
|
||||
_fullSyncTimer = [self createSyncTimerWithBlock:^{
|
||||
[self rescheduleTimerQueue:self.fullSyncTimer
|
||||
secondsFromNow:[SNTConfigurator configurator].FCMFullSyncInterval];
|
||||
[self rescheduleTimerQueue:self.fullSyncTimer secondsFromNow:self.FCMFullSyncInterval];
|
||||
if (![[SNTConfigurator configurator] syncBaseURL]) return;
|
||||
[self lockAction:kFullSync];
|
||||
[self preflight];
|
||||
@@ -99,12 +107,44 @@ static void reachabilityHandler(
|
||||
}];
|
||||
_dispatchLock = [[NSCache alloc] init];
|
||||
_ruleSyncCache = [[NSCache alloc] init];
|
||||
|
||||
_eventBatchSize = kDefaultEventBatchSize;
|
||||
_FCMFullSyncInterval = kDefaultFCMFullSyncInterval;
|
||||
_FCMGlobalRuleSyncDeadline = kDefaultFCMGlobalRuleSyncDeadline;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark SNTSyncdXPC protocol methods
|
||||
|
||||
- (void)postBundleEventToSyncServer:(SNTStoredEvent *)event reply:(void (^)(BOOL))reply {
|
||||
SNTCommandSyncState *syncState = [self createSyncState];
|
||||
SNTCommandSyncEventUpload *p = [[SNTCommandSyncEventUpload alloc] initWithState:syncState];
|
||||
if (event && [p uploadEvents:@[event]]) {
|
||||
BOOL needsRelatedEvents = [syncState.bundleBinaryRequests containsObject:event.fileBundleHash];
|
||||
reply(needsRelatedEvents);
|
||||
if (needsRelatedEvents) {
|
||||
LOGD(@"Needs related events");
|
||||
} else {
|
||||
LOGD(@"Bundle event upload complete");
|
||||
}
|
||||
} else {
|
||||
reply(NO);
|
||||
LOGE(@"Bundle event upload failed");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)postBundleEventsToSyncServer:(NSArray<SNTStoredEvent *> *)events {
|
||||
SNTCommandSyncState *syncState = [self createSyncState];
|
||||
syncState.eventBatchSize = self.eventBatchSize;
|
||||
SNTCommandSyncEventUpload *p = [[SNTCommandSyncEventUpload alloc] initWithState:syncState];
|
||||
if (events && [p uploadEvents:events]) {
|
||||
LOGD(@"Bundle events upload complete");
|
||||
} else {
|
||||
LOGE(@"Bundle events upload failed");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)postEventToSyncServer:(SNTStoredEvent *)event {
|
||||
SNTCommandSyncEventUpload *p = [[SNTCommandSyncEventUpload alloc]
|
||||
initWithState:[self createSyncState]];
|
||||
@@ -115,10 +155,6 @@ static void reachabilityHandler(
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rescheduleSyncSecondsFromNow:(uint64_t)seconds {
|
||||
[self rescheduleTimerQueue:self.fullSyncTimer secondsFromNow:seconds];
|
||||
}
|
||||
|
||||
- (void)isFCMListening:(void (^)(BOOL))reply {
|
||||
reply((self.FCMClient.FCMToken != nil));
|
||||
}
|
||||
@@ -152,7 +188,7 @@ static void reachabilityHandler(
|
||||
LOGE(@"FCM connection error: %@", error);
|
||||
[self.FCMClient disconnect];
|
||||
self.FCMClient = nil;
|
||||
[self rescheduleTimerQueue:self.fullSyncTimer secondsFromNow:kFullSyncInterval];
|
||||
[self rescheduleTimerQueue:self.fullSyncTimer secondsFromNow:kDefaultFullSyncInterval];
|
||||
};
|
||||
|
||||
self.FCMClient.loggingBlock = ^(NSString *log) {
|
||||
@@ -203,9 +239,8 @@ static void reachabilityHandler(
|
||||
self.targetedRuleSync = YES;
|
||||
[self ruleSync];
|
||||
} else {
|
||||
uint32_t delaySeconds =
|
||||
arc4random_uniform((u_int32_t)[SNTConfigurator configurator].FCMGlobalRuleLeeway);
|
||||
LOGD(@"Staggering rule download, %u second delay for this machine", delaySeconds);
|
||||
uint32_t delaySeconds = arc4random_uniform((uint32_t)self.FCMGlobalRuleSyncDeadline);
|
||||
LOGD(@"Staggering rule download: %u second delay", delaySeconds);
|
||||
[self ruleSyncSecondsFromNow:delaySeconds];
|
||||
}
|
||||
} else if ([action isEqualToString:kConfigSync]) {
|
||||
@@ -266,15 +301,18 @@ static void reachabilityHandler(
|
||||
// Clean up reachability if it was started for a non-network error
|
||||
[self stopReachability];
|
||||
|
||||
// Start listening for push notifications with a full sync every kFullSyncFCMInterval or
|
||||
// revert to full syncing every kFullSyncInterval.
|
||||
self.eventBatchSize = syncState.eventBatchSize;
|
||||
|
||||
// Start listening for push notifications with a full sync every FCMFullSyncInterval
|
||||
if (syncState.daemon && syncState.FCMToken) {
|
||||
self.FCMFullSyncInterval = syncState.FCMFullSyncInterval;
|
||||
self.FCMGlobalRuleSyncDeadline = syncState.FCMGlobalRuleSyncDeadline;
|
||||
[self listenForPushNotificationsWithSyncState:syncState];
|
||||
} else if (syncState.daemon) {
|
||||
LOGD(@"FCMToken not provided. Sync every %llu min.", kFullSyncInterval / 60);
|
||||
LOGD(@"FCMToken not provided. Sync every %lu min.", kDefaultFullSyncInterval / 60);
|
||||
[self.FCMClient disconnect];
|
||||
self.FCMClient = nil;
|
||||
[self rescheduleTimerQueue:self.fullSyncTimer secondsFromNow:kFullSyncInterval];
|
||||
[self rescheduleTimerQueue:self.fullSyncTimer secondsFromNow:kDefaultFullSyncInterval];
|
||||
}
|
||||
|
||||
if (syncState.uploadLogURL) {
|
||||
@@ -373,8 +411,11 @@ static void reachabilityHandler(
|
||||
LOGW(@"Missing Machine Owner.");
|
||||
}
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
dispatch_group_enter(group);
|
||||
[[self.daemonConn remoteObjectProxy] xsrfToken:^(NSString *token) {
|
||||
syncState.xsrfToken = token;
|
||||
dispatch_group_leave(group);
|
||||
}];
|
||||
|
||||
MOLAuthenticatingURLSession *authURLSession = [[MOLAuthenticatingURLSession alloc] init];
|
||||
@@ -409,7 +450,8 @@ static void reachabilityHandler(
|
||||
syncState.session = [authURLSession session];
|
||||
syncState.daemonConn = self.daemonConn;
|
||||
syncState.daemon = self.daemon;
|
||||
|
||||
|
||||
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));
|
||||
return syncState;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
}
|
||||
|
||||
- (BOOL)sync {
|
||||
NSDictionary *r = [self performRequest:[self requestWithDictionary:nil]];
|
||||
[self performRequest:[self requestWithDictionary:nil]];
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
void (^replyBlock)() = ^{
|
||||
@@ -43,14 +43,6 @@
|
||||
reply:replyBlock];
|
||||
}
|
||||
|
||||
// Update backoff interval
|
||||
NSString *backoffInterval = r[kBackoffInterval];
|
||||
if (backoffInterval) {
|
||||
dispatch_group_enter(group);
|
||||
[[self.daemonConn remoteObjectProxy] setNextSyncInterval:[backoffInterval intValue]
|
||||
reply:replyBlock];
|
||||
}
|
||||
|
||||
// Remove clean sync flag if we did a clean sync
|
||||
if (self.syncState.cleanSync) {
|
||||
dispatch_group_enter(group);
|
||||
|
||||
@@ -74,9 +74,21 @@
|
||||
|
||||
if (!resp) return NO;
|
||||
|
||||
dispatch_group_enter(group);
|
||||
[[self.daemonConn remoteObjectProxy] setBundlesEnabled:[resp[kBundlesEnabled] boolValue] reply:^{
|
||||
dispatch_group_leave(group);
|
||||
}];
|
||||
|
||||
self.syncState.eventBatchSize = [resp[kBatchSize] unsignedIntegerValue] ?: kDefaultEventBatchSize;
|
||||
self.syncState.FCMToken = resp[kFCMToken];
|
||||
|
||||
self.syncState.eventBatchSize = [resp[kBatchSize] intValue] ?: 50;
|
||||
// Don't let these go too low
|
||||
NSUInteger value = [resp[kFCMFullSyncInterval] unsignedIntegerValue];
|
||||
self.syncState.FCMFullSyncInterval =
|
||||
(value < kDefaultFullSyncInterval) ? kDefaultFCMFullSyncInterval : value;
|
||||
value = [resp[kFCMGlobalRuleSyncDeadline] unsignedIntegerValue];
|
||||
self.syncState.FCMGlobalRuleSyncDeadline =
|
||||
(value < 60) ? kDefaultFCMGlobalRuleSyncDeadline : value;
|
||||
|
||||
self.syncState.uploadLogURL = [NSURL URLWithString:resp[kUploadLogsURL]];
|
||||
|
||||
@@ -99,6 +111,7 @@
|
||||
self.syncState.cleanSync = YES;
|
||||
}
|
||||
|
||||
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC));
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#import "SNTCommonEnums.h"
|
||||
|
||||
@class SNTCommandSyncManager;
|
||||
@class SNTXPCConnection;
|
||||
|
||||
/// An instance of this class is passed to each stage of the sync process for storing data
|
||||
@@ -34,9 +35,15 @@
|
||||
/// An XSRF token to send in the headers with each request.
|
||||
@property NSString *xsrfToken;
|
||||
|
||||
/// A FCM token to subscribe to push notifications.
|
||||
/// An FCM token to subscribe to push notifications.
|
||||
@property(copy) NSString *FCMToken;
|
||||
|
||||
/// Full sync interval in seconds while listening for FCM messages.
|
||||
@property NSUInteger FCMFullSyncInterval;
|
||||
|
||||
/// Leeway time in seconds when receiving a global rule sync message.
|
||||
@property NSUInteger FCMGlobalRuleSyncDeadline;
|
||||
|
||||
/// Machine identifier and owner.
|
||||
@property(copy) NSString *machineID;
|
||||
@property(copy) NSString *machineOwner;
|
||||
@@ -55,7 +62,7 @@
|
||||
/// Log upload URL sent from server. If set, LogUpload phase needs to happen.
|
||||
@property NSURL *uploadLogURL;
|
||||
|
||||
/// Array of bundle paths to find binaries for.
|
||||
/// Array of bundle IDs to find binaries for.
|
||||
@property NSArray *bundleBinaryRequests;
|
||||
|
||||
/// Rules downloaded from server.
|
||||
|
||||
@@ -32,6 +32,14 @@
|
||||
///
|
||||
- (BOOL)addStoredEvent:(SNTStoredEvent *)event;
|
||||
|
||||
///
|
||||
/// Add events to the database.
|
||||
///
|
||||
/// @param events the events to store.
|
||||
/// @return YES if events were successfully stored.
|
||||
///
|
||||
- (BOOL)addStoredEvents:(NSArray<SNTStoredEvent *> *)events;
|
||||
|
||||
///
|
||||
/// Retrieves all events in the database
|
||||
///
|
||||
|
||||
@@ -83,24 +83,37 @@
|
||||
#pragma mark Loading / Storing
|
||||
|
||||
- (BOOL)addStoredEvent:(SNTStoredEvent *)event {
|
||||
if (!event.idx ||
|
||||
!event.fileSHA256 ||
|
||||
!event.filePath ||
|
||||
!event.occurrenceDate ||
|
||||
!event.decision) return NO;
|
||||
return [self addStoredEvents:@[event]];
|
||||
}
|
||||
|
||||
NSData *eventData;
|
||||
@try {
|
||||
eventData = [NSKeyedArchiver archivedDataWithRootObject:event];
|
||||
} @catch (NSException *exception) {
|
||||
return NO;
|
||||
- (BOOL)addStoredEvents:(NSArray<SNTStoredEvent *> *)events {
|
||||
NSMutableDictionary *eventsData = [NSMutableDictionary dictionaryWithCapacity:events.count];
|
||||
for (SNTStoredEvent *event in events) {
|
||||
if (!event.idx ||
|
||||
!event.fileSHA256 ||
|
||||
!event.filePath ||
|
||||
!event.occurrenceDate ||
|
||||
!event.decision) continue;
|
||||
|
||||
NSData *eventData;
|
||||
@try {
|
||||
eventData = [NSKeyedArchiver archivedDataWithRootObject:event];
|
||||
} @catch (NSException *exception) {
|
||||
continue;
|
||||
}
|
||||
eventsData[eventData] = event;
|
||||
}
|
||||
|
||||
__block BOOL success = NO;
|
||||
[self inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
||||
success = [db executeUpdate:@"INSERT INTO 'events' (idx, filesha256, eventdata)"
|
||||
@"VALUES (?, ?, ?)",
|
||||
event.idx, event.fileSHA256, eventData];
|
||||
[eventsData enumerateKeysAndObjectsUsingBlock:^(NSData * eventData,
|
||||
SNTStoredEvent * event,
|
||||
BOOL *stop) {
|
||||
success = [db executeUpdate:@"INSERT INTO 'events' (idx, filesha256, eventdata)"
|
||||
@"VALUES (?, ?, ?)",
|
||||
event.idx, event.fileSHA256, eventData];
|
||||
if (!success) *stop = YES;
|
||||
}];
|
||||
}];
|
||||
|
||||
return success;
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
#import "SNTPolicyProcessor.h"
|
||||
#import "SNTRule.h"
|
||||
#import "SNTRuleTable.h"
|
||||
#import "SNTStoredEvent.h"
|
||||
#import "SNTStrengthify.h"
|
||||
#import "SNTSyncdQueue.h"
|
||||
#import "SNTXPCBundleServiceInterface.h"
|
||||
#import "SNTXPCConnection.h"
|
||||
#import "SNTXPCNotifierInterface.h"
|
||||
#import "SNTXPCSyncdInterface.h"
|
||||
@@ -112,15 +115,19 @@ double watchdogRAMPeak = 0;
|
||||
|
||||
- (void)decisionForFilePath:(NSString *)filePath
|
||||
fileSHA256:(NSString *)fileSHA256
|
||||
signingCertificate:(MOLCertificate *)signingCertificate
|
||||
certificateSHA256:(NSString *)certificateSHA256
|
||||
reply:(void (^)(SNTEventState))reply {
|
||||
reply([self.policyProcessor decisionForFilePath:filePath
|
||||
fileSHA256:fileSHA256
|
||||
signingCertificate:signingCertificate].decision);
|
||||
certificateSHA256:certificateSHA256].decision);
|
||||
}
|
||||
|
||||
#pragma mark Config Ops
|
||||
|
||||
- (void)watchdogInfo:(void (^)(uint64_t, uint64_t, double, double))reply {
|
||||
reply(watchdogCPUEvents, watchdogRAMEvents, watchdogCPUPeak, watchdogRAMPeak);
|
||||
}
|
||||
|
||||
- (void)clientMode:(void (^)(SNTClientMode))reply {
|
||||
reply([[SNTConfigurator configurator] clientMode]);
|
||||
}
|
||||
@@ -177,8 +184,13 @@ double watchdogRAMPeak = 0;
|
||||
reply();
|
||||
}
|
||||
|
||||
- (void)watchdogInfo:(void (^)(uint64_t, uint64_t, double, double))reply {
|
||||
reply(watchdogCPUEvents, watchdogRAMEvents, watchdogCPUPeak, watchdogRAMPeak);
|
||||
- (void)bundlesEnabled:(void (^)(BOOL))reply {
|
||||
reply([SNTConfigurator configurator].bundlesEnabled);
|
||||
}
|
||||
|
||||
- (void)setBundlesEnabled:(BOOL)bundlesEnabled reply:(void (^)())reply {
|
||||
[[SNTConfigurator configurator] setBundlesEnabled:bundlesEnabled];
|
||||
reply();
|
||||
}
|
||||
|
||||
#pragma mark GUI Ops
|
||||
@@ -190,6 +202,13 @@ double watchdogRAMPeak = 0;
|
||||
self.notQueue.notifierConnection = c;
|
||||
}
|
||||
|
||||
- (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener {
|
||||
SNTXPCConnection *bs = [[SNTXPCConnection alloc] initClientWithServiceName:@"com.google.santabs"];
|
||||
bs.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface];
|
||||
[bs resume];
|
||||
[[bs remoteObjectProxy] setBundleNotificationListener:listener];
|
||||
}
|
||||
|
||||
#pragma mark syncd Ops
|
||||
|
||||
- (void)setSyncdListener:(NSXPCListenerEndpoint *)listener {
|
||||
@@ -209,12 +228,6 @@ double watchdogRAMPeak = 0;
|
||||
self.syncdQueue.syncdConnection = c;
|
||||
}
|
||||
|
||||
- (void)setNextSyncInterval:(uint64_t)seconds reply:(void (^)())reply {
|
||||
[[self.syncdQueue.syncdConnection remoteObjectProxy] rescheduleSyncSecondsFromNow:seconds];
|
||||
[[SNTConfigurator configurator] setSyncBackOff:YES];
|
||||
reply();
|
||||
}
|
||||
|
||||
- (void)pushNotifications:(void (^)(BOOL))reply {
|
||||
[self.syncdQueue.syncdConnection.remoteObjectProxy isFCMListening:^(BOOL response) {
|
||||
reply(response);
|
||||
@@ -227,4 +240,57 @@ double watchdogRAMPeak = 0;
|
||||
reply();
|
||||
}
|
||||
|
||||
#pragma mark Bundle ops
|
||||
|
||||
///
|
||||
/// This method is only used for santactl's bundleinfo command. For blocked executions, SantaGUI
|
||||
/// calls on santabs directly.
|
||||
///
|
||||
/// Hash a bundle for an event. The SNTBundleHashBlock will be called with nil parameters if a
|
||||
/// failure or cancellation occurs.
|
||||
///
|
||||
/// @param event The event that includes the fileBundlePath to be hashed.
|
||||
/// @param reply A SNTBundleHashBlock to be executed upon completion or cancellation.
|
||||
///
|
||||
/// @note If there is a current NSProgress when called this method will report back it's progress.
|
||||
///
|
||||
- (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event
|
||||
reply:(SNTBundleHashBlock)reply {
|
||||
SNTXPCConnection *bs =
|
||||
[[SNTXPCConnection alloc] initClientWithServiceName:[SNTXPCBundleServiceInterface serviceId]];
|
||||
bs.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface];
|
||||
[bs resume];
|
||||
[[bs remoteObjectProxy] hashBundleBinariesForEvent:event reply:reply];
|
||||
}
|
||||
|
||||
///
|
||||
/// Used by SantaGUI sync the offending event and potentially all the related events,
|
||||
/// if the sync server has not seen them before.
|
||||
///
|
||||
/// @param event The offending event, fileBundleHash & fileBundleBinaryCount need to be populated.
|
||||
/// @param relatedEvents Nexted bundle events.
|
||||
///
|
||||
- (void)syncBundleEvent:(SNTStoredEvent *)event
|
||||
relatedEvents:(NSArray<SNTStoredEvent *> *)events {
|
||||
SNTEventTable *eventTable = [SNTDatabaseController eventTable];
|
||||
|
||||
// Delete the event cached by the execution controller.
|
||||
[eventTable deleteEventWithId:event.idx];
|
||||
|
||||
// Add the updated event.
|
||||
[eventTable addStoredEvent:event];
|
||||
|
||||
WEAKIFY(self);
|
||||
|
||||
// Sync the updated event. If the sync server needs the related events, add them to the eventTable
|
||||
// and upload them too.
|
||||
[self.syncdQueue addBundleEvent:event reply:^(BOOL needRelatedEvents) {
|
||||
STRONGIFY(self);
|
||||
if (needRelatedEvents) {
|
||||
[eventTable addStoredEvents:events];
|
||||
[self.syncdQueue addBundleEvents:events];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -115,7 +115,8 @@
|
||||
// Actually make the decision.
|
||||
SNTCachedDecision *cd = [self.policyProcessor decisionForFileInfo:binInfo
|
||||
fileSHA256:nil
|
||||
signingCertificate:csInfo.leafCertificate];
|
||||
certificateSHA256:csInfo.leafCertificate.SHA256];
|
||||
cd.certCommonName = csInfo.leafCertificate.commonName;
|
||||
cd.vnodeId = message.vnode_id;
|
||||
|
||||
// Formulate an action from the decision
|
||||
@@ -176,11 +177,19 @@
|
||||
if (action != ACTION_RESPOND_ALLOW) {
|
||||
[_eventLog logDeniedExecution:cd withMessage:message];
|
||||
|
||||
// So the server has something to show the user straight away, initiate an event
|
||||
// upload for the blocked binary rather than waiting for the next sync.
|
||||
dispatch_async(_eventQueue, ^{
|
||||
[self initiateEventUploadForEvent:se];
|
||||
});
|
||||
if ([[SNTConfigurator configurator] bundlesEnabled] && binInfo.bundle) {
|
||||
// If the binary is apart of a bundle, find and hash all the related binaries in the bundle.
|
||||
// Let the GUI know hashing is needed. Once the hashing is complete the GUI will send a
|
||||
// message to santad to perform the upload logic for bundles.
|
||||
// See syncBundleEvent:relatedEvents: for more info.
|
||||
se.needsBundleHash = YES;
|
||||
} else if ([[SNTConfigurator configurator] syncBaseURL]) {
|
||||
// So the server has something to show the user straight away, initiate an event
|
||||
// upload for the blocked binary rather than waiting for the next sync.
|
||||
dispatch_async(_eventQueue, ^{
|
||||
[_syncdQueue addEvent:se];
|
||||
});
|
||||
}
|
||||
|
||||
if (!cd.silentBlock) {
|
||||
// Let the user know what happened, both on the terminal and in the GUI.
|
||||
@@ -245,24 +254,6 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
/**
|
||||
This sends the event that was just saved to santactl for immediate upload, so that the user
|
||||
has something to vote in straight away.
|
||||
|
||||
This method is always called on a serial queue to keep this low-priority method
|
||||
away from the high-priority decision making threads.
|
||||
*/
|
||||
- (void)initiateEventUploadForEvent:(SNTStoredEvent *)event {
|
||||
// The event upload is skipped if the full path is equal to that of santactl so that
|
||||
// on the off chance that santactl is not whitelisted, we don't get into an infinite loop.
|
||||
// It's also skipped if there isn't a server configured or the last sync caused a backoff.
|
||||
if ([event.filePath isEqual:@(kSantaCtlPath)] ||
|
||||
![[SNTConfigurator configurator] syncBaseURL] ||
|
||||
[[SNTConfigurator configurator] syncBackOff]) return;
|
||||
|
||||
[self.syncdQueue addEvent:event];
|
||||
}
|
||||
|
||||
- (void)printMessage:(NSString *)msg toTTYForPID:(pid_t)pid {
|
||||
if (pid < 2) return; // don't bother even looking for launchd.
|
||||
|
||||
|
||||
@@ -39,22 +39,24 @@
|
||||
/// @param fileInfo A SNTFileInfo object.
|
||||
/// @param fileSHA256 The pre-calculated SHA256 hash for the file, can be nil. If nil the hash will
|
||||
/// be calculated by this method from the filePath.
|
||||
/// @param signingCertificate A MOLCertificate object, can be nil.
|
||||
/// @note If fileInfo and signingCertificate are both passed in, the most specific rule will be
|
||||
/// @param certificateSHA256 A SHA256 hash of the signing certificate, can be nil.
|
||||
/// @note If fileSHA256 and certificateSHA256 are both passed in, the most specific rule will be
|
||||
/// returned. Binary rules take precedence over cert rules.
|
||||
/// @note This method can also be used to generate a SNTCachedDecision object without any
|
||||
/// artifacts on disk. Simply pass nil to fileInfo and pass in the desired SHA256s.
|
||||
///
|
||||
- (nonnull SNTCachedDecision *)decisionForFileInfo:(nonnull SNTFileInfo *)fileInfo
|
||||
- (nonnull SNTCachedDecision *)decisionForFileInfo:(nullable SNTFileInfo *)fileInfo
|
||||
fileSHA256:(nullable NSString *)fileSHA256
|
||||
signingCertificate:(nullable MOLCertificate *)signingCertificate;
|
||||
certificateSHA256:(nullable NSString *)certificateSHA256;
|
||||
|
||||
///
|
||||
/// A wrapper for decisionForFileInfo:fileSHA256:signingCertificate:. This method is slower as it
|
||||
/// A wrapper for decisionForFileInfo:fileSHA256:certificateSHA256:. This method is slower as it
|
||||
/// has to create the SNTFileInfo object. This is mainly used by the santactl binary because
|
||||
/// SNTFileInfo is not SecureCoding compliant. If the SHA256 hash of the file has already been
|
||||
/// calculated, use the fileSHA256 parameter to save a second calculation of the hash.
|
||||
///
|
||||
- (nonnull SNTCachedDecision *)decisionForFilePath:(nonnull NSString *)filePath
|
||||
- (nonnull SNTCachedDecision *)decisionForFilePath:(nullable NSString *)filePath
|
||||
fileSHA256:(nullable NSString *)fileSHA256
|
||||
signingCertificate:(nullable MOLCertificate *)signingCertificate;
|
||||
certificateSHA256:(nullable NSString *)certificateSHA256;
|
||||
|
||||
@end
|
||||
|
||||
@@ -38,14 +38,11 @@
|
||||
|
||||
- (SNTCachedDecision *)decisionForFileInfo:(SNTFileInfo *)fileInfo
|
||||
fileSHA256:(NSString *)fileSHA256
|
||||
signingCertificate:(MOLCertificate *)signingCertificate {
|
||||
certificateSHA256:(NSString *)certificateSHA256 {
|
||||
SNTCachedDecision *cd = [[SNTCachedDecision alloc] init];
|
||||
cd.sha256 = fileSHA256 ?: fileInfo.SHA256;
|
||||
cd.certSHA256 = certificateSHA256;
|
||||
cd.quarantineURL = fileInfo.quarantineDataURL;
|
||||
if (signingCertificate) {
|
||||
cd.certCommonName = signingCertificate.commonName;
|
||||
cd.certSHA256 = signingCertificate.SHA256;
|
||||
}
|
||||
|
||||
SNTRule *rule = [self.ruleTable ruleForBinarySHA256:cd.sha256
|
||||
certificateSHA256:cd.certSHA256];
|
||||
@@ -113,13 +110,16 @@
|
||||
|
||||
- (SNTCachedDecision *)decisionForFilePath:(NSString *)filePath
|
||||
fileSHA256:(NSString *)fileSHA256
|
||||
signingCertificate:(MOLCertificate *)signingCertificate {
|
||||
NSError *error;
|
||||
SNTFileInfo *fileInfo = [[SNTFileInfo alloc] initWithPath:filePath error:&error];
|
||||
if (!fileInfo) LOGW(@"Failed to read file %@: %@", filePath, error.localizedDescription);
|
||||
certificateSHA256:(NSString *)certificateSHA256 {
|
||||
SNTFileInfo *fileInfo;
|
||||
if (filePath) {
|
||||
NSError *error;
|
||||
fileInfo = [[SNTFileInfo alloc] initWithPath:filePath error:&error];
|
||||
if (!fileInfo) LOGW(@"Failed to read file %@: %@", filePath, error.localizedDescription);
|
||||
}
|
||||
return [self decisionForFileInfo:fileInfo
|
||||
fileSHA256:fileSHA256
|
||||
signingCertificate:signingCertificate];
|
||||
certificateSHA256:certificateSHA256];
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
@property(copy) void (^acceptedHandler)();
|
||||
|
||||
- (void)addEvent:(SNTStoredEvent *)event;
|
||||
- (void)addBundleEvents:(NSArray<SNTStoredEvent *> *)events;
|
||||
- (void)addBundleEvent:(SNTStoredEvent *)event reply:(void (^)(BOOL))reply;
|
||||
- (void)startSyncingEvents;
|
||||
- (void)stopSyncingEvents;
|
||||
|
||||
|
||||
@@ -38,27 +38,31 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addBundleEvents:(NSArray<SNTStoredEvent *> *)events {
|
||||
if (![self backoffForBundleHash:events.firstObject.fileBundleHash]) return;
|
||||
[self dispatchBlockOnSyncdQueue:^{
|
||||
[self.syncdConnection.remoteObjectProxy postBundleEventsToSyncServer:events];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)addBundleEvent:(SNTStoredEvent *)event reply:(void (^)(BOOL))reply {
|
||||
if (![self backoffForBundleHash:event.fileBundleHash]) return;
|
||||
[self dispatchBlockOnSyncdQueue:^{
|
||||
[self.syncdConnection.remoteObjectProxy postBundleEventToSyncServer:event
|
||||
reply:^(BOOL needRelatedEvents) {
|
||||
// Remove the backoff entry for the inital block event. The same event will be included in the
|
||||
// related events synced using addBundleEvents:.
|
||||
if (needRelatedEvents) [self.uploadBackoff removeObjectForKey:event.fileBundleHash];
|
||||
reply(needRelatedEvents);
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)addEvent:(SNTStoredEvent *)event {
|
||||
// The event upload is skipped if an event upload has been initiated for it in the
|
||||
// last 10 minutes.
|
||||
NSDate *backoff = [self.uploadBackoff objectForKey:event.fileSHA256];
|
||||
NSDate *now = [NSDate date];
|
||||
if (([now timeIntervalSince1970] - [backoff timeIntervalSince1970]) < 600) return;
|
||||
[self.uploadBackoff setObject:now forKey:event.fileSHA256];
|
||||
|
||||
// Hold events for a few seconds to allow santad and santactl to establish connections.
|
||||
// If the connections are not established in time drop the event from the queue.
|
||||
// They will be uploaded during a full sync.
|
||||
dispatch_async(self.syncdQueue, ^{
|
||||
if (!dispatch_semaphore_wait(self.sema, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC))) {
|
||||
[self.syncdConnection.remoteObjectProxy postEventToSyncServer:event];
|
||||
|
||||
// Let em flow
|
||||
dispatch_semaphore_signal(self.sema);
|
||||
} else {
|
||||
LOGI(@"Dropping event %@ from com.google.syncd_queue", event.fileSHA256);
|
||||
}
|
||||
});
|
||||
if (![self backoffForEvent:event]) return;
|
||||
[self dispatchBlockOnSyncdQueue:^{
|
||||
[self.syncdConnection.remoteObjectProxy postEventToSyncServer:event];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)startSyncingEvents {
|
||||
@@ -69,4 +73,38 @@
|
||||
self.sema = dispatch_semaphore_create(0);
|
||||
}
|
||||
|
||||
// Hold events for a few seconds to allow santad and santactl to establish connections.
|
||||
// If the connections are not established in time drop the event from the queue.
|
||||
// They will be uploaded during a full sync.
|
||||
- (void)dispatchBlockOnSyncdQueue:(void (^)())block {
|
||||
dispatch_async(self.syncdQueue, ^{
|
||||
if (!dispatch_semaphore_wait(self.sema, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC))) {
|
||||
if (block) block();
|
||||
dispatch_semaphore_signal(self.sema);
|
||||
} else {
|
||||
LOGD(@"Dropping block %@ from com.google.syncd_queue", block);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// The event upload is skipped if an event upload has been initiated for it in the
|
||||
// last 10 minutes.
|
||||
- (BOOL)backoffForEvent:(SNTStoredEvent *)event {
|
||||
NSDate *backoff = [self.uploadBackoff objectForKey:event.fileSHA256];
|
||||
NSDate *now = [NSDate date];
|
||||
if (([now timeIntervalSince1970] - [backoff timeIntervalSince1970]) < 600) return NO;
|
||||
[self.uploadBackoff setObject:now forKey:event.fileSHA256];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// The bundle event upload is skipped if a bundle event has been initiated for it in the
|
||||
// last 10 minutes.
|
||||
- (BOOL)backoffForBundleHash:(NSString *)bundleHash {
|
||||
NSDate *backoff = [self.uploadBackoff objectForKey:bundleHash];
|
||||
NSDate *now = [NSDate date];
|
||||
if (([now timeIntervalSince1970] - [backoff timeIntervalSince1970]) < 600) return NO;
|
||||
[self.uploadBackoff setObject:now forKey:bundleHash];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>16F73</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>BundleExample</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.google.santa.BundleExample</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>BundleExample</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>7D1014</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>15E60</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.11</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0731</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>7D1014</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.12</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2017 Google. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
Tests/LogicTests/Resources/BundleExample.app/Contents/MacOS/BundleExample
Executable file
BIN
Tests/LogicTests/Resources/BundleExample.app/Contents/MacOS/BundleExample
Executable file
Binary file not shown.
@@ -120,16 +120,88 @@
|
||||
}
|
||||
|
||||
- (void)testBundle {
|
||||
SNTFileInfo *sut =
|
||||
[[SNTFileInfo alloc] initWithPath:@"/Applications/Safari.app/Contents/MacOS/Safari"];
|
||||
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"BundleExample"
|
||||
ofType:@"app"];
|
||||
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
|
||||
|
||||
XCTAssertNotNil([sut bundle]);
|
||||
|
||||
XCTAssertEqualObjects([sut bundleIdentifier], @"com.apple.Safari");
|
||||
XCTAssertEqualObjects([sut bundleName], @"Safari");
|
||||
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.santa.BundleExample");
|
||||
XCTAssertEqualObjects([sut bundleName], @"BundleExample");
|
||||
XCTAssertEqualObjects([sut bundleVersion], @"1");
|
||||
XCTAssertEqualObjects([sut bundleShortVersionString], @"1.0");
|
||||
XCTAssertEqualObjects([sut bundlePath], path);
|
||||
}
|
||||
|
||||
- (void)testAncestorBundle {
|
||||
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"BundleExample"
|
||||
ofType:@"app"];
|
||||
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
|
||||
sut.useAncestorBundle = YES;
|
||||
|
||||
XCTAssertNotNil([sut bundle]);
|
||||
|
||||
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.LogicTests");
|
||||
XCTAssertNotNil([sut bundleVersion]);
|
||||
XCTAssertNotNil([sut bundleShortVersionString]);
|
||||
XCTAssertEqualObjects([sut bundlePath], @"/Applications/Safari.app");
|
||||
|
||||
NSString *ancestorBundlePath = path;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ancestorBundlePath = [ancestorBundlePath stringByDeletingLastPathComponent];
|
||||
}
|
||||
XCTAssertEqualObjects([sut bundlePath], ancestorBundlePath);
|
||||
}
|
||||
|
||||
- (void)testBundleIsAncestor {
|
||||
NSString *path = [NSBundle bundleForClass:[self class]].bundlePath;
|
||||
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
|
||||
sut.useAncestorBundle = YES;
|
||||
|
||||
XCTAssertNotNil([sut bundle]);
|
||||
|
||||
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.LogicTests");
|
||||
XCTAssertNotNil([sut bundleVersion]);
|
||||
XCTAssertNotNil([sut bundleShortVersionString]);
|
||||
XCTAssertEqualObjects([sut bundlePath], path);
|
||||
}
|
||||
|
||||
- (void)testBundleCacheReset {
|
||||
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"BundleExample"
|
||||
ofType:@"app"];
|
||||
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
|
||||
|
||||
XCTAssertNotNil([sut bundle]);
|
||||
|
||||
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.santa.BundleExample");
|
||||
XCTAssertEqualObjects([sut bundleName], @"BundleExample");
|
||||
XCTAssertEqualObjects([sut bundleVersion], @"1");
|
||||
XCTAssertEqualObjects([sut bundleShortVersionString], @"1.0");
|
||||
XCTAssertEqualObjects([sut bundlePath], path);
|
||||
|
||||
sut.useAncestorBundle = YES;
|
||||
|
||||
XCTAssertNotNil([sut bundle]);
|
||||
|
||||
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.LogicTests");
|
||||
XCTAssertNotNil([sut bundleVersion]);
|
||||
XCTAssertNotNil([sut bundleShortVersionString]);
|
||||
|
||||
NSString *ancestorBundlePath = path;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ancestorBundlePath = [ancestorBundlePath stringByDeletingLastPathComponent];
|
||||
}
|
||||
XCTAssertEqualObjects([sut bundlePath], ancestorBundlePath);
|
||||
}
|
||||
|
||||
- (void)testNonBundle {
|
||||
SNTFileInfo *sut =
|
||||
[[SNTFileInfo alloc] initWithPath:@"/usr/bin/yes"];
|
||||
|
||||
XCTAssertNil([sut bundle]);
|
||||
|
||||
sut.useAncestorBundle = YES;
|
||||
|
||||
XCTAssertNil([sut bundle]);
|
||||
}
|
||||
|
||||
- (void)testEmbeddedInfoPlist {
|
||||
|
||||
Reference in New Issue
Block a user