Compare commits

...

119 Commits
0.7 ... 0.8

Author SHA1 Message Date
Russell Hancox
3423026a43 santad: move scope check after bin/cert rule checks 2015-02-02 18:25:28 -05:00
Russell Hancox
e574621911 santactl/binaryinfo: Only show index in signing chain once 2015-02-02 18:17:46 -05:00
Russell Hancox
f1a3246eb9 santactl/sync: Minor style cleanup 2015-02-02 18:15:32 -05:00
Russell Hancox
eeda832fae santactl/sync: Factor out dictionary conversion 2015-02-02 18:12:07 -05:00
Russell Hancox
40af338af2 santad: Correctly log when file allowed due to scope 2015-02-02 17:35:45 -05:00
Russell Hancox
8a4b2a8480 SNTXPCConnection: add invalidate to header 2015-02-02 17:32:29 -05:00
Russell Hancox
912f3aa0e1 SantaGUI: kill daemon connection on user-switch, re-create on switch back. 2015-02-02 17:32:09 -05:00
Russell Hancox
e7cb5703f2 Tidy up event UI 2015-02-02 17:05:16 -05:00
Russell Hancox
6fb81471e0 Fix SNTEventTableTest 2015-02-02 17:04:56 -05:00
Russell Hancox
54ffbf40d6 Ensure kernel cache is flushed if rules are added which are not whitelisting 2015-02-02 17:04:37 -05:00
Russell Hancox
101c9d2b1f Event Table: rename a method, simplify event decoding, lowercase all table fields 2015-02-02 17:04:06 -05:00
Russell Hancox
ce9af3d019 santactl/sync: Simplify cert signing chain in event upload. 2015-02-02 17:02:55 -05:00
Russell Hancox
d11b137f9b santactl/sync: Don't attempt to apply rules until all have been downloaded 2015-02-02 17:02:08 -05:00
Russell Hancox
9d1117b0c7 SNTExecutionController: Change logging separator from comma to pipe. Also use logDecision when out of scope 2015-02-02 17:00:30 -05:00
Russell Hancox
ee9a7f635a Move from Certificate SHA-1 to SHA-256 2015-02-02 16:59:04 -05:00
Russell Hancox
63c6e4f852 santactl binaryinfo: Add Cert SHA-256 2015-02-02 13:21:34 -05:00
Russell Hancox
af63d036de Finish SNTExecutionControllerTest: testOutOfScope 2015-02-02 13:21:09 -05:00
Russell Hancox
b728ea3077 Rename SNTBinaryInfo -> SNTFileInfo, add more tests 2015-01-31 17:54:29 -05:00
Russell Hancox
a98bd00492 Unify path-standardizing into SNTBinaryInfo 2015-01-30 18:56:43 -05:00
Russell Hancox
6aeae5f1b6 santactl rule: print if rule is being deleted 2015-01-30 18:45:12 -05:00
Russell Hancox
7a03183cf0 Update Copyright years 2015-01-30 18:41:12 -05:00
Russell Hancox
6b743015a0 santactl rule: Correctly show rule SHA-256 2015-01-30 18:31:30 -05:00
Russell Hancox
b095625972 Remove SNTNotificationMessage, use SNTStoredEvent for that purpose instead. 2015-01-30 18:31:17 -05:00
Russell Hancox
98adf9c2c1 Update SNTRule and SNTStoredEvent encoding/decoding 2015-01-30 18:29:45 -05:00
Russell Hancox
c447eb959b More comment fixes 2015-01-30 17:28:32 -05:00
Russell Hancox
801d2b241a CommonEnums: Add ALLOW_SCOPE and BLOCK_SCOPE 2015-01-30 17:28:21 -05:00
Russell Hancox
42684387c5 Kernel: Rename RESPONSE_VALID macro to CHECKBW_RESPONSE_VALID 2015-01-30 17:28:04 -05:00
Russell Hancox
a66255aa8f Events: store event in archived form in database, store & upload entire signing chain rather than just leaf, rename eventsPendingCount, add unit tests. 2015-01-30 17:27:34 -05:00
Russell Hancox
30d335658c More missed SHA-1 references 2015-01-29 19:55:03 -05:00
Russell Hancox
20a7d6074f Missed a few SHA-1 references 2015-01-29 12:33:57 -05:00
Russell Hancox
f8273555a4 santactl: Binaryinfo detects bundles 2015-01-28 23:28:41 -05:00
Russell Hancox
a607136a0d Add logging of out-of-scope files 2015-01-28 23:20:16 -05:00
Russell Hancox
4b166f4485 Update Pods 2015-01-28 22:33:42 -05:00
Russell Hancox
f1f2913529 Update kernel tests for switch to userland hashing 2015-01-28 22:33:17 -05:00
Russell Hancox
1117b28d8d Change RuleDownload JSON to refer to shasum for rule instead of sha1 2015-01-28 22:20:55 -05:00
Russell Hancox
72811e5546 SNTXPCConnection: break loop when rejecting 2015-01-28 22:01:50 -05:00
Russell Hancox
3fefa7676f Add xctool support to Rakefile 2015-01-28 21:59:51 -05:00
Russell Hancox
75883af800 Fix some tests 2015-01-28 21:29:08 -05:00
Russell Hancox
22e5ffa1f1 SNTEventTable, rename from indexes to id 2015-01-28 21:28:59 -05:00
Russell Hancox
8b671ea2cd Remove DebugLogging config option, change to --debug flag instead. 2015-01-28 21:28:40 -05:00
Russell Hancox
ecbd92646d Update all docstrings to triple-slash doxygen style 2015-01-28 21:28:17 -05:00
Russell Hancox
b946598f7b Remove unused method from SNTEventTable 2015-01-28 19:13:00 -05:00
Russell Hancox
b30696b8a3 Fix alignment in SNTCommandSync.m 2015-01-28 19:13:00 -05:00
Russell Hancox
ae74a61a7e Add SHA-256 output to santactl binaryinfo command 2015-01-28 19:13:00 -05:00
Russell Hancox
2ae9229a6b Remove SHA-1 import in kernel 2015-01-28 19:12:59 -05:00
Russell Hancox
95a334dbaf Remove bundle icon from notification window 2015-01-28 19:12:59 -05:00
Russell Hancox
6335a02404 Move to SHA-256 hashing 2015-01-28 19:12:59 -05:00
Russell Hancox
5c9cceec35 common: Add SHA-256 to binaryinfo 2015-01-28 19:12:06 -05:00
Russell Hancox
71b08307a3 Driver: Move SHA-1 calculation to userland 2015-01-28 19:12:06 -05:00
Russell Hancox
180c8f2226 SNTCertificate: add SHA-256 hashing 2015-01-23 16:46:09 -05:00
Russell Hancox
2305ec578c More comment string updates 2015-01-23 16:45:54 -05:00
Russell Hancox
2f735dc716 Grr. Tabs. 2015-01-20 19:06:31 -05:00
Russell Hancox
afca026c12 SNTConfigurator: NSPropertyListSerialization argument should be NULL instead of nil 2015-01-20 19:05:32 -05:00
Russell Hancox
1447fd8789 SNTConfigurator: Make configFilePath configurable, try to enforce permissions on config file, use NSPropertyListSerialization instead of CFPropertyListCreateWithData 2015-01-20 18:59:45 -05:00
Russell Hancox
ccd871cfdd santactl: Simplify protocol and daemonConn handling 2015-01-20 18:58:40 -05:00
Russell Hancox
407466cd5f Update SNTXPCConnection's wait-during-resume and utilize it in SNTCommandController 2015-01-20 18:58:08 -05:00
Russell Hancox
ba9340d30d Some doxygen comment cleanups 2015-01-20 18:57:14 -05:00
Russell Hancox
a7715e3ce2 santad: Fix long-standing bug where santad won't finish shutting down when kext goes away 2015-01-14 18:37:46 -05:00
Russell Hancox
1a8cd79bf9 SNTXPCConnection: sleep for up to 5s during resume in clients to avoid sending messages during validation 2015-01-14 11:43:31 -05:00
Russell Hancox
a560c84cdc SNTBinaryInfo: Add downloadURLs method 2015-01-13 18:27:02 -05:00
Russell Hancox
4e0cfeb16d Driver: add missing debug log when process listener stops 2015-01-13 16:32:08 -05:00
Russell Hancox
195ba4d918 santactl status: don't block infinitely if daemonConn is nil 2015-01-13 16:16:03 -05:00
Russell Hancox
7458896a2a Driver: send down ppid to daemon 2015-01-13 16:08:29 -05:00
Russell Hancox
a78f2b37ee Driver: style and comment cleanup 2015-01-13 16:07:03 -05:00
Russell Hancox
d3c0d409ab Project: Remove references to unused imports 2015-01-13 16:05:09 -05:00
Russell Hancox
71833da8f4 Driver: Change back from using vn_rdwr to VNOP_READ 2015-01-13 16:01:45 -05:00
Russell Hancox
10892691e8 Merge pull request #12 from dutchcoders/add-remove-rules-using-cli
santactl: can add and remove rule(s) now
2015-01-12 18:56:20 -05:00
Russell Hancox
5139fe692c Project: Update deployment target to 10.9, santactl sync has never worked on 10.8 2015-01-09 16:46:58 -05:00
Russell Hancox
7cdfda187e Tests: Update to OCMock3 macro syntax 2015-01-09 16:36:43 -05:00
Russell Hancox
d4538b4f7c Project: simplify version numbering by basing the version number on the latest git tag number. Mark debug builds with git commit id. 2015-01-07 18:42:17 -05:00
Remco
c885dbdd4f moving exit within the block, because of race condition 2015-01-06 22:06:56 +01:00
Remco
1bfe8feeb1 customMsg wasn't set to parameter value 2015-01-06 22:06:18 +01:00
Remco
caaa7e60c3 disallow rule management when syncbaseurl is set 2015-01-06 22:05:51 +01:00
Remco
21bf445f46 fixed typo in help text 2015-01-06 22:05:36 +01:00
Russell Hancox
685641bb5d Merge branch 'master' of github.com:google/santa 2015-01-05 23:31:46 -05:00
Russell Hancox
53c00ef61e Move Style section, rename 2015-01-05 23:31:14 -05:00
Russell Hancox
8ec7f28f94 Update CONTRIBUTING, link to style guides 2015-01-05 23:29:52 -05:00
Russell Hancox
09d71f8790 Merge pull request #13 from russellhancox/master
Style cleanups and fix for santactl memory leak
2015-01-05 23:26:14 -05:00
Russell Hancox
e8f298aa38 santactl: Fix memory leaks in SNTAuthenticatingURLSession, inline extractIdentityAndTrust function 2015-01-05 23:19:24 -05:00
Russell Hancox
172a260cdc Style cleanups 2015-01-05 23:18:12 -05:00
Russell Hancox
d47770804e Merge branch 'master' of github.com:google/santa 2015-01-05 22:04:07 -05:00
Russell Hancox
b4b899cf37 Merge pull request #11 from dutchcoders/add-help-command
added help command to usage
2015-01-05 14:41:49 -05:00
Russell Hancox
df59825c57 Merge pull request #10 from dutchcoders/working-on-client-certificates
Work on client certificates
2015-01-05 14:40:50 -05:00
Remco
e959e42282 add help command to usage 2014-12-29 17:24:47 +01:00
Remco
86cd6aa133 enhancement(santactl): can add and remove rule(s) now. 2014-12-29 17:20:56 +01:00
Remco
de61869b01 corrected typo 2014-12-24 09:25:00 +01:00
Remco
c9a6b59a43 Print error when config couldn't be loaded and use empty configuration. 2014-12-24 09:21:03 +01:00
Remco
76ae6adced updated some styling issues 2014-12-24 09:19:03 +01:00
Remco
6b177933e2 fixed remarks 2014-12-23 20:51:00 +01:00
Remco
06c95e9121 fixed issue with ignored cert issuer cn and cert common name config 2014-12-22 15:41:22 +01:00
Remco
dbbdfb1965 added support for using custom pkcs#12 file with password 2014-12-22 15:37:25 +01:00
Remco
2d927175e0 Improved error logging. 2014-12-22 15:23:25 +01:00
Remco
642b69bde2 Removing hard coded disabling of client certificates. 2014-12-22 15:22:17 +01:00
Remco
16ca9b85ab exit when configuration file couldn't be opened
* when the configuration file couldn't be opened it failed silently and
used empty configuration. Now it prints an error and quits with
errorcode 1.
* LOGE not used because of circular reference
2014-12-22 12:31:23 +01:00
Remco
cbf16d140b return error when certificate file could not be loaded. 2014-12-21 15:20:43 +01:00
Russell Hancox
bf84a86450 Merge pull request #8 from dutchcoders/add-contenttype-header
added content-type application/json to json requests
2014-12-19 21:01:06 -05:00
Remco
1503f8658d added content-type application/json to json requests 2014-12-20 02:29:02 +01:00
Russell Hancox
c8bcf3ba2c Driver: Get ref to node before trying to read file 2014-12-19 12:41:30 -05:00
Russell Hancox
9d1c850b91 Driver: Use kernel page_size global 2014-12-19 12:40:53 -05:00
Russell Hancox
fe90353c75 Driver: invalidate cache on vnode delete 2014-12-19 12:39:28 -05:00
Russell Hancox
2d1941dcff Merge pull request #7 from dutchcoders/fix-rule-sync
santad: fix segfault while adding rules
2014-12-19 11:12:50 -05:00
Remco
546b2f1383 switched to @() boxing syntax instead of NSNumber literals 2014-12-19 17:10:49 +01:00
Remco
4509cd5c0b fixed segfault while adding rules 2014-12-19 12:45:35 +01:00
Russell Hancox
9a423f1b06 Proj: Add Travis-CI integration 2014-12-16 23:20:11 -05:00
Russell Hancox
292c51e8a5 Conf: remove log output for santagui 2014-12-16 17:11:27 -05:00
Russell Hancox
c2f04c50a5 santad: Add debug message when waiting for driver 2014-12-16 16:41:30 -05:00
Russell Hancox
65cb531ac8 Conf: Make claim only asl.conf work properly, maybe 2014-12-16 16:40:46 -05:00
Russell Hancox
373b49cee4 Proj: allow Mac Developer identity to sign kext 2014-12-16 16:40:34 -05:00
Russell Hancox
654aa7cf2d Driver: Add debug log when write is denied. 2014-12-16 16:40:34 -05:00
Russell Hancox
6174f80abd Driver: result of AddToCache is never used, so make it void. 2014-12-16 16:40:34 -05:00
Russell Hancox
7268de352f santad: Fix for XPC deadlock bug on Yosemite 2014-12-16 16:40:33 -05:00
Russell Hancox
f046711fb0 GUI: always do createConnection on main thread to avoid over resume 2014-12-16 16:40:24 -05:00
Russell Hancox
fac4e68adf Proj: Bump version to 0.7.1 2014-12-16 16:40:23 -05:00
Russell Hancox
8693fad2c9 santad: close stderr before starting singleevent sync 2014-12-16 16:40:06 -05:00
Russell Hancox
bca08ad359 Proj: Add Dist command to Rakefile 2014-12-16 16:40:05 -05:00
Russell Hancox
e32b4e2350 Proj: Add a few more entries to gitignore 2014-12-16 16:39:56 -05:00
Russell Hancox
97a5755c3d Proj: Update README to link to releases page 2014-12-16 16:39:29 -05:00
Russell Hancox
17f102662a Driver: Clean-up logic when checking cache entry actions 2014-12-16 16:39:17 -05:00
Russell Hancox
f47ce3d2bc Update kext signing section to clarify when applying for a kext-signing cert is suitable. Resolves #5 2014-12-12 12:09:51 -05:00
113 changed files with 2746 additions and 2125 deletions

3
.gitignore vendored
View File

@@ -1,5 +1,8 @@
.DS_Store
Build
Dist
Pods
Santa.xcodeproj/xcuserdata
Santa.xcodeproj/project.xcworkspace
Santa.xcworkspace/xcuserdata
Santa.xcworkspace/xcshareddata

10
.travis.yml Normal file
View File

@@ -0,0 +1,10 @@
---
language: objective-c
before_install:
- gem install cocoapods
- brew update
- brew upgrade xctool
script:
- xctool -workspace Santa.xcworkspace -scheme All build test CODE_SIGN_IDENTITY=''

View File

@@ -25,6 +25,12 @@ tests beforehand, which you can do with the following commands:
rake tests:logic
rake tests:kernel # only necessary if you're changing the kext code
```
### Code Style
All code submissions should try to match the surrounding code. Wherever possible,
code should adhere to either the
[Google Objective-C Style Guide](http://google-styleguide.googlecode.com/svn/trunk/objcguide.xml)
or the [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html).
### The small print
Contributions made by corporations are covered by a different agreement than

View File

@@ -1,2 +1,4 @@
# Copy this file to /etc/asl to log all messages from santa-driver to the log file
? [S= Message santa-driver:] file /var/log/santa.log claim only format="[$((Time)(utc.3))] $Message"
? [S= Message santa-driver:] claim only
? [S= Message santa-driver:] file /var/log/santa.log format="[$((Time)(utc.3))] $Message"
> /var/log/santa.log mode=0644 rotate=seq compress file_max=5M all_max=100M

View File

@@ -8,10 +8,6 @@
<array>
<string>/Applications/Santa.app/Contents/MacOS/Santa</string>
</array>
<key>StandardOutPath</key>
<string>/var/log/santa.log</string>
<key>StandardErrorPath</key>
<string>/var/log/santa.log</string>
<key>RunAtLoad</key>
<true/>
</dict>

View File

@@ -1,4 +1,4 @@
platform :osx, "10.8"
platform :osx, "10.9"
inhibit_all_warnings!

View File

@@ -1,17 +1,17 @@
PODS:
- FMDB (2.4):
- FMDB/standard (= 2.4)
- FMDB/common (2.4)
- FMDB/standard (2.4):
- FMDB (2.5):
- FMDB/standard (= 2.5)
- FMDB/common (2.5)
- FMDB/standard (2.5):
- FMDB/common
- OCMock (3.1.1)
- OCMock (3.1.2)
DEPENDENCIES:
- FMDB
- OCMock
SPEC CHECKSUMS:
FMDB: 0b2fa25e5264ef177973c0cb8c02c711107979aa
OCMock: f6cb8c162ab9d5620dddf411282c7b2c0ee78854
FMDB: 0efa188cf0dd1ce82c27a478cd5f5fa245308677
OCMock: ecdd510b73ef397f2f97274785c1e87fd147c49f
COCOAPODS: 0.35.0

View File

@@ -1,4 +1,4 @@
Santa
Santa [![Build Status](https://travis-ci.org/google/santa.png?branch=master)](https://travis-ci.org/google/santa)
=====
Santa is a binary whitelisting/blacklisting system for Mac OS X. It consists of
@@ -112,16 +112,22 @@ be shown when loading the kext for the first time. In 10.10 this is a hard error
and the kext will not load at all unless the machine is booted with a debug
boot-arg.
There are two possible solutions for this:
There are two possible solutions for this, for distribution purposes:
1) Use a pre-built, pre-signed version of the kext that we supply. Each time
changes are made to the kext code we will update the pre-built version that you
can make use of. This doesn't prevent you from making changes to the non-kext
parts of Santa and distributing those. If you make changes to the kext and make
a pull request, we can merge them in and distribute a new version of the
pre-signed kext.
1) Use a [pre-built, pre-signed version](https://github.com/google/santa/releases)
of the kext that we supply. Each time changes are made to the kext code we will
update the pre-built version that you can make use of. This doesn't prevent you
from making changes to the non-kext parts of Santa and distributing those.
If you make changes to the kext and make a pull request, we can merge them in
and distribute a new version of the pre-signed kext.
2) Apply for your own [kext signing certificate](https://developer.apple.com/contact/kext/).
Apple will only grant this for broad distribution within an organization, they
won't issue them just for testing purposes.
If you just want to locally test changes to the kext code, you should enable
kext-dev mode, instructions for which can be found on the Apple developer site.
Contributing
============

View File

@@ -2,17 +2,20 @@ require 'timeout'
WORKSPACE = 'Santa.xcworkspace'
DEFAULT_SCHEME = 'All'
OUTPUT_PATH = 'build'
PLISTS = ['Source/SantaGUI/Resources/Santa-Info.plist',
'Source/santad/Resources/santad-Info.plist',
'Source/santa-driver/Resources/santa-driver-Info.plist',
'Source/santactl/Resources/santactl-Info.plist']
OUTPUT_PATH = 'Build'
DIST_PATH = 'Dist'
BINARIES = ['Santa.app', 'santa-driver.kext', 'santad', 'santactl']
XCTOOL_DEFAULTS = "-workspace #{WORKSPACE} -scheme #{DEFAULT_SCHEME}"
XCODE_DEFAULTS = "-workspace #{WORKSPACE} -scheme #{DEFAULT_SCHEME} -derivedDataPath #{OUTPUT_PATH} -parallelizeTargets"
task :default do
system("rake -sT")
end
def xctool_available
return system 'xctool --version >/dev/null 2>&1'
end
def run_and_output_on_fail(cmd)
output=`#{cmd} 2>&1`
if not $?.success?
@@ -43,7 +46,7 @@ end
task :init do
unless File.exists?(WORKSPACE) and File.exists?('Pods')
puts "Workspace is missing, running 'pod install'"
puts "Pods missing, running 'pod install'"
system "pod install" or raise "CocoaPods is not installed. Install with 'sudo gem install cocoapods'"
end
end
@@ -58,8 +61,9 @@ end
desc "Clean"
task :clean => :init do
puts "Cleaning"
run_and_output_on_fail("xcodebuild #{XCODE_DEFAULTS} clean")
system "xcodebuild #{XCODE_DEFAULTS} clean"
FileUtils.rm_rf(OUTPUT_PATH)
FileUtils.rm_rf(DIST_PATH)
end
# Build
@@ -77,7 +81,11 @@ namespace :build do
task :build, [:configuration] => :init do |t, args|
config = args[:configuration]
puts "Building with configuration: #{config}"
run_and_output_on_fail("xcodebuild #{XCODE_DEFAULTS} -configuration #{config} build")
if xctool_available
system "xctool #{XCTOOL_DEFAULTS} -configuration #{config} build"
else
system "xcodebuild #{XCODE_DEFAULTS} -configuration #{config} build"
end
end
end
@@ -110,12 +118,38 @@ namespace :install do
end
end
# Dist
task :dist do
desc "Create distribution folder"
Rake::Task['build:build'].invoke("Release")
FileUtils.rm_rf(DIST_PATH)
FileUtils.mkdir_p("#{DIST_PATH}/binaries")
FileUtils.mkdir_p("#{DIST_PATH}/conf")
FileUtils.mkdir_p("#{DIST_PATH}/dsym")
BINARIES.each do |x|
FileUtils.cp_r("#{OUTPUT_PATH}/Products/Release/#{x}", "#{DIST_PATH}/binaries")
FileUtils.cp_r("#{OUTPUT_PATH}/Products/Release/#{x}.dSYM", "#{DIST_PATH}/dsym")
end
Dir.glob("Conf/*") {|x| FileUtils.cp(x, "#{DIST_PATH}/conf")}
puts "Distribution folder created"
end
# Tests
namespace :tests do
desc "Tests: Logic"
task :logic => [:init] do
puts "Running logic tests"
run_and_output_with_color("xcodebuild #{XCODE_DEFAULTS} test")
if xctool_available
system "xctool #{XCTOOL_DEFAULTS} test"
else
system "xcodebuild #{XCODE_DEFAULTS} test"
end
end
desc "Tests: Kernel"
@@ -188,23 +222,3 @@ namespace :reload do
Rake::Task['load'].invoke()
end
end
# Versioning
desc "Update version, version should be of the form rake version[\\d{1,4}.\\d{1,2}(?:.\\d{1,2})?]"
task :version, :version do |t, args|
response = args[:version]
unless response =~ /^\d{1,4}\.\d{1,2}(?:\.\d{1,2})?$/
raise "Version number must be of form: xxxx.xx[.xx]. E.g: rake version[1.0.2], rake version[1.7]"
end
system "sed -i -e 's/MODULE_VERSION = .*;/MODULE_VERSION = #{response};/g' Santa.xcodeproj/project.pbxproj"
PLISTS.each do |plist|
system "defaults write $PWD/#{plist} CFBundleVersion #{response}"
system "defaults write $PWD/#{plist} CFBundleShortVersionString #{response}"
system "plutil -convert xml1 $PWD/#{plist}"
end
puts "Updated version to #{response}"
end

View File

@@ -40,8 +40,7 @@
0D1AF478187C7A2C00D3298D /* SNTCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D1AF476187C7A2C00D3298D /* SNTCertificate.m */; };
0D1B477019A53419008CADD3 /* SNTAboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D1B476E19A53419008CADD3 /* SNTAboutWindowController.m */; };
0D1B477119A53419008CADD3 /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0D1B476F19A53419008CADD3 /* AboutWindow.xib */; };
0D260DAE18B68E12002A0B55 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D260DAD18B68E12002A0B55 /* XCTest.framework */; };
0D260DC118B69078002A0B55 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D260DC018B69078002A0B55 /* Security.framework */; };
0D20710E1A7C4A86008B0A9A /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
0D28D53819D9F5910015C5EB /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; };
0D31DF4718D254B3002B300D /* SNTCodesignChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D59C0E317710E6000748EBF /* SNTCodesignChecker.m */; };
0D35BD9F18FD71CE00921A21 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D9A7F3E1759330500035EB5 /* Foundation.framework */; };
@@ -71,13 +70,14 @@
0D3AFBF818FB4C870087BCEE /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D3AFBF718FB4C870087BCEE /* IOKit.framework */; };
0D416401191974F1006A356A /* SNTCommandSyncStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D416400191974F1006A356A /* SNTCommandSyncStatus.m */; };
0D41640519197AD7006A356A /* SNTCommandSyncEventUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D41640419197AD7006A356A /* SNTCommandSyncEventUpload.m */; };
0D41DAD41A7C28C800A890FE /* SNTEventTableTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D41DAD31A7C28C800A890FE /* SNTEventTableTest.m */; };
0D42D2B519D1D98A00955F08 /* SNTSystemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B419D1D98A00955F08 /* SNTSystemInfo.m */; };
0D42D2B819D2042900955F08 /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; };
0D42D2B919D2042900955F08 /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; };
0D4644C5182AF81700098690 /* SantaDecisionManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0D4644C3182AF81700098690 /* SantaDecisionManager.cc */; };
0D4644C6182AF81700098690 /* SantaDecisionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D4644C4182AF81700098690 /* SantaDecisionManager.h */; };
0D4A5007176A4602004F63BF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D4A5006176A4602004F63BF /* Security.framework */; };
0D54E0B11976F8D3000BB59F /* SNTBinaryInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTBinaryInfo.m */; };
0D54E0B11976F8D3000BB59F /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
0D59C0E417710E6000748EBF /* SNTCodesignChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D59C0E317710E6000748EBF /* SNTCodesignChecker.m */; };
0D63DD5C1906FCB400D346C4 /* SNTDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */; };
0D63DD5E1906FCB400D346C4 /* SNTDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D63DD5B1906FCB400D346C4 /* SNTDatabaseController.m */; };
@@ -88,7 +88,6 @@
0D6FDC8518C68E500044685C /* GIAG2.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0D6FDC8418C68E500044685C /* GIAG2.pem */; };
0D6FDC8718C6913D0044685C /* apple.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0D6FDC8618C6913D0044685C /* apple.pem */; };
0D6FDC8C18C69AF90044685C /* SNTCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D1AF476187C7A2C00D3298D /* SNTCertificate.m */; };
0D6FDC8F18C7F0200044685C /* SNTNotificationMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DBE65F018BEA3CC00AC994C /* SNTNotificationMessage.m */; };
0D6FDC9618C93A020044685C /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; };
0D6FDC9718C93A020044685C /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; };
0D7A7AF3174FCF4C00B77646 /* SantaMessage.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A7AF1174FCF4C00B77646 /* SantaMessage.cc */; };
@@ -109,15 +108,14 @@
0DA73CA11934F8100056D7C4 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; };
0DA73CA21934F88D0056D7C4 /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; };
0DB8ACC1185662DC00FEF9C7 /* SNTApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */; };
0DBE65F118BEA3CC00AC994C /* SNTNotificationMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DBE65F018BEA3CC00AC994C /* SNTNotificationMessage.m */; };
0DC5D86D191AED220078A5C0 /* SNTRuleTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */; };
0DC5D86E191AED220078A5C0 /* SNTRuleTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */; };
0DC5D871192160180078A5C0 /* SNTCommandSyncLogUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC5D870192160180078A5C0 /* SNTCommandSyncLogUpload.m */; };
0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FDC9518C93A020044685C /* SNTXPCConnection.m */; };
0DCD5FBF1909D64A006B445C /* SNTCommandBinaryInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD5FBE1909D64A006B445C /* SNTCommandBinaryInfo.m */; };
0DCD6042190ACCB8006B445C /* SNTBinaryInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTBinaryInfo.m */; };
0DCD6043190ACCB8006B445C /* SNTBinaryInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTBinaryInfo.m */; };
0DCD6044190ACCB8006B445C /* SNTBinaryInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTBinaryInfo.m */; };
0DCD6042190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
0DCD6043190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
0DCD6044190ACCB8006B445C /* SNTFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD6041190ACCB8006B445C /* SNTFileInfo.m */; };
0DCD604B19105433006B445C /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
0DCD604D19105433006B445C /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
0DCD604F19115A06006B445C /* SNTXPCNotifierInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604E19115A06006B445C /* SNTXPCNotifierInterface.m */; };
@@ -132,7 +130,7 @@
0DD0D487194F5187005F27EB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D3AFBF718FB4C870087BCEE /* IOKit.framework */; };
0DD0D48B194F6193005F27EB /* SNTCertificateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DD0D48A194F6193005F27EB /* SNTCertificateTest.m */; };
0DD0D48D194F6D5B005F27EB /* SNTCodesignCheckerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DD0D48C194F6D5B005F27EB /* SNTCodesignCheckerTest.m */; };
0DD0D48F194F78F8005F27EB /* SNTBinaryInfoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DD0D48E194F78F8005F27EB /* SNTBinaryInfoTest.m */; };
0DD0D48F194F78F8005F27EB /* SNTFileInfoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DD0D48E194F78F8005F27EB /* SNTFileInfoTest.m */; };
0DD0D491194F9947005F27EB /* SNTExecutionControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DD0D490194F9947005F27EB /* SNTExecutionControllerTest.m */; };
0DD0D492194F9BEF005F27EB /* SNTLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DA73C9E1934F8100056D7C4 /* SNTLogging.m */; };
0DD65D98184D2F0A00822DA7 /* SNTCodesignChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D59C0E317710E6000748EBF /* SNTCodesignChecker.m */; };
@@ -141,9 +139,9 @@
0DE50F681912716A007B2B0C /* SNTRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE50F671912716A007B2B0C /* SNTRule.m */; };
0DE50F691912B0CD007B2B0C /* SNTRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE50F671912716A007B2B0C /* SNTRule.m */; };
0DE50F6C19130358007B2B0C /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
0DE50F6D191303E3007B2B0C /* SNTNotificationMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DBE65F018BEA3CC00AC994C /* SNTNotificationMessage.m */; };
0DE50F6E191304E0007B2B0C /* SNTRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE50F671912716A007B2B0C /* SNTRule.m */; };
0DE6788D1784A8C2007A9E52 /* SNTExecutionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6788C1784A8C2007A9E52 /* SNTExecutionController.m */; };
4092327A1A51B66400A04527 /* SNTCommandRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 409232791A51B65D00A04527 /* SNTCommandRule.m */; };
8BFD9B39112F4D16B3D0EFFB /* libPods-LogicTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 752301D17AA44BDE8B6D0541 /* libPods-LogicTests.a */; };
E86AE075D7F24FB88FB627C5 /* libPods-santad.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A84545E322F475FA0B505D5 /* libPods-santad.a */; };
/* End PBXBuildFile section */
@@ -193,18 +191,6 @@
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
0D9A7F3B1759330400035EB5 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0A84545E322F475FA0B505D5 /* libPods-santad.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-santad.a"; sourceTree = BUILT_PRODUCTS_DIR; };
0D0016A2192BCD3C005E7FCD /* KernelTests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KernelTests; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -222,10 +208,8 @@
0D1B476E19A53419008CADD3 /* SNTAboutWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTAboutWindowController.m; sourceTree = "<group>"; };
0D1B476F19A53419008CADD3 /* AboutWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutWindow.xib; sourceTree = "<group>"; };
0D260DAC18B68E12002A0B55 /* LogicTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LogicTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
0D260DAD18B68E12002A0B55 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
0D260DB118B68E12002A0B55 /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = "<group>"; };
0D260DB718B68E12002A0B55 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = "<group>"; };
0D260DC018B69078002A0B55 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; };
0D28E5E119269B3600280F87 /* SNTLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTLogging.h; sourceTree = "<group>"; };
0D28E5E31926AFE400280F87 /* SNTKernelCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTKernelCommon.h; sourceTree = "<group>"; };
0D28E5E41926B55600280F87 /* santactl-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "santactl-Info.plist"; sourceTree = "<group>"; };
@@ -242,7 +226,7 @@
0D37C10E18F6029A0069BC61 /* SNTDatabaseTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTDatabaseTable.m; sourceTree = "<group>"; };
0D385DB6180DE4A900418BC6 /* Santa.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Santa.app; sourceTree = BUILT_PRODUCTS_DIR; };
0D385DB7180DE4A900418BC6 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
0D385DBF180DE4A900418BC6 /* Santa-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Santa-Info.plist"; sourceTree = "<group>"; };
0D385DBF180DE4A900418BC6 /* SantaGUI-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SantaGUI-Info.plist"; sourceTree = "<group>"; };
0D385DC3180DE4A900418BC6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
0D385DC5180DE4A900418BC6 /* Santa-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Santa-Prefix.pch"; sourceTree = "<group>"; };
0D385DCF180DE4A900418BC6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
@@ -259,6 +243,7 @@
0D416400191974F1006A356A /* SNTCommandSyncStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandSyncStatus.m; sourceTree = "<group>"; };
0D41640319197AD7006A356A /* SNTCommandSyncEventUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncEventUpload.h; sourceTree = "<group>"; };
0D41640419197AD7006A356A /* SNTCommandSyncEventUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandSyncEventUpload.m; sourceTree = "<group>"; };
0D41DAD31A7C28C800A890FE /* SNTEventTableTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTEventTableTest.m; sourceTree = "<group>"; };
0D42D2B319D1D98A00955F08 /* SNTSystemInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTSystemInfo.h; sourceTree = "<group>"; };
0D42D2B419D1D98A00955F08 /* SNTSystemInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTSystemInfo.m; sourceTree = "<group>"; };
0D42D2B619D2042900955F08 /* SNTConfigurator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTConfigurator.h; sourceTree = "<group>"; };
@@ -304,16 +289,14 @@
0DB8ACBF185662DC00FEF9C7 /* SNTApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTApplication.h; sourceTree = "<group>"; };
0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SNTApplication.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
0DB8ACE41858D73000FEF9C7 /* santad-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "santad-Info.plist"; sourceTree = "<group>"; };
0DBE65EF18BEA3CC00AC994C /* SNTNotificationMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTNotificationMessage.h; sourceTree = "<group>"; };
0DBE65F018BEA3CC00AC994C /* SNTNotificationMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTNotificationMessage.m; sourceTree = "<group>"; };
0DC5D86C191AED220078A5C0 /* SNTRuleTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTRuleTable.m; sourceTree = "<group>"; };
0DC5D86F192160180078A5C0 /* SNTCommandSyncLogUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommandSyncLogUpload.h; sourceTree = "<group>"; };
0DC5D870192160180078A5C0 /* SNTCommandSyncLogUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandSyncLogUpload.m; sourceTree = "<group>"; };
0DC8C9E3180CC3BC00FCFB29 /* SNTXPCNotifierInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTXPCNotifierInterface.h; sourceTree = "<group>"; };
0DCD5F771909C659006B445C /* SecurityInterface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityInterface.framework; path = System/Library/Frameworks/SecurityInterface.framework; sourceTree = SDKROOT; };
0DCD5FBE1909D64A006B445C /* SNTCommandBinaryInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandBinaryInfo.m; sourceTree = "<group>"; };
0DCD6040190ACCB8006B445C /* SNTBinaryInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTBinaryInfo.h; sourceTree = "<group>"; };
0DCD6041190ACCB8006B445C /* SNTBinaryInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTBinaryInfo.m; sourceTree = "<group>"; };
0DCD6040190ACCB8006B445C /* SNTFileInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTFileInfo.h; sourceTree = "<group>"; };
0DCD6041190ACCB8006B445C /* SNTFileInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTFileInfo.m; sourceTree = "<group>"; };
0DCD604919105433006B445C /* SNTStoredEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTStoredEvent.h; sourceTree = "<group>"; };
0DCD604A19105433006B445C /* SNTStoredEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTStoredEvent.m; sourceTree = "<group>"; };
0DCD604E19115A06006B445C /* SNTXPCNotifierInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTXPCNotifierInterface.m; sourceTree = "<group>"; };
@@ -325,7 +308,7 @@
0DCD6061191188B1006B445C /* SNTAuthenticatingURLSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTAuthenticatingURLSession.m; sourceTree = "<group>"; };
0DD0D48A194F6193005F27EB /* SNTCertificateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCertificateTest.m; sourceTree = "<group>"; };
0DD0D48C194F6D5B005F27EB /* SNTCodesignCheckerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCodesignCheckerTest.m; sourceTree = "<group>"; };
0DD0D48E194F78F8005F27EB /* SNTBinaryInfoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTBinaryInfoTest.m; sourceTree = "<group>"; };
0DD0D48E194F78F8005F27EB /* SNTFileInfoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTFileInfoTest.m; sourceTree = "<group>"; };
0DD0D490194F9947005F27EB /* SNTExecutionControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTExecutionControllerTest.m; sourceTree = "<group>"; };
0DE4C8A518FF3B1700466D04 /* SNTCommandFlushCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommandFlushCache.m; sourceTree = "<group>"; };
0DE50F6619127169007B2B0C /* SNTRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTRule.h; sourceTree = "<group>"; };
@@ -333,6 +316,7 @@
0DE6788B1784A8C2007A9E52 /* SNTExecutionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTExecutionController.h; sourceTree = "<group>"; };
0DE6788C1784A8C2007A9E52 /* SNTExecutionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SNTExecutionController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
13A4FE400F3857C0F5831498 /* Pods-LogicTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LogicTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LogicTests/Pods-LogicTests.debug.xcconfig"; sourceTree = "<group>"; };
409232791A51B65D00A04527 /* SNTCommandRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SNTCommandRule.m; path = rule/SNTCommandRule.m; sourceTree = "<group>"; };
627BB4EC9917DC20E89D718C /* Pods-santad.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santad.debug.xcconfig"; path = "Pods/Target Support Files/Pods-santad/Pods-santad.debug.xcconfig"; sourceTree = "<group>"; };
752301D17AA44BDE8B6D0541 /* libPods-LogicTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LogicTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
8003CA1D3E46447BCEA56440 /* 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>"; };
@@ -355,8 +339,6 @@
files = (
0D3AFBF618FB4C7E0087BCEE /* Cocoa.framework in Frameworks */,
0D3AFBF818FB4C870087BCEE /* IOKit.framework in Frameworks */,
0D260DC118B69078002A0B55 /* Security.framework in Frameworks */,
0D260DAE18B68E12002A0B55 /* XCTest.framework in Frameworks */,
8BFD9B39112F4D16B3D0EFFB /* libPods-LogicTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -407,11 +389,12 @@
isa = PBXGroup;
children = (
0D260DB018B68E12002A0B55 /* Resources */,
0DD0D48E194F78F8005F27EB /* SNTBinaryInfoTest.m */,
0DD0D48A194F6193005F27EB /* SNTCertificateTest.m */,
0DD0D48C194F6D5B005F27EB /* SNTCodesignCheckerTest.m */,
0D10BE8A1A0AB23300C0C944 /* SNTDERDecoderTest.m */,
0D41DAD31A7C28C800A890FE /* SNTEventTableTest.m */,
0DD0D490194F9947005F27EB /* SNTExecutionControllerTest.m */,
0DD0D48E194F78F8005F27EB /* SNTFileInfoTest.m */,
0D3AFBE618FB32CB0087BCEE /* SNTXPCConnectionTest.m */,
);
path = LogicTests;
@@ -422,10 +405,10 @@
children = (
0D6FDC8618C6913D0044685C /* apple.pem */,
0D6FDC8218C68D7E0044685C /* GIAG2.crt */,
0D6F12D919EDE411006B218E /* tubitak.crt */,
0D6FDC8418C68E500044685C /* GIAG2.pem */,
0D260DB118B68E12002A0B55 /* Tests-Info.plist */,
0D260DB718B68E12002A0B55 /* Tests-Prefix.pch */,
0D6FDC8418C68E500044685C /* GIAG2.pem */,
0D6F12D919EDE411006B218E /* tubitak.crt */,
);
path = Resources;
sourceTree = "<group>";
@@ -433,6 +416,7 @@
0D35BDA018FD71CE00921A21 /* santactl */ = {
isa = PBXGroup;
children = (
409232751A51914400A04527 /* rule */,
0D35BDA118FD71CE00921A21 /* main.m */,
0D35BDAA18FD7CFD00921A21 /* SNTCommandController.h */,
0D35BDAB18FD7CFD00921A21 /* SNTCommandController.m */,
@@ -449,8 +433,8 @@
0D35BDA318FD71CE00921A21 /* Resources */ = {
isa = PBXGroup;
children = (
0D35BDA418FD71CE00921A21 /* santactl-Prefix.pch */,
0D28E5E41926B55600280F87 /* santactl-Info.plist */,
0D35BDA418FD71CE00921A21 /* santactl-Prefix.pch */,
);
path = Resources;
sourceTree = "<group>";
@@ -503,7 +487,7 @@
isa = PBXGroup;
children = (
0D385DCF180DE4A900418BC6 /* Images.xcassets */,
0D385DBF180DE4A900418BC6 /* Santa-Info.plist */,
0D385DBF180DE4A900418BC6 /* SantaGUI-Info.plist */,
0D385DC5180DE4A900418BC6 /* Santa-Prefix.pch */,
0D1B476F19A53419008CADD3 /* AboutWindow.xib */,
0D385DE9180DE51600418BC6 /* MessageWindow.xib */,
@@ -570,13 +554,11 @@
children = (
0DCD5F771909C659006B445C /* SecurityInterface.framework */,
0D3AFBF718FB4C870087BCEE /* IOKit.framework */,
0D260DC018B69078002A0B55 /* Security.framework */,
0D8C200B180F359A00CE2BF8 /* Security.framework */,
0D4A5006176A4602004F63BF /* Security.framework */,
0D91BCB8174E8A7E00131A7D /* Kernel.framework */,
0D9A7F3E1759330500035EB5 /* Foundation.framework */,
0D385DB7180DE4A900418BC6 /* Cocoa.framework */,
0D260DAD18B68E12002A0B55 /* XCTest.framework */,
752301D17AA44BDE8B6D0541 /* libPods-LogicTests.a */,
0A84545E322F475FA0B505D5 /* libPods-santad.a */,
);
@@ -603,8 +585,6 @@
0D91BCD5174E8AAB00131A7D /* common */ = {
isa = PBXGroup;
children = (
0DCD6040190ACCB8006B445C /* SNTBinaryInfo.h */,
0DCD6041190ACCB8006B445C /* SNTBinaryInfo.m */,
0D1AF475187C7A2C00D3298D /* SNTCertificate.h */,
0D1AF476187C7A2C00D3298D /* SNTCertificate.m */,
0D59C0E217710E6000748EBF /* SNTCodesignChecker.h */,
@@ -614,11 +594,11 @@
0D42D2B719D2042900955F08 /* SNTConfigurator.m */,
0D10BE881A0AAC2100C0C944 /* SNTDropRootPrivs.h */,
0D10BE851A0AABD600C0C944 /* SNTDropRootPrivs.m */,
0DCD6040190ACCB8006B445C /* SNTFileInfo.h */,
0DCD6041190ACCB8006B445C /* SNTFileInfo.m */,
0D28E5E31926AFE400280F87 /* SNTKernelCommon.h */,
0D28E5E119269B3600280F87 /* SNTLogging.h */,
0DA73C9E1934F8100056D7C4 /* SNTLogging.m */,
0DBE65EF18BEA3CC00AC994C /* SNTNotificationMessage.h */,
0DBE65F018BEA3CC00AC994C /* SNTNotificationMessage.m */,
0DE50F6619127169007B2B0C /* SNTRule.h */,
0DE50F671912716A007B2B0C /* SNTRule.m */,
0DCD604919105433006B445C /* SNTStoredEvent.h */,
@@ -705,6 +685,14 @@
name = Pods;
sourceTree = "<group>";
};
409232751A51914400A04527 /* rule */ = {
isa = PBXGroup;
children = (
409232791A51B65D00A04527 /* SNTCommandRule.m */,
);
name = rule;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -762,6 +750,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 0D35BDA918FD71CE00921A21 /* Build configuration list for PBXNativeTarget "santactl" */;
buildPhases = (
0DD98E671A5DD02000A754C6 /* Update Version Info */,
0D35BD9A18FD71CE00921A21 /* Sources */,
0D35BD9B18FD71CE00921A21 /* Frameworks */,
);
@@ -778,6 +767,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 0D385DE3180DE4A900418BC6 /* Build configuration list for PBXNativeTarget "Santa" */;
buildPhases = (
0DD98E681A5DD03E00A754C6 /* Update Version Info */,
0D385DB2180DE4A900418BC6 /* Sources */,
0D385DB3180DE4A900418BC6 /* Frameworks */,
0D385DB4180DE4A900418BC6 /* Resources */,
@@ -795,6 +785,8 @@
isa = PBXNativeTarget;
buildConfigurationList = 0D91BCC3174E8A7E00131A7D /* Build configuration list for PBXNativeTarget "santa-driver" */;
buildPhases = (
0D45F4271A5DCB7A00BF4375 /* Update Version Info */,
0DD98E691A5DD5C900A754C6 /* Update Module Version */,
0D91BCAE174E8A7E00131A7D /* Sources */,
0D91BCB0174E8A7E00131A7D /* Headers */,
);
@@ -812,9 +804,9 @@
buildConfigurationList = 0D9A7F471759330500035EB5 /* Build configuration list for PBXNativeTarget "santad" */;
buildPhases = (
34C9C9E8C5454BBE980DF8A9 /* Check Pods Manifest.lock */,
0DD98E661A5DCED300A754C6 /* Update Version Info */,
0D9A7F391759330400035EB5 /* Sources */,
0D9A7F3A1759330400035EB5 /* Frameworks */,
0D9A7F3B1759330400035EB5 /* CopyFiles */,
3CDBFA3554E7465D93EAA5C8 /* Copy Pods Resources */,
);
buildRules = (
@@ -834,25 +826,9 @@
attributes = {
LastUpgradeCheck = 0510;
TargetAttributes = {
0D0016A1192BCD3C005E7FCD = {
DevelopmentTeam = 48U5E5R4XN;
};
0D260DAB18B68E12002A0B55 = {
DevelopmentTeam = 48U5E5R4XN;
TestTargetID = 0D385DB5180DE4A900418BC6;
};
0D35BD9D18FD71CE00921A21 = {
DevelopmentTeam = 48U5E5R4XN;
};
0D385DB5180DE4A900418BC6 = {
DevelopmentTeam = 48U5E5R4XN;
};
0D91BCB3174E8A7E00131A7D = {
DevelopmentTeam = 48U5E5R4XN;
};
0D9A7F3C1759330400035EB5 = {
DevelopmentTeam = 48U5E5R4XN;
};
};
};
buildConfigurationList = 0D91BCAB174E8A6500131A7D /* Build configuration list for PBXProject "Santa" */;
@@ -904,6 +880,22 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0D45F4271A5DCB7A00BF4375 /* Update Version Info */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/Source/santa-driver/Resources/santa-driver-Info.plist",
);
name = "Update Version Info";
outputPaths = (
"$(DERIVED_FILE_DIR)/santa-driver-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\n newVersion=\"${GIT_TAG}d${GIT_COMMIT}\"\nelse\n newVersion=\"${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}";
};
0D673DAD18FC9017009C5B06 /* Delete existing coverage files */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -919,6 +911,68 @@
shellScript = "# Delete existing gcda files to prevent the build log being filled with hundreds of lines\n# of \"profiling:invalid arc tag\".\n# TODO(rah): Remove when Xcode fixes this.\nfind . -name \"*.gcda\" -print0 | xargs -0 rm";
showEnvVarsInLog = 0;
};
0DD98E661A5DCED300A754C6 /* Update Version Info */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/Source/santad/Resources/santad-Info.plist",
);
name = "Update Version Info";
outputPaths = (
"$(DERIVED_FILE_DIR)/santad-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}";
};
0DD98E671A5DD02000A754C6 /* Update Version Info */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/Source/santactl/Resources/santactl-Info.plist",
);
name = "Update Version Info";
outputPaths = (
"$(DERIVED_FILE_DIR)/santactl-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}";
};
0DD98E681A5DD03E00A754C6 /* Update Version Info */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/Source/SantaGUI/Resources/SantaGUI-Info.plist",
);
name = "Update Version Info";
outputPaths = (
"$(DERIVED_FILE_DIR)/SantaGUI-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}";
};
0DD98E691A5DD5C900A754C6 /* Update Module Version */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Update Module Version";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
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";
};
34C9C9E8C5454BBE980DF8A9 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -995,9 +1049,8 @@
buildActionMask = 2147483647;
files = (
0D63DD5E1906FCB400D346C4 /* SNTDatabaseController.m in Sources */,
0D6FDC8F18C7F0200044685C /* SNTNotificationMessage.m in Sources */,
0D3AFBF018FB4C6C0087BCEE /* SNTDriverManager.m in Sources */,
0DCD6044190ACCB8006B445C /* SNTBinaryInfo.m in Sources */,
0DCD6044190ACCB8006B445C /* SNTFileInfo.m in Sources */,
0D6FDC9718C93A020044685C /* SNTXPCConnection.m in Sources */,
0D3AFBEB18FB48E70087BCEE /* SNTDatabaseTable.m in Sources */,
0DD0D491194F9947005F27EB /* SNTExecutionControllerTest.m in Sources */,
@@ -1011,8 +1064,9 @@
0D28D53819D9F5910015C5EB /* SNTConfigurator.m in Sources */,
0D3AFBE718FB32CB0087BCEE /* SNTXPCConnectionTest.m in Sources */,
0DCD605719115E54006B445C /* SNTDaemonControlController.m in Sources */,
0D41DAD41A7C28C800A890FE /* SNTEventTableTest.m in Sources */,
0D3AFBEE18FB4C6C0087BCEE /* SNTApplication.m in Sources */,
0DD0D48F194F78F8005F27EB /* SNTBinaryInfoTest.m in Sources */,
0DD0D48F194F78F8005F27EB /* SNTFileInfoTest.m in Sources */,
0DC5D86E191AED220078A5C0 /* SNTRuleTable.m in Sources */,
0D31DF4718D254B3002B300D /* SNTCodesignChecker.m in Sources */,
0DD0D492194F9BEF005F27EB /* SNTLogging.m in Sources */,
@@ -1041,10 +1095,11 @@
0D42D2B919D2042900955F08 /* SNTConfigurator.m in Sources */,
0D10BE871A0AABD600C0C944 /* SNTDropRootPrivs.m in Sources */,
0DE4C8A618FF3B1700466D04 /* SNTCommandFlushCache.m in Sources */,
4092327A1A51B66400A04527 /* SNTCommandRule.m in Sources */,
0D416401191974F1006A356A /* SNTCommandSyncStatus.m in Sources */,
0DC5D871192160180078A5C0 /* SNTCommandSyncLogUpload.m in Sources */,
0D35BDA218FD71CE00921A21 /* main.m in Sources */,
0DCD6043190ACCB8006B445C /* SNTBinaryInfo.m in Sources */,
0DCD6043190ACCB8006B445C /* SNTFileInfo.m in Sources */,
0DE50F6E191304E0007B2B0C /* SNTRule.m in Sources */,
0D0A1EC3191998C900B8450F /* SNTCommandSyncRuleDownload.m in Sources */,
0D35BDC018FDA5C800921A21 /* SNTCertificate.m in Sources */,
@@ -1060,7 +1115,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D54E0B11976F8D3000BB59F /* SNTBinaryInfo.m in Sources */,
0D54E0B11976F8D3000BB59F /* SNTFileInfo.m in Sources */,
0DCA552718C95928002A7DAE /* SNTXPCConnection.m in Sources */,
0D385DF1180DE51600418BC6 /* SNTAppDelegate.m in Sources */,
0DCD605119115A06006B445C /* SNTXPCNotifierInterface.m in Sources */,
@@ -1073,7 +1128,7 @@
0D1B477019A53419008CADD3 /* SNTAboutWindowController.m in Sources */,
0D668E8118D1121700E29A8B /* SNTMessageWindow.m in Sources */,
0DA73CA11934F8100056D7C4 /* SNTLogging.m in Sources */,
0DE50F6D191303E3007B2B0C /* SNTNotificationMessage.m in Sources */,
0D20710E1A7C4A86008B0A9A /* SNTStoredEvent.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1100,7 +1155,7 @@
0D9A7F421759330500035EB5 /* main.m in Sources */,
0D1AF477187C7A2C00D3298D /* SNTCertificate.m in Sources */,
0DA73C9F1934F8100056D7C4 /* SNTLogging.m in Sources */,
0DCD6042190ACCB8006B445C /* SNTBinaryInfo.m in Sources */,
0DCD6042190ACCB8006B445C /* SNTFileInfo.m in Sources */,
0DC5D86D191AED220078A5C0 /* SNTRuleTable.m in Sources */,
0D7D01871774F93A005DBAB4 /* SNTDriverManager.m in Sources */,
0D8E18CD19107B56000F89B8 /* SNTDaemonControlController.m in Sources */,
@@ -1108,7 +1163,6 @@
0D377C2A17A071B7008453DB /* SNTEventTable.m in Sources */,
0DE50F681912716A007B2B0C /* SNTRule.m in Sources */,
0D37C10F18F6029A0069BC61 /* SNTDatabaseTable.m in Sources */,
0DBE65F118BEA3CC00AC994C /* SNTNotificationMessage.m in Sources */,
0D59C0E417710E6000748EBF /* SNTCodesignChecker.m in Sources */,
0D42D2B819D2042900955F08 /* SNTConfigurator.m in Sources */,
0DCD605519115D17006B445C /* SNTXPCControlInterface.m in Sources */,
@@ -1340,7 +1394,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "Source/santactl/Resources/santactl-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santactl-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
};
@@ -1372,7 +1426,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "Source/santactl/Resources/santactl-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santactl-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
};
@@ -1411,7 +1465,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "Source/SantaGUI/Resources/Santa-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/SantaGUI-Info.plist";
PRODUCT_NAME = "${TARGET_NAME}";
PROVISIONING_PROFILE = "";
WRAPPER_EXTENSION = app;
@@ -1445,7 +1499,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "Source/SantaGUI/Resources/Santa-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/SantaGUI-Info.plist";
PRODUCT_NAME = "${TARGET_NAME}";
PROVISIONING_PROFILE = "";
WRAPPER_EXTENSION = app;
@@ -1459,7 +1513,7 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CODE_SIGN_IDENTITY = "Mac Developer";
MACOSX_DEPLOYMENT_TARGET = 10.8;
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;
PROVISIONING_PROFILE = "";
RUN_CLANG_STATIC_ANALYZER = YES;
@@ -1475,7 +1529,7 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CODE_SIGN_IDENTITY = "Mac Developer";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
MACOSX_DEPLOYMENT_TARGET = 10.8;
MACOSX_DEPLOYMENT_TARGET = 10.9;
PROVISIONING_PROFILE = "";
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = macosx;
@@ -1492,7 +1546,6 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
@@ -1505,10 +1558,10 @@
GCC_WARN_UNINITIALIZED_AUTOS = NO;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "";
INFOPLIST_FILE = "Source/santa-driver/Resources/santa-driver-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santa-driver-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
MODULE_NAME = "com.google.santa-driver";
MODULE_VERSION = 0.7;
MODULE_VERSION = TO.BE.FILLED;
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -1527,7 +1580,6 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -1537,10 +1589,10 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "";
INFOPLIST_FILE = "Source/santa-driver/Resources/santa-driver-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santa-driver-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
MODULE_NAME = "com.google.santa-driver";
MODULE_VERSION = 0.7;
MODULE_VERSION = TO.BE.FILLED;
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
WARNING_CFLAGS = "-Wno-deprecated-register";
@@ -1589,7 +1641,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "Source/santad/Resources/santad-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santad-Info.plist";
INSTALL_PATH = /usr/sbin;
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1616,7 +1668,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "Source/santad/Resources/santad-Info.plist";
INFOPLIST_FILE = "${DERIVED_FILE_DIR}/santad-Info.plist";
INSTALL_PATH = /usr/sbin;
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -42,6 +42,7 @@
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
debugAsWhichUser = "root"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SNTMessageWindowController">
@@ -14,18 +14,14 @@
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window 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="550" height="275"/>
<rect key="contentRect" x="167" y="107" width="550" height="331"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1577"/>
<view key="contentView" id="Iwq-Lx-rLv">
<rect key="frame" x="0.0" y="0.0" width="550" height="275"/>
<rect key="frame" x="0.0" y="0.0" width="550" height="331"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="t8c-Fx-e5h">
<rect key="frame" x="234" y="210" width="83" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="KoG-v6-GfK"/>
<constraint firstAttribute="width" constant="79" id="oS3-CE-1vv"/>
</constraints>
<rect key="frame" x="234" y="261" width="83" height="40"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Santa" id="7YA-iB-Zma">
<font key="font" size="34" name="HelveticaNeue-UltraLight"/>
<color key="textColor" red="0.18696189413265307" green="0.18696189413265307" blue="0.18696189413265307" alpha="1" colorSpace="calibratedRGB"/>
@@ -33,9 +29,9 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cD5-Su-lXR">
<rect key="frame" x="23" y="168" width="504" height="17"/>
<rect key="frame" x="25" y="214" width="500" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="500" id="q9O-xW-hnS"/>
<constraint firstAttribute="width" constant="496" id="XgJ-EV-tBa"/>
</constraints>
<textFieldCell key="cell" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="center" title="A message to the user goes here..." allowsEditingTextAttributes="YES" id="5tH-bG-UJA">
<font key="font" metaFont="system"/>
@@ -43,36 +39,13 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="self.attributedCustomMessage" id="NH1-gV-Cor">
<dictionary key="options">
<string key="NSNullPlaceholder">The following application has been blocked from executing because its trustworthiness cannot be determined.</string>
</dictionary>
</binding>
<binding destination="-2" name="value" keyPath="self.attributedCustomMessage" id="376-sj-4Q1"/>
</connections>
</textField>
<imageView horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="GYD-v8-fqH">
<rect key="frame" x="31" y="91" width="32" height="32"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSBonjour" id="jKM-qY-7mp"/>
<connections>
<binding destination="-2" name="value" keyPath="self.bundleIcon" id="X4L-aD-P21">
<dictionary key="options">
<bool key="NSConditionallySetsEnabled" value="NO"/>
</dictionary>
</binding>
</connections>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d9e-Wv-Y5H">
<rect key="frame" x="111" y="126" width="34" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Path" id="KgY-X1-ESG">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="pc8-G9-4pJ">
<rect key="frame" x="154" y="126" width="350" height="17"/>
<textField horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pc8-G9-4pJ">
<rect key="frame" x="175" y="167" width="324" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="346" id="BYY-2q-Lmb"/>
<constraint firstAttribute="width" constant="320" id="xVR-j3-dLw"/>
</constraints>
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Binary Path" id="E7T-9h-ofr">
<font key="font" metaFont="system"/>
@@ -80,41 +53,27 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="self.event.path" id="4Nh-Ue-aCb"/>
<binding destination="-2" name="value" keyPath="self.event.filePath" id="qfp-sR-Nmu"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KEB-eH-x2Y">
<rect key="frame" x="96" y="99" width="46" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="SHA-1" id="eKN-Ic-5zy">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PXc-xv-A28">
<rect key="frame" x="155" y="99" width="88" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Binary SHA-1" id="X4W-9e-eIu">
<textField horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PXc-xv-A28">
<rect key="frame" x="175" y="142" width="304" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="4hh-R2-86s"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="charWrapping" selectable="YES" sendsActionOnEndEditing="YES" title="File SHA-256" id="X4W-9e-eIu">
<font key="font" metaFont="system"/>
<color key="textColor" white="0.0" alpha="0.5" colorSpace="deviceWhite"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="self.event.SHA1" id="KuE-WW-9av"/>
<binding destination="-2" name="value" keyPath="self.event.fileSHA256" id="SzX-Ep-rBa"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" verticalCompressionResistancePriority="499" translatesAutoresizingMaskIntoConstraints="NO" id="lvJ-Rk-UT5">
<rect key="frame" x="78" y="72" width="66" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Publisher" id="yL9-yD-JXX">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button toolTip="Show code signing certificate chain" translatesAutoresizingMaskIntoConstraints="NO" id="cJf-k6-OxS">
<rect key="frame" x="322" y="75" width="10" height="10"/>
<button toolTip="Show code signing certificate chain" translatesAutoresizingMaskIntoConstraints="NO" id="cJf-k6-OxS" userLabel="Publisher Certs">
<rect key="frame" x="340" y="118" width="10" height="15"/>
<constraints>
<constraint firstAttribute="height" constant="10" id="c3b-iv-bWa"/>
<constraint firstAttribute="width" constant="10" id="fXl-na-Lwx"/>
<constraint firstAttribute="width" constant="10" id="QTm-Iv-m5p"/>
</constraints>
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="NSFollowLinkFreestandingTemplate" imagePosition="overlaps" alignment="center" refusesFirstResponder="YES" imageScaling="proportionallyDown" inset="2" id="R72-Qy-Xbb">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@@ -122,7 +81,7 @@
</buttonCell>
<connections>
<action selector="showCertInfo:" target="-2" id="dB0-a3-X31"/>
<binding destination="-2" name="hidden" keyPath="self.binaryCert" id="xpJ-jl-aUN">
<binding destination="-2" name="hidden" keyPath="self.publisherInfo" id="fFR-f3-Oiw">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
@@ -130,10 +89,10 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="BbV-3h-mmL">
<rect key="frame" x="220" y="23" width="110" height="25"/>
<rect key="frame" x="220" y="33" width="110" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="110" id="HdL-6x-X4f"/>
<constraint firstAttribute="height" constant="22" id="YYm-GI-ojT"/>
<constraint firstAttribute="width" constant="110" id="6Uh-Bd-N64"/>
<constraint firstAttribute="height" constant="22" id="GH6-nw-6rD"/>
</constraints>
<buttonCell key="cell" type="roundTextured" title="OK" bezelStyle="texturedRounded" alignment="center" refusesFirstResponder="YES" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="XR6-Xa-gP4">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@@ -147,56 +106,116 @@ DQ
<action selector="closeWindow:" target="-2" id="qQq-gh-8lw"/>
</connections>
</button>
<textField horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="C3G-wL-u7w">
<rect key="frame" x="154" y="72" width="159" height="17"/>
<constraints>
<constraint firstAttribute="height" constant="17" id="re0-7U-qcL"/>
</constraints>
<textField horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="C3G-wL-u7w">
<rect key="frame" x="175" y="117" width="159" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Code signing information" placeholderString="" id="ztA-La-XgT">
<font key="font" metaFont="system"/>
<color key="textColor" white="0.0" alpha="0.5" colorSpace="deviceWhite"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="self.binaryCert" id="eFt-oy-SXL">
<binding destination="-2" name="value" keyPath="self.publisherInfo" id="CEI-Cu-7pC">
<dictionary key="options">
<string key="NSNullPlaceholder">Not code-signed</string>
</dictionary>
</binding>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="oFj-ol-xpL">
<rect key="frame" x="18" y="92" width="120" 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"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lvJ-Rk-UT5">
<rect key="frame" x="18" y="117" width="120" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Publisher" id="yL9-yD-JXX">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d9e-Wv-Y5H">
<rect key="frame" x="18" y="167" width="120" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="116" id="Kqd-nX-7df"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Path" id="KgY-X1-ESG">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KEB-eH-x2Y">
<rect key="frame" x="18" y="142" width="120" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="SHA-256" id="eKN-Ic-5zy">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="h6f-PY-cc0">
<rect key="frame" x="175" y="92" width="368" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="364" id="on6-pj-m2k"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Executing User" id="HRT-Be-ePf">
<font key="font" metaFont="system"/>
<color key="textColor" white="0.0" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="self.event.executingUser" id="xe2-U2-WrZ"/>
</connections>
</textField>
<box horizontalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="4Li-ul-zIi">
<rect key="frame" x="154" y="92" width="5" height="92"/>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<font key="titleFont" metaFont="system"/>
</box>
</subviews>
<constraints>
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="113" id="3oY-g4-wHW"/>
<constraint firstItem="BbV-3h-mmL" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="bottom" priority="800" constant="52" id="42Z-62-hKo"/>
<constraint firstItem="cD5-Su-lXR" firstAttribute="top" secondItem="t8c-Fx-e5h" secondAttribute="bottom" constant="25" id="4Hn-vu-fva"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="bottom" constant="10" id="7Pr-bA-HgG"/>
<constraint firstItem="PXc-xv-A28" firstAttribute="top" secondItem="pc8-G9-4pJ" secondAttribute="bottom" constant="10" id="8LX-e8-bKv"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="top" secondItem="d9e-Wv-Y5H" secondAttribute="top" id="94E-d6-Jrg"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="leading" secondItem="d9e-Wv-Y5H" secondAttribute="trailing" constant="13" id="A6N-gA-dt5"/>
<constraint firstItem="KEB-eH-x2Y" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="98" id="CYj-Gm-XZp"/>
<constraint firstItem="PXc-xv-A28" firstAttribute="leading" secondItem="KEB-eH-x2Y" secondAttribute="trailing" constant="17" id="IGi-bx-nBP"/>
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="80" id="O3p-RO-0ZJ"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="centerY" secondItem="cJf-k6-OxS" secondAttribute="centerY" constant="-1" id="R0U-iV-5Fx"/>
<constraint firstAttribute="centerX" secondItem="t8c-Fx-e5h" secondAttribute="centerX" id="SHu-BF-01V"/>
<constraint firstAttribute="centerX" secondItem="BbV-3h-mmL" secondAttribute="centerX" id="UAx-Xk-9DE"/>
<constraint firstItem="KEB-eH-x2Y" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="top" id="YiW-o8-HZ2"/>
<constraint firstItem="BbV-3h-mmL" firstAttribute="top" secondItem="C3G-wL-u7w" secondAttribute="bottom" constant="25" id="Zxm-Pa-Ryj"/>
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="top" secondItem="C3G-wL-u7w" secondAttribute="top" id="adm-oT-FAf"/>
<constraint firstAttribute="bottom" secondItem="BbV-3h-mmL" secondAttribute="bottom" constant="25" id="awW-Dh-Xl4"/>
<constraint firstItem="GYD-v8-fqH" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="31" id="btT-jY-NXw"/>
<constraint firstItem="GYD-v8-fqH" firstAttribute="centerY" secondItem="KEB-eH-x2Y" secondAttribute="centerY" id="cOS-EE-Mw8"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="leading" secondItem="lvJ-Rk-UT5" secondAttribute="trailing" constant="14" id="ewf-Pg-nRK"/>
<constraint firstAttribute="centerX" secondItem="cD5-Su-lXR" secondAttribute="centerX" id="goV-ub-zwi"/>
<constraint firstItem="t8c-Fx-e5h" firstAttribute="top" secondItem="Iwq-Lx-rLv" secondAttribute="top" constant="25" id="mY6-FP-uEK"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="top" secondItem="cD5-Su-lXR" secondAttribute="bottom" constant="25" id="pfg-1u-Yfj"/>
<constraint firstItem="cJf-k6-OxS" firstAttribute="leading" secondItem="C3G-wL-u7w" secondAttribute="trailing" constant="11" id="sMW-KK-A28"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="bottom" secondItem="4Li-ul-zIi" secondAttribute="bottom" id="1Nc-gl-xMe"/>
<constraint firstItem="BbV-3h-mmL" firstAttribute="top" secondItem="oFj-ol-xpL" secondAttribute="bottom" constant="35" id="7K6-bY-Rn6"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="ALv-0v-szi"/>
<constraint firstItem="cJf-k6-OxS" firstAttribute="centerY" secondItem="C3G-wL-u7w" secondAttribute="centerY" id="FdL-ZZ-Vbe"/>
<constraint firstItem="t8c-Fx-e5h" firstAttribute="top" secondItem="Iwq-Lx-rLv" secondAttribute="top" constant="30" id="FuB-GX-0jg"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="centerY" secondItem="oFj-ol-xpL" secondAttribute="centerY" id="GXI-pT-FM1"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="20" id="IwX-ja-ZIs"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="centerY" secondItem="d9e-Wv-Y5H" secondAttribute="centerY" id="JeD-9X-ULA"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="d9e-Wv-Y5H" secondAttribute="leading" priority="999" id="MVr-jY-GDj"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="top" secondItem="cD5-Su-lXR" secondAttribute="bottom" constant="30" id="Nsl-zf-poH"/>
<constraint firstItem="pc8-G9-4pJ" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="SCl-Ky-VmT"/>
<constraint firstAttribute="centerX" secondItem="cD5-Su-lXR" secondAttribute="centerX" id="V0a-Py-iEc"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="lvJ-Rk-UT5" secondAttribute="leading" priority="999" id="Z6G-l9-G4a"/>
<constraint firstAttribute="centerX" secondItem="BbV-3h-mmL" secondAttribute="centerX" id="acs-5J-vQY"/>
<constraint firstItem="KEB-eH-x2Y" firstAttribute="leading" secondItem="oFj-ol-xpL" secondAttribute="leading" priority="999" id="b5A-M7-ZsD"/>
<constraint firstItem="KEB-eH-x2Y" firstAttribute="centerY" secondItem="PXc-xv-A28" secondAttribute="centerY" id="cHe-pZ-0Oq"/>
<constraint firstItem="cD5-Su-lXR" firstAttribute="top" secondItem="t8c-Fx-e5h" secondAttribute="bottom" constant="30" id="dYg-zP-wh2"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="eSz-lz-Fdh"/>
<constraint firstItem="4Li-ul-zIi" firstAttribute="top" secondItem="pc8-G9-4pJ" secondAttribute="top" id="fzY-94-y2n"/>
<constraint firstAttribute="centerX" secondItem="t8c-Fx-e5h" secondAttribute="centerX" constant="-0.5" id="h3d-Kc-q88"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="centerY" secondItem="lvJ-Rk-UT5" secondAttribute="centerY" id="jfs-YI-7Ae"/>
<constraint firstItem="lvJ-Rk-UT5" firstAttribute="trailing" secondItem="KEB-eH-x2Y" secondAttribute="trailing" id="jlD-Lo-abc"/>
<constraint firstItem="oFj-ol-xpL" firstAttribute="trailing" secondItem="lvJ-Rk-UT5" secondAttribute="trailing" id="lse-kg-lA2"/>
<constraint firstItem="d9e-Wv-Y5H" firstAttribute="trailing" secondItem="KEB-eH-x2Y" secondAttribute="trailing" id="pdq-a6-Y73"/>
<constraint firstItem="4Li-ul-zIi" firstAttribute="leading" secondItem="lvJ-Rk-UT5" secondAttribute="trailing" constant="20" id="qKi-KT-jzJ"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="top" secondItem="C3G-wL-u7w" secondAttribute="bottom" constant="8" id="rwU-fp-qh6"/>
<constraint firstItem="h6f-PY-cc0" firstAttribute="top" secondItem="C3G-wL-u7w" secondAttribute="bottom" constant="8" id="sG1-gQ-Qoo"/>
<constraint firstItem="C3G-wL-u7w" firstAttribute="top" secondItem="PXc-xv-A28" secondAttribute="bottom" constant="8" id="snd-8T-LjC"/>
<constraint firstItem="PXc-xv-A28" firstAttribute="leading" secondItem="4Li-ul-zIi" secondAttribute="trailing" constant="20" id="tAa-1s-xVZ"/>
<constraint firstAttribute="bottom" secondItem="BbV-3h-mmL" secondAttribute="bottom" constant="35" id="ukF-FH-DE8"/>
<constraint firstItem="cJf-k6-OxS" firstAttribute="leading" secondItem="C3G-wL-u7w" secondAttribute="trailing" constant="8" id="wsf-ru-MoA"/>
<constraint firstItem="PXc-xv-A28" firstAttribute="top" secondItem="pc8-G9-4pJ" secondAttribute="bottom" constant="8" id="zst-nc-VqA"/>
</constraints>
</view>
<point key="canvasLocation" x="162" y="710.5"/>
</window>
</objects>
<resources>
<image name="NSBonjour" width="32" height="32"/>
<image name="NSFollowLinkFreestandingTemplate" width="14" height="14"/>
</resources>
</document>

View File

@@ -2,30 +2,26 @@
<!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>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.google.${PRODUCT_NAME:rfc1034identifier}GUI</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.7</string>
<key>NSHumanReadableCopyright</key>
<string>Google, Inc.</string>
<key>CFBundleIdentifier</key>
<string>com.google.${PRODUCT_NAME:rfc1034identifier}GUI</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleVersion</key>
<string>0.7</string>
<string>TO.BE.FILLED</string>
<key>CFBundleShortVersionString</key>
<string>TO.BE.FILLED</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>LSUIElement</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Google, Inc.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Initiates and manages the connection to santad
///
@interface SNTAppDelegate : NSObject<NSApplicationDelegate>
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -32,6 +32,17 @@
[self setupMenu];
self.aboutWindowController = [[SNTAboutWindowController alloc] init];
self.notificationManager = [[SNTNotificationManager alloc] init];
NSNotificationCenter *workspaceNotifications = [[NSWorkspace sharedWorkspace] notificationCenter];
[workspaceNotifications addObserver:self
selector:@selector(killConnection)
name:NSWorkspaceSessionDidResignActiveNotification
object:nil];
[workspaceNotifications addObserver:self
selector:@selector(createConnection)
name:NSWorkspaceSessionDidBecomeActiveNotification
object:nil];
[self createConnection];
}
@@ -58,10 +69,19 @@
[self.listener resume];
}
- (void)killConnection {
self.listener.invalidationHandler = nil;
[self.listener invalidate];
self.listener = nil;
NSLog(@"KILLING CONNECTION");
}
- (void)attemptReconnection {
// TODO(rah): Make this smarter.
sleep(10);
[self createConnection];
[self performSelectorOnMainThread:@selector(createConnection)
withObject:nil
waitUntilDone:NO];
}
#pragma mark Menu Management

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,13 +12,19 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// An NSPanel that can become key/main and can fade in/out.
///
/// An NSPanel that can become key/main and can fade in/out.
///
@interface SNTMessageWindow : NSPanel
/// Fade the window in
///
/// Fade the window in
///
- (IBAction)fadeIn:(id)sender;
/// Fade the window out
///
/// Fade the window out
///
- (IBAction)fadeOut:(id)sender;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,34 +12,46 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@class SNTNotificationMessage;
@class SNTStoredEvent;
@protocol SNTMessageWindowControllerDelegate
- (void)windowDidClose;
@end
/// Controller for a single message window.
///
/// Controller for a single message window.
///
@interface SNTMessageWindowController : NSWindowController
- (instancetype)initWithEvent:(SNTNotificationMessage *)event;
- (instancetype)initWithEvent:(SNTStoredEvent *)event andMessage:(NSString *)message;
- (IBAction)showWindow:(id)sender;
- (IBAction)closeWindow:(id)sender;
- (IBAction)showCertInfo:(id)sender;
/// The execution event that this window is for
@property SNTNotificationMessage *event;
///
/// The execution event that this window is for
///
@property SNTStoredEvent *event;
/// The delegate to inform when the notification is dismissed
///
/// The custom message to display for this event
///
@property NSString *customMessage;
///
/// The delegate to inform when the notification is dismissed
///
@property(weak) id<SNTMessageWindowControllerDelegate> delegate;
/// A 'friendly' string representing the certificate information
@property(readonly) IBOutlet NSString *binaryCert;
///
/// A 'friendly' string representing the certificate information
///
@property(readonly) IBOutlet NSString *publisherInfo;
/// An optional message to display with this block.
///
/// An optional message to display with this block.
///
@property(readonly) IBOutlet NSAttributedString *attributedCustomMessage;
/// If the binary is part of a bundle, this is the icon for that bundle
@property(readonly) IBOutlet NSImage *bundleIcon;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,17 +16,18 @@
#import <SecurityInterface/SFCertificatePanel.h>
#import "SNTBinaryInfo.h"
#import "SNTCertificate.h"
#import "SNTFileInfo.h"
#import "SNTMessageWindow.h"
#import "SNTNotificationMessage.h"
#import "SNTStoredEvent.h"
@implementation SNTMessageWindowController
- (instancetype)initWithEvent:(SNTNotificationMessage *)event {
- (instancetype)initWithEvent:(SNTStoredEvent *)event andMessage:(NSString *)message {
self = [super initWithWindowNibName:@"MessageWindow"];
if (self) {
_event = event;
_customMessage = message;
[self.window setMovableByWindowBackground:NO];
[self.window setLevel:NSPopUpMenuWindowLevel];
[self.window center];
@@ -48,8 +49,8 @@
- (IBAction)showCertInfo:(id)sender {
// SFCertificatePanel expects an NSArray of SecCertificateRef's
NSMutableArray *certArray = [NSMutableArray arrayWithCapacity:[self.event.certificates count]];
for (SNTCertificate *cert in self.event.certificates) {
NSMutableArray *certArray = [NSMutableArray arrayWithCapacity:[self.event.signingChain count]];
for (SNTCertificate *cert in self.event.signingChain) {
[certArray addObject:(id)cert.certRef];
}
@@ -71,11 +72,11 @@
}
}
- (NSString *)binaryCert {
SNTCertificate *leafCert = self.event.leafCertificate;
- (NSString *)publisherInfo {
SNTCertificate *leafCert = [self.event.signingChain firstObject];
if (leafCert.commonName && leafCert.orgName) {
return [NSString stringWithFormat:@"%@ - %@", leafCert.commonName, leafCert.orgName];
return [NSString stringWithFormat:@"%@ - %@", leafCert.orgName, leafCert.commonName];
} else if (leafCert.commonName) {
return leafCert.commonName;
} else if (leafCert.orgName) {
@@ -86,33 +87,31 @@
}
- (NSAttributedString *)attributedCustomMessage {
if (self.event.customMessage) {
NSString *htmlHeader = @"<html><head><style>"
@"body {"
@" font-family: 'Lucida Grande', 'Helvetica', sans-serif;"
@" font-size: 13px;"
@" color: #666;"
@" text-align: center;"
@"}"
@"</style></head><body>";
NSString *htmlFooter = @"</body></html>";
NSString *fullHtml = [NSString stringWithFormat:@"%@%@%@", htmlHeader,
self.event.customMessage, htmlFooter];
NSData *htmlData = [fullHtml dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *returnStr = [[NSAttributedString alloc] initWithHTML:htmlData
documentAttributes:NULL];
return returnStr;
NSString *htmlHeader = @"<html><head><style>"
@"body {"
@" font-family: 'Lucida Grande', 'Helvetica', sans-serif;"
@" font-size: 13px;"
@" color: #AAA;"
@" text-align: center;"
@"}"
@"</style></head><body>";
NSString *htmlFooter = @"</body></html>";
NSString *message;
if (self.customMessage && ![self.customMessage isEqual:@""]) {
message = self.customMessage;
} else {
return nil;
message = @"The following application has been blocked from executing<br />"
@"because its trustworthiness cannot be determined.";
}
}
- (NSImage *)bundleIcon {
SNTBinaryInfo *bi = [[SNTBinaryInfo alloc] initWithPath:self.event.path];
NSString *fullHTML = [NSString stringWithFormat:@"%@%@%@", htmlHeader, message, htmlFooter];
if (!bi || !bi.bundle) return nil;
NSData *htmlData = [fullHTML dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *returnStr = [[NSAttributedString alloc] initWithHTML:htmlData
documentAttributes:NULL];
return returnStr;
return [[NSWorkspace sharedWorkspace] iconForFile:bi.bundlePath];
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -15,7 +15,9 @@
#import "SNTMessageWindowController.h"
#import "SNTXPCNotifierInterface.h"
/// Keeps track of pending notifications and ensures only one is presented to the user at a time.
///
/// Keeps track of pending notifications and ensures only one is presented to the user at a time.
///
@interface SNTNotificationManager : NSObject<SNTMessageWindowControllerDelegate, SNTNotifierXPC>

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,13 +14,17 @@
#import "SNTNotificationManager.h"
#import "SNTNotificationMessage.h"
#import "SNTStoredEvent.h"
@interface SNTNotificationManager ()
/// The currently displayed notification
///
/// The currently displayed notification
///
@property SNTMessageWindowController *currentWindowController;
/// The queue of pending notifications
///
/// The queue of pending notifications
///
@property(readonly) NSMutableArray *pendingNotifications;
@end
@@ -48,21 +52,25 @@
#pragma mark SNTNotifierXPC protocol methods
- (void)postBlockNotification:(SNTNotificationMessage *)event {
- (void)postBlockNotification:(SNTStoredEvent *)event withCustomMessage:(NSString *)message {
// See if this binary is already in the list of pending notifications.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"event.SHA1==%@", event.SHA1];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"fileSHA256==%@", event.fileSHA256];
if ([[self.pendingNotifications filteredArrayUsingPredicate:predicate] count]) return;
// Notifications arrive on a background thread but UI updates must happen on the main thread.
// This includes making windows.
[self performSelectorOnMainThread:@selector(postBlockNotificationMainThread:)
withObject:event
withObject:@{ @"event": event, @"custommsg": message }
waitUntilDone:NO];
}
- (void)postBlockNotificationMainThread:(SNTNotificationMessage *)event {
- (void)postBlockNotificationMainThread:(NSDictionary *)dict {
SNTStoredEvent *event = dict[@"event"];
NSString *msg = dict[@"custommsg"];
// Create message window
SNTMessageWindowController *pendingMsg = [[SNTMessageWindowController alloc] initWithEvent:event];
SNTMessageWindowController *pendingMsg = [[SNTMessageWindowController alloc] initWithEvent:event
andMessage:msg];
pendingMsg.delegate = self;
[self.pendingNotifications addObject:pendingMsg];

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,73 +0,0 @@
/// Copyright 2014 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.
/// SNTBinaryInfo represents a binary on disk, providing access to details about that binary such as
/// the SHA-1, the Info.plist and the Mach-O data.
@interface SNTBinaryInfo : NSObject
/// Designated initializer
- (instancetype)initWithPath:(NSString *)path;
/// Return SHA-1 hash of this binary
- (NSString *)SHA1;
/// Returns the type of Mach-O file:
/// Dynamic Library, Kernel Extension, Fat Binary, Thin Binary
- (NSString *)machoType;
/// Returns the architectures included in this binary (e.g. x86_64, ppc)
- (NSArray *)architectures;
/// Returns YES if this file is a Mach-O file
- (BOOL)isMachO;
/// Returns YES if this file contains multiple architectures
- (BOOL)isFat;
/// Returns YES if this file is an executable Mach-O file
- (BOOL)isExecutable;
/// Returns YES if this file is a dynamic library
- (BOOL)isDylib;
/// Returns YES if this file is a kernel extension
- (BOOL)isKext;
/// Returns YES if this file is a script (e.g. it begins #!)
- (BOOL)isScript;
/// Returns an NSBundle if this file is part of a bundle.
- (NSBundle *)bundle;
/// Returns the path to the bundle this file is a part of, if any.
- (NSString *)bundlePath;
/// Returns either the Info.plist in the bundle this file is part of, or an embedded plist if there
/// is one. In the odd case that a file has both an embedded Info.plist and is part of a bundle,
/// the Info.plist from the bundle will be returned.
- (NSDictionary *)infoPlist;
/// Returns the CFBundleIdentifier from this file's Info.plist
- (NSString *)bundleIdentifier;
/// Returns the CFBundleName from this file's Info.plist
- (NSString *)bundleName;
/// Returns the CFBundleVersion from this file's Info.plist
- (NSString *)bundleVersion;
/// Returns the CFBundleShortVersionString from this file's Info.plist
- (NSString *)bundleShortVersionString;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,56 +12,100 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// SNTCertificate wraps a @c SecCertificateRef to provide Objective-C accessors to
/// commonly used certificate data. Accessors cache data for repeated access.
///
/// SNTCertificate wraps a @c SecCertificateRef to provide Objective-C accessors to
/// commonly used certificate data. Accessors cache data for repeated access.
///
@interface SNTCertificate : NSObject<NSSecureCoding>
/// Initialize a SNTCertificate object with a valid SecCertificateRef. Designated initializer.
///
/// Initialize a SNTCertificate object with a valid SecCertificateRef. Designated initializer.
///
/// @param certRef valid SecCertificateRef, which will be retained.
///
- (instancetype)initWithSecCertificateRef:(SecCertificateRef)certRef;
/// Initialize a SNTCertificate object with certificate data in DER format.
/// Returns nil if |certData| is invalid.
///
/// Initialize a SNTCertificate object with certificate data in DER format.
///
/// @param certData DER-encoded certificate data.
/// @return initialized SNTCertificate or nil if certData is not a DER-encoded certificate.
///
- (instancetype)initWithCertificateDataDER:(NSData *)certData;
/// Initialize a SNTCertificate object with certificate data in PEM format.
/// If multiple PEM certificates exist within the string, the first is used.
/// Returns nil if |certData| is invalid.
///
/// Initialize a SNTCertificate object with certificate data in PEM format.
/// If multiple PEM certificates exist within the string, the first is used.
///
/// @param certData PEM-encoded certificate data.
/// @return initialized SNTCertifcate or nil if certData is not a PEM-encoded certificate.
///
- (instancetype)initWithCertificateDataPEM:(NSString *)certData;
/// Returns an array of SNTCertificate's for all of the certificates in |pemData|.
///
/// Returns an array of SNTCertificate's for all of the certificates in @c pemData.
///
/// @param pemData PEM-encoded certificates.
/// @return array of SNTCertificate objects.
///
+ (NSArray *)certificatesFromPEM:(NSString *)pemData;
/// Access the underlying certificate ref.
///
/// Access the underlying certificate ref.
///
@property(readonly) SecCertificateRef certRef;
/// SHA-1 hash of the certificate data.
///
/// SHA-1 hash of the certificate data.
///
@property(readonly) NSString *SHA1;
/// Certificate data.
///
/// SHA-256 hash of the certificate data.
///
@property(readonly) NSString *SHA256;
///
/// Certificate data.
///
@property(readonly) NSData *certData;
/// Common Name e.g: "Software Signing"
///
/// Common Name e.g: "Software Signing"
///
@property(readonly) NSString *commonName;
/// Country Name e.g: "US"
///
/// Country Name e.g: "US"
///
@property(readonly) NSString *countryName;
/// Organizational Name e.g: "Apple Inc."
///
/// Organizational Name e.g: "Apple Inc."
///
@property(readonly) NSString *orgName;
/// Organizational Unit Name e.g: "Apple Software"
///
/// Organizational Unit Name e.g: "Apple Software"
///
@property(readonly) NSString *orgUnit;
/// Issuer details, same fields as above.
///
/// Issuer details, same fields as above.
///
@property(readonly) NSString *issuerCommonName;
@property(readonly) NSString *issuerCountryName;
@property(readonly) NSString *issuerOrgName;
@property(readonly) NSString *issuerOrgUnit;
/// Validity Not Before
///
/// Validity Not Before
///
@property(readonly) NSDate *validFrom;
/// Validity Not After
///
/// Validity Not After
///
@property(readonly) NSDate *validUntil;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -18,7 +18,9 @@
#import <Security/Security.h>
@interface SNTCertificate ()
/// A container for cached property values
///
/// A container for cached property values
///
@property NSMutableDictionary *memoizedData;
@end
@@ -42,7 +44,7 @@ static NSString *const kCertDataKey = @"certData";
if (cert) {
// Despite the header file claiming that SecCertificateCreateWithData will return NULL if
// |certData| doesn't contain a valid DER-encoded X509 cert, this isn't always true.
// @c certData doesn't contain a valid DER-encoded X509 cert, this isn't always true.
// radar://problem/16124651
// To workaround, check that the certificate serial number can be retrieved.
NSData *ser = CFBridgingRelease(SecCertificateCopySerialNumber(cert, NULL));
@@ -164,9 +166,11 @@ static NSString *const kCertDataKey = @"certData";
#pragma mark Private Accessors
///
/// For a given selector, caches the value that selector would return on subsequent invocations,
/// using the provided block to get the value on the first invocation.
/// Assumes the selector's value will never change.
///
- (id)memoizedSelector:(SEL)selector forBlock:(id (^)(void))block {
NSString *selName = NSStringFromSelector(selector);
@@ -205,10 +209,13 @@ static NSString *const kCertDataKey = @"certData";
}];
}
/// Retrieve the value with the specified label from the X509 dictionary provided
/// @param desiredLabel The label you want, e.g: kSecOIDOrganizationName.
/// @param dict The dictionary to look in (Subject or Issuer)
/// @returns An @c NSString, the value for the specified label.
///
/// Retrieve the value with the specified label from the X509 dictionary provided
///
/// @param desiredLabel The label you want, e.g: kSecOIDOrganizationName.
/// @param dict The dictionary to look in (Subject or Issuer)
/// @return An @c NSString, the value for the specified label.
///
- (NSString *)x509ValueForLabel:(NSString *)desiredLabel fromDictionary:(NSDictionary *)dict {
@try {
NSArray *valArray = dict[(__bridge NSString *)kSecPropertyKeyValue];
@@ -226,10 +233,13 @@ static NSString *const kCertDataKey = @"certData";
}
}
///
/// Retrieve the specified date from the certificate's values and convert from a reference date
/// to an NSDate object.
///
/// @param key The identifier for the date: @c kSecOIDX509V1ValiditityNot{Before,After}
/// @return An @c NSDate representing the date and time the certificate is valid from or expires.
///
- (NSDate *)dateForX509Key:(NSString *)key {
NSDictionary *curCertVal = [self allCertificateValues][key];
NSNumber *value = curCertVal[(__bridge NSString *)kSecPropertyKeyValue];
@@ -250,12 +260,29 @@ static NSString *const kCertDataKey = @"certData";
CC_SHA1([self.certData bytes], (CC_LONG)[self.certData length], [SHA1Buffer mutableBytes]);
const unsigned char *bytes = (const unsigned char *)[SHA1Buffer bytes];
return [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8],
bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], bytes[16],
bytes[17], bytes[18], bytes[19]];
const unsigned char *bytes = (const unsigned char *)[SHA1Buffer bytes];
NSMutableString *hexDigest = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
[hexDigest appendFormat:@"%02x", bytes[i]];
}
return hexDigest;
}];
}
- (NSString *)SHA256 {
return [self memoizedSelector:_cmd forBlock:^id{
NSMutableData *SHA256Buffer = [[NSMutableData alloc] initWithCapacity:CC_SHA256_DIGEST_LENGTH];
CC_SHA256([self.certData bytes], (CC_LONG)[self.certData length], [SHA256Buffer mutableBytes]);
const unsigned char *bytes = (const unsigned char *)[SHA256Buffer bytes];
NSMutableString *hexDigest = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[hexDigest appendFormat:@"%02x", bytes[i]];
}
return hexDigest;
}];
}

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,42 +14,77 @@
@class SNTCertificate;
/// SNTCodesignChecker validates a binary (either on-disk or in memory) has been signed
/// and if so allows for pulling out the certificates that were used to sign it.
///
/// SNTCodesignChecker validates a binary (either on-disk or in memory) has been signed
/// and if so allows for pulling out the certificates that were used to sign it.
///
@interface SNTCodesignChecker : NSObject
/// The SecStaticCodeRef that this SNTCodesignChecker is working around
///
/// The SecStaticCodeRef that this SNTCodesignChecker is working around
///
@property(readonly) SecStaticCodeRef codeRef;
/// Returns a dictionary of raw signing information
///
/// Returns a dictionary of raw signing information
///
@property(readonly) NSDictionary *signingInformation;
/// Returns an array of @c SNTCertificate objects representing the chain that signed this binary.
///
/// Returns an array of @c SNTCertificate objects representing the chain that signed this binary.
///
@property(readonly) NSArray *certificates;
/// Returns the leaf certificate that this binary was signed with
///
/// Returns the leaf certificate that this binary was signed with
///
@property(readonly) SNTCertificate *leafCertificate;
/// Returns the on-disk path of this binary.
///
/// Returns the on-disk path of this binary.
///
@property(readonly) NSString *binaryPath;
/// Initialize an @c SNTCodesignChecker with a SecStaticCodeRef
/// Designated initializer.
/// Takes ownership of @c codeRef.
///
/// Designated initializer
/// Takes ownership of the codeRef reference.
///
/// @param codeRef a SecStaticCodeRef or SecCodeRef representing a binary.
/// @return an initialized SNTCodesignChecker if the binary is validly signed, nil otherwise.
///
- (instancetype)initWithSecStaticCodeRef:(SecStaticCodeRef)codeRef;
/// Initialize an @c SNTCodesignChecker with a binary on disk.
/// Returns nil if @c binaryPath does not exist, is not a binary or is not codesigned.
///
/// Convenience initializer for a binary on disk.
///
/// @param binaryPath A binary file on disk
/// @return an initialized SNTCodesignChecker if file is a binary and is signed, nil otherwise.
///
- (instancetype)initWithBinaryPath:(NSString *)binaryPath;
/// Initialize an @c SNTCodesignChecker with the PID of a running process.
///
/// Convenience initializer for a binary that is running, by its process ID.
///
/// @param PID Id of a running process.
/// @return an initialized SNTCodesignChecker if binary is signed, nil otherwise.
///
- (instancetype)initWithPID:(pid_t)PID;
/// Initialize an @c SNTCodesignChecker for the currently-running process.
///
/// Convenience initializer for the currently running process.
///
/// @return an initialized SNTCodesignChecker if current binary is signed, nil otherwise.
///
- (instancetype)initWithSelf;
/// Returns true if the binary represented by @c otherChecker has signing information that matches
/// this binary.
///
/// Compares the signatures of the binaries represented by this SNTCodesignChecker and
/// @c otherChecker.
///
/// If both binaries are correctly signed and the leaf signatures are identical.
///
/// @return YES if both binaries are signed with the same leaf certificate.
///
- (BOOL)signingInformationMatches:(SNTCodesignChecker *)otherChecker;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -19,36 +19,41 @@
#import "SNTCertificate.h"
// kStaticSigningFlags are the flags used when validating signatures on disk.
//
// Don't validate resources but do validate nested code. Ignoring resources _dramatically_ speeds
// up validation (see below) but does mean images, plists, etc will not be checked and modifying
// these will not be considered invalid. To ensure any code inside the binary is still checked,
// we check nested code.
//
// Timings with different flags:
// Checking Xcode 5.1.1 bundle:
// kSecCSDefaultFlags: 3.895s
// kSecCSDoNotValidateResources: 0.013s
// kSecCSDoNotValidateResources | kSecCSCheckNestedCode: 0.013s
//
// Checking Google Chrome 36.0.1985.143 bundle:
// kSecCSDefaultFlags: 0.529s
// kSecCSDoNotValidateResources: 0.032s
// kSecCSDoNotValidateResources | kSecCSCheckNestedCode: 0.033s
//
/**
* kStaticSigningFlags are the flags used when validating signatures on disk.
*
* Don't validate resources but do validate nested code. Ignoring resources _dramatically_ speeds
* up validation (see below) but does mean images, plists, etc will not be checked and modifying
* these will not be considered invalid. To ensure any code inside the binary is still checked,
* we check nested code.
*
* Timings with different flags:
* Checking Xcode 5.1.1 bundle:
* kSecCSDefaultFlags: 3.895s
* kSecCSDoNotValidateResources: 0.013s
* kSecCSDoNotValidateResources | kSecCSCheckNestedCode: 0.013s
*
* Checking Google Chrome 36.0.1985.143 bundle:
* kSecCSDefaultFlags: 0.529s
* kSecCSDoNotValidateResources: 0.032s
* kSecCSDoNotValidateResources | kSecCSCheckNestedCode: 0.033s
*/
const SecCSFlags kStaticSigningFlags = kSecCSDoNotValidateResources | kSecCSCheckNestedCode;
// kSigningFlags are the flags used when validating signatures for running binaries.
//
// No special flags needed currently.
/**
* kSigningFlags are the flags used when validating signatures for running binaries.
*
* No special flags needed currently.
*/
const SecCSFlags kSigningFlags = kSecCSDefaultFlags;
@implementation SNTCodesignChecker {
/// Array of @c SNTCertificate's representing the chain of certs this executable was signed with.
NSMutableArray *_certificates;
}
@interface SNTCodesignChecker ()
/// Array of @c SNTCertificate's representing the chain of certs this executable was signed with.
@property NSMutableArray *certificates;
@end
@implementation SNTCodesignChecker
#pragma mark Init/dealloc
@@ -81,12 +86,13 @@ const SecCSFlags kSigningFlags = kSecCSDefaultFlags;
if (!certs) return nil;
// Wrap SecCertificateRef objects in SNTCertificate and put in a new NSArray
_certificates = [[NSMutableArray alloc] initWithCapacity:certs.count];
NSMutableArray *mutableCerts = [[NSMutableArray alloc] initWithCapacity:certs.count];
for (int i = 0; i < certs.count; ++i) {
SecCertificateRef certRef = (__bridge SecCertificateRef)certs[i];
SNTCertificate *newCert = [[SNTCertificate alloc] initWithSecCertificateRef:certRef];
[_certificates addObject:newCert];
[mutableCerts addObject:newCert];
}
_certificates = [mutableCerts copy];
_codeRef = codeRef;
CFRetain(_codeRef);

View File

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

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -15,11 +15,10 @@
#ifndef SANTA__COMMON__COMMONENUMS_H
#define SANTA__COMMON__COMMONENUMS_H
// These enums are used in various places throughout the Santa client code.
// The integer values are also stored in the database and so shouldn't be changed.
// Each enum contains an _UNKNOWN and a _MAX value, which the valid values must be between so that
// the code can easily verify valid values.
///
/// These enums are used in various places throughout the Santa client code.
/// The integer values are also stored in the database and so shouldn't be changed.
///
typedef enum {
RULETYPE_UNKNOWN,
@@ -56,9 +55,12 @@ typedef enum {
EVENTSTATE_ALLOW_UNKNOWN = 1,
EVENTSTATE_ALLOW_BINARY = 2,
EVENTSTATE_ALLOW_CERTIFICATE = 3,
EVENTSTATE_BLOCK_UNKNOWN = 4,
EVENTSTATE_BLOCK_BINARY = 5,
EVENTSTATE_BLOCK_CERTIFICATE = 6,
EVENTSTATE_ALLOW_SCOPE = 4,
EVENTSTATE_BLOCK_UNKNOWN = 5,
EVENTSTATE_BLOCK_BINARY = 6,
EVENTSTATE_BLOCK_CERTIFICATE = 7,
EVENTSTATE_BLOCK_SCOPE = 8,
EVENTSTATE_MAX
} santa_eventstate_t;

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,48 +14,81 @@
#include "SNTCommonEnums.h"
/// Singleton that provides an interface for managing configuration values on disk
/// n.b: This class is designed as a singleton but is not enforced.
///
/// Singleton that provides an interface for managing configuration values on disk
/// @note This class is designed as a singleton but that is not enforced.
///
@interface SNTConfigurator : NSObject
/// The operating mode
///
/// The operating mode
///
@property santa_clientmode_t clientMode;
/// If YES, debug logging is enabled
@property(readonly) BOOL debugLogging;
# pragma mark - Sync Settings
/// The base URL of the sync server
///
/// The base URL of the sync server
///
@property(readonly) NSURL *syncBaseURL;
/// The machine owner
///
/// The machine owner
///
@property(readonly) NSString *machineOwner;
/// If set, this over-rides the default machine ID used for syncing
///
/// If set, this over-rides the default machine ID used for syncing
///
@property(readonly) NSString *machineIDOverride;
# pragma mark Server Auth Settings
/// If set, this is valid PEM containing one or more certificates to be used to evaluate the
/// server's SSL chain, overriding the list of trusted CAs distributed with the OS.
///
/// If set, this is valid PEM containing one or more certificates to be used to evaluate the
/// server's SSL chain, overriding the list of trusted CAs distributed with the OS.
///
@property(readonly) NSData *syncServerAuthRootsData;
/// This property is the same as the above but is a file on disk containing the PEM data.
///
/// This property is the same as the above but is a file on disk containing the PEM data.
///
@property(readonly) NSString *syncServerAuthRootsFile;
# pragma mark Client Auth Settings
/// If set, this is the Common Name of a certificate in the System keychain to be used for
/// sync authentication. The corresponding private key must also be in the keychain.
///
/// If set, this contains the location of a PKCS#12 certificate to be used for sync authentication.
///
@property(readonly) NSString *syncClientAuthCertificateFile;
///
/// Contains the password for the pkcs#12 certificate.
///
@property(readonly) NSString *syncClientAuthCertificatePassword;
///
/// If set, this is the Common Name of a certificate in the System keychain to be used for
/// sync authentication. The corresponding private key must also be in the keychain.
///
@property(readonly) NSString *syncClientAuthCertificateCn;
/// If set, this is the Issuer Name of a certificate in the System keychain to be used for
/// sync authentication. The corresponding private key must also be in the keychain.
///
/// If set, this is the Issuer Name of a certificate in the System keychain to be used for
/// sync authentication. The corresponding private key must also be in the keychain.
///
@property(readonly) NSString *syncClientAuthCertificateIssuer;
/// Retrieve the initialized singleton configurator object
///
/// Retrieve an initialized singleton configurator object using the default file path
///
+ (instancetype)configurator;
///
/// Designated initializer
///
/// @param filePath The path to the file to use as a backing store.
///
- (instancetype)initWithFilePath:(NSString *)filePath;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
#import "SNTLogging.h"
@interface SNTConfigurator ()
@property NSString *configFilePath;
@property NSMutableDictionary *configData;
@end
@@ -27,11 +28,12 @@ static NSString * const kConfigFilePath = @"/var/db/santa/config.plist";
/// The keys in the config file
static NSString * const kSyncBaseURLKey = @"SyncBaseURL";
static NSString * const kClientAuthCertificateFileKey = @"ClientAuthCertificateFile";
static NSString * const kClientAuthCertificatePasswordKey = @"ClientAuthCertificatePassword";
static NSString * const kClientAuthCertificateCNKey = @"ClientAuthCertificateCN";
static NSString * const kClientAuthCertificateIssuerKey = @"ClientAuthCertificateIssuerCN";
static NSString * const kServerAuthRootsDataKey = @"ServerAuthRootsData";
static NSString * const kServerAuthRootsFileKey = @"ServerAuthRootsFile";
static NSString * const kDebugLoggingKey = @"DebugLogging";
static NSString * const kClientModeKey = @"ClientMode";
static NSString * const kMachineOwnerKey = @"MachineOwner";
@@ -43,9 +45,10 @@ static NSString * const kMachineOwnerPlistKeyKey = @"MachineOwnerKey";
static NSString * const kMachineIDPlistFileKey = @"MachineIDPlist";
static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
- (instancetype)init {
- (instancetype)initWithFilePath:(NSString *)filePath {
self = [super init];
if (self) {
_configFilePath = filePath;
[self reloadConfigData];
}
return self;
@@ -57,7 +60,7 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
static SNTConfigurator *sharedConfigurator = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedConfigurator = [[SNTConfigurator alloc] init];
sharedConfigurator = [[SNTConfigurator alloc] initWithFilePath:kConfigFilePath];
});
return sharedConfigurator;
}
@@ -68,6 +71,14 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
return [NSURL URLWithString:self.configData[kSyncBaseURLKey]];
}
- (NSString *)syncClientAuthCertificateFile {
return self.configData[kClientAuthCertificateFileKey];
}
- (NSString *)syncClientAuthCertificatePassword {
return self.configData[kClientAuthCertificatePasswordKey];
}
- (NSString *)syncClientAuthCertificateCn {
return self.configData[kClientAuthCertificateCNKey];
}
@@ -112,10 +123,6 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
return @"";
}
- (BOOL)debugLogging {
return [self.configData[kDebugLoggingKey] boolValue];
}
- (santa_clientmode_t)clientMode {
int cm = [self.configData[kClientModeKey] intValue];
if (cm > CLIENTMODE_UNKNOWN && cm < CLIENTMODE_MAX) {
@@ -136,16 +143,64 @@ static NSString * const kMachineIDPlistKeyKey = @"MachineIDKey";
#pragma mark Private
///
/// Saves the current @c _configData to disk.
///
- (void)saveConfigToDisk {
[self.configData writeToFile:kConfigFilePath atomically:YES];
}
///
/// Populate @c self.configData, using the config file on disk if possible,
/// otherwise an empty mutable dictionary.
///
/// If the config file's permissions are not @c 0644, will attempt to set them
/// but will fail silently if this cannot be done.
///
- (void)reloadConfigData {
_configData = [[NSDictionary dictionaryWithContentsOfFile:kConfigFilePath] mutableCopy];
NSFileManager *fm = [NSFileManager defaultManager];
if (!_configData) {
if (![fm fileExistsAtPath:self.configFilePath]) {
_configData = [NSMutableDictionary dictionary];
return;
}
// Ensure the config file permissions are 0644. Fail silently if they can't be changed.
NSDictionary *fileAttrs = [fm attributesOfItemAtPath:self.configFilePath error:nil];
if ([fileAttrs filePosixPermissions] != 0644) {
[fm setAttributes:@{ NSFilePosixPermissions: @(0644) }
ofItemAtPath:self.configFilePath
error:nil];
}
NSError *error;
NSData *readData = [NSData dataWithContentsOfFile:self.configFilePath
options:NSDataReadingMappedIfSafe
error:&error];
if (error) {
fprintf(stderr, "%s\n", [[NSString stringWithFormat:@"Could not read configuration file %@: %@",
self.configFilePath, [error localizedDescription]] UTF8String]);
_configData = [NSMutableDictionary dictionary];
return;
}
NSDictionary *configData =
[NSPropertyListSerialization propertyListWithData:readData
options:kCFPropertyListImmutable
format:NULL
error:&error];
if (error) {
fprintf(stderr, "%s\n",
[[NSString stringWithFormat:@"Could not parse configuration file %@: %@",
self.configFilePath,
[error localizedDescription]] UTF8String]);
_configData = [NSMutableDictionary dictionary];
return;
}
_configData = [configData mutableCopy];
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,6 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// Simple function to check and drop root privileges.
/// @return True if dropping was successful or unnecessary.
BOOL DropRootPrivileges();
///
/// Simple function to check and drop root privileges.
///
/// @return YES if dropping was successful or unnecessary.
///
BOOL DropRootPrivileges();

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -27,4 +27,4 @@ BOOL DropRootPrivileges() {
}
return true;
}
}

128
Source/common/SNTFileInfo.h Normal file
View File

@@ -0,0 +1,128 @@
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Represents a binary on disk, providing access to details about that binary
/// such as the SHA-1, SHA-256, Info.plist and the Mach-O data.
///
@interface SNTFileInfo : NSObject
///
/// Designated initializer.
///
/// @param path The path of the file this instance is to represent. The path will be
/// converted to an absolute, standardized path if it isn't already.
///
- (instancetype)initWithPath:(NSString *)path;
///
/// @return Path of this file.
///
- (NSString *)path;
///
/// @return SHA-1 hash of this binary.
///
- (NSString *)SHA1;
///
/// @return SHA-256 hash of this binary.
///
- (NSString *)SHA256;
///
/// @return The type of Mach-O file, one of:
/// Dynamic Library, Kernel Extension, Fat Binary or Thin Binary.
///
- (NSString *)machoType;
///
/// @return The architectures included in this binary (e.g. x86_64, ppc).
///
- (NSArray *)architectures;
///
/// @return YES if this file is a Mach-O file.
///
- (BOOL)isMachO;
///
/// @return YES if this file contains multiple architectures.
///
- (BOOL)isFat;
///
/// @return YES if this file is an executable Mach-O file.
///
- (BOOL)isExecutable;
///
/// @return YES if this file is a dynamic library.
///
- (BOOL)isDylib;
///
/// @return YES if this file is a kernel extension.
///
- (BOOL)isKext;
///
/// @return YES if this file is a script (e.g. it begins #!).
///
- (BOOL)isScript;
///
/// @return An NSBundle if this file is part of a bundle.
///
- (NSBundle *)bundle;
///
/// @return The path to the bundle this file is a part of, if any.
///
- (NSString *)bundlePath;
///
/// @return Either the Info.plist in the bundle this file is part of, or an embedded plist if there
/// is one. In the odd case that a file has both an embedded Info.plist and is part of a bundle,
/// the Info.plist from the bundle will be returned.
///
- (NSDictionary *)infoPlist;
///
/// @return the CFBundleIdentifier from this file's Info.plist.
///
- (NSString *)bundleIdentifier;
///
/// @return the CFBundleName from this file's Info.plist.
///
- (NSString *)bundleName;
///
/// @return the CFBundleVersion from this file's Info.plist.
///
- (NSString *)bundleVersion;
///
/// @return the CFBundleShortVersionString from this file's Info.plist.
///
- (NSString *)bundleShortVersionString;
///
/// @return any URLs this file may have been downloaded from, using the
/// @c com.apple.metadata:kMDItemWhereFroms extended attribute.
///
- (NSArray *)downloadURLs;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,29 +12,54 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTBinaryInfo.h"
#import "SNTFileInfo.h"
#import <CommonCrypto/CommonDigest.h>
#include <mach-o/loader.h>
#include <mach-o/swap.h>
#include <sys/xattr.h>
@interface SNTBinaryInfo ()
@interface SNTFileInfo ()
@property NSString *path;
@property NSData *fileData;
@property NSBundle *bundleRef;
@property NSDictionary *infoDict;
@end
@implementation SNTBinaryInfo
@implementation SNTFileInfo
- (instancetype)initWithPath:(NSString *)path {
self = [super init];
if (self) {
_path = path;
// Convert to absolute, standardized path
path = [path stringByResolvingSymlinksInPath];
if (![path isAbsolutePath]) {
NSString *cwd = [[NSFileManager defaultManager] currentDirectoryPath];
path = [cwd stringByAppendingPathComponent:path];
}
path = [path stringByStandardizingPath];
_fileData = [NSData dataWithContentsOfFile:path options:NSDataReadingMappedIfSafe error:nil];
// Determine if file exists.
// If path is actually a directory, check to see if it's a bundle and has a CFBundleExecutable.
BOOL directory;
if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&directory]) {
return nil;
} else if (directory) {
NSString *infoPath = [path stringByAppendingPathComponent:@"Contents/Info.plist"];
NSDictionary *d = [NSDictionary dictionaryWithContentsOfFile:infoPath];
if (d && d[@"CFBundleExecutable"]) {
path = [path stringByAppendingPathComponent:@"Contents/MacOS"];
_path = [path stringByAppendingPathComponent:d[@"CFBundleExecutable"]];
} else {
return nil;
}
} else {
_path = path;
}
_fileData = [NSData dataWithContentsOfFile:_path options:NSDataReadingMappedIfSafe error:nil];
if (!_fileData) return nil;
}
@@ -54,6 +79,18 @@
return buf;
}
- (NSString *)SHA256 {
unsigned char sha2[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(self.fileData.bytes, (unsigned int)self.fileData.length, sha2);
NSMutableString *buf = [[NSMutableString alloc] initWithCapacity:CC_SHA256_DIGEST_LENGTH *2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[buf appendFormat:@"%02x", (unsigned char)sha2[i]];
}
return buf;
}
- (NSString *)machoType {
if ([self isDylib]) { return @"Dynamic Library"; }
if ([self isKext]) { return @"Kernel Extension"; }
@@ -148,26 +185,26 @@
# pragma mark Bundle Information
/**
* Try and determine the bundle that the represented executable is contained within, if any.
*
* 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 to count
* as being part of the bundle.
*
* This method relies on executable bundles being laid out as follows:
*
*@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.
*/
///
/// Try and determine the bundle that the represented executable is contained within, if any.
///
/// 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 to count
/// as being part of the bundle.
///
/// This method relies on executable bundles being laid out as follows:
///
/// @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.
///
- (NSBundle *)bundle {
if (self.bundleRef) return self.bundleRef;
@@ -220,11 +257,38 @@
return [[self infoPlist] objectForKey:@"CFBundleShortVersionString"];
}
- (NSArray *)downloadURLs {
char *path = (char *)[self.path fileSystemRepresentation];
size_t size = getxattr(path, "com.apple.metadata:kMDItemWhereFroms", NULL, 0, 0, 0);
char *value = malloc(size);
if (!value) return nil;
if (getxattr(path, "com.apple.metadata:kMDItemWhereFroms", value, size, 0, 0) == -1) {
free(value);
return nil;
}
NSData *data = [NSData dataWithBytes:value length:size];
free(value);
if (data) {
NSArray *urls = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:NULL
error:NULL];
return urls;
}
return nil;
}
# pragma mark Internal Methods
/// Look through the file for the first mach_header. If the file is thin, this will be the
/// header at the beginning of the file. If the file is fat, it will be the first
/// architecture-specific header.
///
/// Look through the file for the first mach_header. If the file is thin, this will be the
/// header at the beginning of the file. If the file is fat, it will be the first
/// architecture-specific header.
///
- (struct mach_header *)firstMachHeader {
if (![self isMachO]) return NULL;
@@ -261,8 +325,10 @@
return (header->magic == FAT_MAGIC || header->magic == FAT_CIGAM);
}
/// Wrap subdataWithRange: in a @try/@catch, returning nil on exception.
/// Useful for when the range is beyond the end of the file.
///
/// Wrap @c subdataWithRange: in a @@try/@@catch, returning nil on exception.
/// Useful for when the range is beyond the end of the file.
///
- (NSData *)safeSubdataWithRange:(NSRange)range {
@try {
return [self.fileData subdataWithRange:range];

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,16 +12,16 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Common defines between kernel <-> userspace
///
#ifndef SANTA__COMMON__KERNELCOMMON_H
#define SANTA__COMMON__KERNELCOMMON_H
// Defines the lengths of paths and SHA-1's passed around.
#define MAX_PATH_LEN 1024
#define MAX_SHA1_LEN 20
#define MAX_SHA1_STRING 41
#define MAX_VNODE_ID_STR 21
// Defines the lengths of paths and Vnode IDs passed around.
#define MAX_PATH_LEN 1024 // ==PATH_LEN from syslimits.h
#define MAX_VNODE_ID_STR 21 // digits in UINT64_MAX + 1 for NULL-terminator
// Defines the name of the userclient class and the driver bundle ID.
#define USERCLIENT_CLASS "com_google_SantaDriver"
@@ -58,14 +58,17 @@ typedef enum {
ACTION_ERROR = 99,
} santa_action_t;
#define CHECKBW_RESPONSE_VALID(x) (x == ACTION_RESPOND_CHECKBW_ALLOW || \
x == ACTION_RESPOND_CHECKBW_DENY)
// Message struct that is sent down the IODataQueue.
typedef struct {
santa_action_t action;
uint64_t vnode_id;
uid_t userId;
pid_t pid;
char sha1[MAX_SHA1_STRING];
pid_t ppid;
char path[MAX_PATH_LEN];
uint64_t vnode_id;
} santa_message_t;
#endif // SANTA__COMMON__KERNELCOMMON_H

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,7 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Logging definitions, for both kernel and user space.
///
#ifndef SANTA__COMMON__LOGGING_H
#define SANTA__COMMON__LOGGING_H
@@ -35,11 +37,14 @@
#define LOG_LEVEL_INFO 3
#define LOG_LEVEL_DEBUG 4
/// Logging function.
/// level is one of the levels defined above
/// error is the destination a FILE, generally should be stdout or stderr
/// format is the printf style format string
/// ... is the arguments to format.
///
/// Logging function.
///
/// @param level one of the levels defined above
/// @param destination a FILE, generally should be stdout or stderr
/// @param format the printf style format string
/// @param ... the arguments to format.
///
void logMessage(int level, FILE *destination, NSString *format, ...);
/// Simple logging macros

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,8 +14,6 @@
#import "SNTLogging.h"
#import "SNTConfigurator.h"
#ifdef DEBUG
static int logLevel = LOG_LEVEL_DEBUG; // default to info
#else
@@ -35,7 +33,7 @@ void logMessage(int level, FILE *destination, NSString *format, ...) {
binaryName = [[NSProcessInfo processInfo] processName];
// If debug logging is enabled, the process must be restarted.
if ([[SNTConfigurator configurator] debugLogging]) {
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--debug"]) {
logLevel = LOG_LEVEL_DEBUG;
}
});
@@ -62,4 +60,4 @@ void logMessage(int level, FILE *destination, NSString *format, ...) {
fprintf(destination, "%s\n", [[NSString stringWithFormat:@"[%@] %@ %@: %@",
[dateFormatter stringFromDate:[NSDate date]], levelName, binaryName, s] UTF8String]);
}
}
}

View File

@@ -1,37 +0,0 @@
/// Copyright 2014 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.
@class SNTCertificate;
/// An SNTEvent is created when Santa is making a decision about an execution request.
/// All of the information required to make that decision, log it, notify the user etc. must be
/// encapsulated within this class.
@interface SNTNotificationMessage : NSObject<NSSecureCoding>
/// The path of the binary that was blocked.
@property(copy) NSString *path;
/// The SHA-1 of the binary that was blocked.
@property(copy) NSString *SHA1;
/// An array of @c SNTCertificate objects representing the certificate chain the binary was signed with.
@property(copy) NSArray *certificates;
/// A custom message to display to the user when blocking this binary, if any.
@property(copy) NSString *customMessage;
// A convenience accessor to the first certificate in @c certificates.
@property(readonly) SNTCertificate *leafCertificate;
@end

View File

@@ -1,55 +0,0 @@
/// Copyright 2014 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 "SNTNotificationMessage.h"
#import "SNTCertificate.h"
@implementation SNTNotificationMessage
static NSString *const kPathKey = @"path";
static NSString *const kSHA1Key = @"sha1";
static NSString *const kCertificatesKey = @"certificates";
static NSString *const kCustomMessageKey = @"custommessage";
#pragma mark NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.path forKey:kPathKey];
[coder encodeObject:self.SHA1 forKey:kSHA1Key];
[coder encodeObject:self.customMessage forKey:kCustomMessageKey];
[coder encodeObject:self.certificates forKey:kCertificatesKey];
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
_path = [decoder decodeObjectOfClass:[NSString class] forKey:kPathKey];
_SHA1 = [decoder decodeObjectOfClass:[NSString class] forKey:kSHA1Key];
_customMessage = [decoder decodeObjectOfClass:[NSString class] forKey:kCustomMessageKey];
NSSet *certClasses = [NSSet setWithObjects:[NSArray class], [SNTCertificate class], nil];
_certificates = [decoder decodeObjectOfClasses:certClasses forKey:kCertificatesKey];
return self;
}
#pragma mark Calculated Properties
- (SNTCertificate *)leafCertificate {
return [self.certificates firstObject];
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,25 +14,37 @@
#include "SNTCommonEnums.h"
/// Represents a Rule.
///
/// Represents a Rule.
///
@interface SNTRule : NSObject<NSSecureCoding>
/// The SHA-1 hash of the object this rule is for
@property NSString *SHA1;
///
/// The hash of the object this rule is for
///
@property NSString *shasum;
/// The state of this rule
///
/// The state of this rule
///
@property santa_rulestate_t state;
/// The type of object this rule is for (binary, certificate)
///
/// The type of object this rule is for (binary, certificate)
///
@property santa_ruletype_t type;
/// A custom message that will be displayed if this rule blocks a binary from executing
///
/// A custom message that will be displayed if this rule blocks a binary from executing
///
@property NSString *customMsg;
/// Designated initializer.
- (instancetype)initWithSHA1:(NSString *)SHA1
state:(santa_rulestate_t)state
type:(santa_ruletype_t)type
customMsg:(NSString *)customMsg;
///
/// Designated initializer.
///
- (instancetype)initWithShasum:(NSString *)shasum
state:(santa_rulestate_t)state
type:(santa_ruletype_t)type
customMsg:(NSString *)customMsg;
@end
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,18 +16,13 @@
@implementation SNTRule
static NSString *const kSHA1Key = @"sha1";
static NSString *const kStateKey = @"state";
static NSString *const kTypeKey = @"type";
static NSString *const kCustomMessageKey = @"custommsg";
- (instancetype)initWithSHA1:(NSString *)SHA1
state:(santa_rulestate_t)state
type:(santa_ruletype_t)type
customMsg:(NSString *)customMsg {
- (instancetype)initWithShasum:(NSString *)shasum
state:(santa_rulestate_t)state
type:(santa_ruletype_t)type
customMsg:(NSString *)customMsg {
self = [super init];
if (self) {
_SHA1 = SHA1;
_shasum = shasum;
_state = state;
_type = type;
_customMsg = customMsg;
@@ -37,23 +32,30 @@ static NSString *const kCustomMessageKey = @"custommsg";
#pragma mark NSSecureCoding
#define ENCODE(obj, key) if (obj) [coder encodeObject:obj forKey:key]
#define DECODE(cls, key) [decoder decodeObjectOfClass:[cls class] forKey:key]
#define DECODEARRAY(cls, key) \
[decoder decodeObjectOfClasses:[NSSet setWithObjects:[NSArray class], [cls class], nil] \
forKey:key]
+ (BOOL)supportsSecureCoding { return YES; }
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.SHA1 forKey:kSHA1Key];
[coder encodeInt:self.state forKey:kStateKey];
[coder encodeInt:self.type forKey:kTypeKey];
[coder encodeObject:self.customMsg forKey:kCustomMessageKey];
ENCODE(self.shasum, @"shasum");
ENCODE(@(self.state), @"state");
ENCODE(@(self.type), @"type");
ENCODE(self.customMsg, @"custommsg");
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
NSSet *stringPlusNull = [NSSet setWithObjects:[NSString class], [NSNull class], nil];
_SHA1 = [decoder decodeObjectOfClass:[NSString class] forKey:kSHA1Key];
_state = [decoder decodeIntForKey:kStateKey];
_type = [decoder decodeIntForKey:kTypeKey];
_customMsg = [decoder decodeObjectOfClasses:stringPlusNull forKey:kCustomMessageKey];
self = [super init];
if (self) {
_shasum = DECODE(NSString, @"shasum");
_state = [DECODE(NSNumber, @"state") intValue];
_type = [DECODE(NSNumber, @"type") intValue];
_customMsg = DECODE(NSString, @"custommsg");
}
return self;
}
@end
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,27 +14,80 @@
#include "SNTCommonEnums.h"
/// Represents an event stored in the database.
///
/// Represents an event stored in the database.
///
@interface SNTStoredEvent : NSObject<NSSecureCoding>
///
/// An index for this event, empty unless the event came from the database.
///
@property NSNumber *idx;
@property NSString *fileSHA1;
///
/// The SHA-256 of the executed file.
///
@property NSString *fileSHA256;
///
/// The full path of the executed file.
///
@property NSString *filePath;
///
/// If the executed file was part of the bundle, this is the CFBundleName.
///
@property NSString *fileBundleName;
///
/// If the executed file was part of the bundle, this is the CFBundleID.
///
@property NSString *fileBundleID;
///
/// If the executed file was part of the bundle, this is the CFBundleVersion.
///
@property NSString *fileBundleVersion;
///
/// If the executed file was part of the bundle, this is the CFBundleShortVersionString.
///
@property NSString *fileBundleVersionString;
@property NSString *certSHA1;
@property NSString *certCN;
@property NSString *certOrg;
@property NSString *certOU;
@property NSDate *certValidFromDate;
@property NSDate *certValidUntilDate;
///
/// If the executed file was signed, this is an NSArray of SNTCertificate's
/// representing the signing chain.
///
@property NSArray *signingChain;
///
/// The user who executed the binary.
///
@property NSString *executingUser;
///
/// The date and time the execution request was received by santad.
///
@property NSDate *occurrenceDate;
///
/// The decision santad returned.
///
@property santa_eventstate_t decision;
///
/// NSArray of logged in users when the decision was made.
///
@property NSArray *loggedInUsers;
///
/// NSArray of sessions when the decision was made (e.g. nobody@console, nobody@ttys000).
///
@property NSArray *currentSessions;
///
/// The process ID of the binary being executed.
///
@property NSNumber *pid;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,75 +14,66 @@
#import "SNTStoredEvent.h"
#import "SNTCertificate.h"
@implementation SNTStoredEvent
#define ENCODE(obj, key) if (obj) [coder encodeObject:obj forKey:key]
#define DECODE(cls, key) [decoder decodeObjectOfClass:[cls class] forKey:key]
#define DECODEARRAY(cls, key) \
[decoder decodeObjectOfClasses:[NSSet setWithObjects:[NSArray class], [cls class], nil] \
forKey:key]
+ (BOOL)supportsSecureCoding { return YES; }
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.idx forKey:@"idx"];
[coder encodeObject:self.fileSHA1 forKey:@"fileSHA1"];
[coder encodeObject:self.filePath forKey:@"filePath"];
ENCODE(self.idx, @"idx");
ENCODE(self.fileSHA256, @"fileSHA256");
ENCODE(self.filePath, @"filePath");
if (self.fileBundleName) [coder encodeObject:self.fileBundleName forKey:@"fileBundleName"];
if (self.fileBundleID) [coder encodeObject:self.fileBundleID forKey:@"fileBundleID"];
if (self.fileBundleVersion) {
[coder encodeObject:self.fileBundleVersion forKey:@"fileBundleVersion"];
}
if (self.fileBundleVersionString) {
[coder encodeObject:self.fileBundleVersionString forKey:@"fileBundleVersionString"];
}
ENCODE(self.fileBundleName, @"fileBundleName");
ENCODE(self.fileBundleID, @"fileBundleID");
ENCODE(self.fileBundleVersion, @"fileBundleVersion");
ENCODE(self.fileBundleVersionString, @"fileBundleVersionString");
if (self.certSHA1) [coder encodeObject:self.certSHA1 forKey:@"certSHA1"];
if (self.certCN) [coder encodeObject:self.certCN forKey:@"certCN"];
if (self.certOrg) [coder encodeObject:self.certOrg forKey:@"certOrg"];
if (self.certOU) [coder encodeObject:self.certOU forKey:@"certOU"];
if (self.certValidFromDate) {
[coder encodeObject:self.certValidFromDate forKey:@"certValidFromDate"];
}
if (self.certValidUntilDate) {
[coder encodeObject:self.certValidUntilDate forKey:@"certValidUntilDate"];
}
ENCODE(self.signingChain, @"signingChain");
[coder encodeObject:self.executingUser forKey:@"executingUser"];
[coder encodeObject:self.occurrenceDate forKey:@"occurrenceDate"];
[coder encodeInt:self.decision forKey:@"decision"];
ENCODE(self.executingUser, @"executingUser");
ENCODE(self.occurrenceDate, @"occurrenceDate");
ENCODE(@(self.decision), @"decision");
if (self.loggedInUsers) [coder encodeObject:self.loggedInUsers forKey:@"loggedInUsers"];
if (self.currentSessions) [coder encodeObject:self.currentSessions forKey:@"currentSessions"];
ENCODE(self.loggedInUsers, @"loggedInUsers");
ENCODE(self.currentSessions, @"currentSessions");
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
_idx = [decoder decodeObjectOfClass:[NSNumber class] forKey:@"idx"];
_fileSHA1 = [decoder decodeObjectOfClass:[NSString class] forKey:@"fileSHA1"];
_filePath = [decoder decodeObjectOfClass:[NSString class] forKey:@"filePath"];
_fileBundleName = [decoder decodeObjectOfClass:[NSString class] forKey:@"fileBundleName"];
self = [super init];
if (self) {
_idx = DECODE(NSNumber, @"idx");
_fileSHA256 = DECODE(NSString, @"fileSHA256");
_filePath = DECODE(NSString, @"filePath");
_fileBundleID = [decoder decodeObjectOfClass:[NSString class] forKey:@"fileBundleID"];
_fileBundleVersion = [decoder decodeObjectOfClass:[NSString class] forKey:@"fileBundleVersion"];
_fileBundleVersionString =
[decoder decodeObjectOfClass:[NSString class] forKey:@"fileBundleVersionString"];
_certSHA1 = [decoder decodeObjectOfClass:[NSString class] forKey:@"certSHA1"];
_certCN = [decoder decodeObjectOfClass:[NSString class] forKey:@"certCN"];
_certOrg = [decoder decodeObjectOfClass:[NSString class] forKey:@"certOrg"];
_certOU = [decoder decodeObjectOfClass:[NSString class] forKey:@"certOU"];
_certValidFromDate = [decoder decodeObjectOfClass:[NSDate class] forKey:@"certValidFromDate"];
_certValidUntilDate = [decoder decodeObjectOfClass:[NSDate class] forKey:@"certValidUntilDate"];
_executingUser = [decoder decodeObjectOfClass:[NSString class] forKey:@"executingUser"];
_occurrenceDate = [decoder decodeObjectOfClass:[NSDate class] forKey:@"occurrenceDate"];
_decision = [decoder decodeIntForKey:@"decision"];
_fileBundleName = DECODE(NSString, @"fileBundleName");
_fileBundleID = DECODE(NSString, @"fileBundleID");
_fileBundleVersion = DECODE(NSString, @"fileBundleVersion");
_fileBundleVersionString = DECODE(NSString, @"fileBundleVersionString");
NSSet *stringAndArrayClasses = [NSSet setWithObjects:[NSArray class], [NSString class], nil];
_loggedInUsers = [decoder decodeObjectOfClasses:stringAndArrayClasses forKey:@"loggedInUsers"];
_currentSessions = [decoder decodeObjectOfClasses:stringAndArrayClasses
forKey:@"currentSessions"];
_signingChain = DECODEARRAY(SNTCertificate, @"signingChain");
_executingUser = DECODE(NSString, @"executingUser");
_occurrenceDate = DECODE(NSDate, @"occurrenceDate");
_decision = [DECODE(NSNumber, @"decision") intValue];
_loggedInUsers = DECODEARRAY(NSString, @"loggedInUsers");
_currentSessions = DECODEARRAY(NSString, @"currentSessions");
}
return self;
}
- (BOOL)isEqual:(SNTStoredEvent *)other {
if (other == self) return YES;
if (![other isKindOfClass:[SNTStoredEvent class]]) return NO;
return ([self.fileSHA1 isEqual:other.fileSHA1] &&
return ([self.fileSHA256 isEqual:other.fileSHA256] &&
[self.idx isEqual:other.idx]);
}
@@ -90,13 +81,14 @@
NSUInteger prime = 31;
NSUInteger result = 1;
result = prime * result + [self.idx hash];
result = prime * result + [self.fileSHA1 hash];
result = prime * result + [self.filePath hash];
result = prime * result + [self.fileSHA256 hash];
result = prime * result + [self.occurrenceDate hash];
return result;
}
- (NSString *)description {
return [NSString stringWithFormat:@"SNTStoredEvent[%@] with SHA-1: %@", self.idx, self.fileSHA1];
return [NSString stringWithFormat:@"SNTStoredEvent[%@] with SHA-256: %@",
self.idx, self.fileSHA256];
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,17 +12,39 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// Simple class for fetching system information
///
/// Simple class for fetching system information
///
@interface SNTSystemInfo : NSObject
///
/// @return System serial number
///
+ (NSString *)serialNumber;
///
/// @return System hardware UUID
///
+ (NSString *)hardwareUUID;
///
/// @return OS Version, e.g.: 10.10.2
///
+ (NSString *)osVersion;
///
/// @return OS Build, e.g.: 14C109
///
+ (NSString *)osBuild;
///
/// @return Short hostname
///
+ (NSString *)shortHostname;
///
/// @return Long hostname
///
+ (NSString *)longHostname;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,76 +12,108 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
/**
* A validating XPC connection/listener which uses codesigning to validate that both ends of the
* connection were signed by the same certificate chain.
*
* Example server started by @c launchd where the @c launchd job has a @c MachServices key:
*
*@code
* SNTXPCConnection *conn = [[SNTXPCConnection alloc] initServerWithName:@"MyServer"];
* conn.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)];
* conn.exportedObject = myObject;
* conn.remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyClientProtocol)];
* [conn resume];
*@endcode
*
* Example client, connecting to above server:
*
*@code
* SNTXPCConnection *conn = [[SNTXPCConnection alloc] initClientWithName:"MyServer" withOptions:0];
* conn.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyClientProtocol)];
* conn.exportedObject = myObject;
* conn.remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)];
* conn.invalidationHandler = ^{ NSLog(@"Connection invalidated") };
* [conn resume];
*@endcode
*
* Either side can then send a message to the other with:
*
*@code
* [conn.remoteObjectProxy selectorInRemoteInterface];
*@endcode
*
* Note: messages are always delivered on a background thread!
**/
///
/// A validating XPC connection/listener which uses codesigning to validate that both ends of the
/// connection were signed by the same certificate chain.
///
/// Example server started by @c launchd where the @c launchd job has a @c MachServices key:
///
/// @code
/// SNTXPCConnection *conn = [[SNTXPCConnection alloc] initServerWithName:@"MyServer"];
/// conn.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)];
/// conn.exportedObject = myObject;
/// conn.remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyClientProtocol)];
/// [conn resume];
/// @endcode
///
/// Example client, connecting to above server:
///
/// @code
/// SNTXPCConnection *conn = [[SNTXPCConnection alloc] initClientWithName:"MyServer"
/// withOptions:0];
/// conn.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyClientProtocol)];
/// conn.exportedObject = myObject;
/// conn.remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)];
/// conn.invalidationHandler = ^{ NSLog(@"Connection invalidated") };
/// [conn resume];
/// @endcode
///
/// Either side can then send a message to the other with:
///
/// @code
/// [conn.remoteObjectProxy selectorInRemoteInterface];
/// @endcode
///
/// @note messages are always delivered on a background thread!
///
@interface SNTXPCConnection : NSObject<NSXPCListenerDelegate>
typedef void (^SNTXPCInvalidationBlock)(void);
typedef void (^SNTXPCAcceptedBlock)(void);
typedef void (^SNTXPCRejectedBlock)(void);
/// The interface the remote object should conform to.
///
/// The interface the remote object should conform to.
///
@property(retain) NSXPCInterface *remoteInterface;
/// A proxy to the object at the other end of the connection.
/// *Warning*: Do not send a message to this object if you didn't set @c remoteInterface above
/// before calling the @c resume method, doing so will throw an exception.
///
/// A proxy to the object at the other end of the connection.
///
/// @warning Do not send a message to this object if you didn't set @c remoteInterface above
/// before calling the @c resume method. Doing so will throw an exception.
///
@property(readonly) id remoteObjectProxy;
/// The interface this object conforms to.
///
/// The interface this object exports.
///
@property(retain) NSXPCInterface *exportedInterface;
/// The object that responds to messages from the other end.
///
/// The object that responds to messages from the other end.
///
@property(retain) id exportedObject;
/// A block to run when the connection is invalidated.
///
/// A block to run when the connection is invalidated.
///
@property(copy) SNTXPCInvalidationBlock invalidationHandler;
/// A block to run when the connection has been accepted.
///
/// A block to run when the connection has been accepted.
///
@property(copy) SNTXPCAcceptedBlock acceptedHandler;
/// A block to run when the connection has been rejected.
///
/// A block to run when the connection has been rejected.
///
@property(copy) SNTXPCRejectedBlock rejectedHandler;
/// Initializer for the 'server' side of the connection, the binary that was started by launchd.
///
/// Initializer for the 'server' side of the connection, the binary that was started by launchd.
///
/// @param name MachService name
///
- (instancetype)initServerWithName:(NSString *)name;
/// Initializer for the 'client' side of the connection. If the 'server' was started as a
/// LaunchDaemon (running as root), pass |NSXPCConnectionPrivileged| for |options|, otherwise use 0.
///
/// Initializer for the 'client' side of the connection.
///
/// @param name MachService name
/// @param options Use NSXPCConnectionPrivileged if the server is running as root, otherwise use 0.
///
- (instancetype)initClientWithName:(NSString *)name options:(NSXPCConnectionOptions)options;
/// Call when the properties of the object have been set-up and you're ready for connections.
///
/// Call when the properties of the object have been set-up and you're ready for connections.
/// Blocks the executing thread for up to 5s while waiting for the verification to complete.
///
- (void)resume;
///
/// Invalidate the connection. This must be done before the connection can be released.
///
- (void)invalidate;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -21,14 +21,22 @@
@end
@interface SNTXPCConnection ()
///
/// The XPC listener (used on server-side only).
///
@property NSXPCListener *listenerObject;
///
/// The current connection object.
///
@property NSXPCConnection *currentConnection;
///
/// The remote interface to use while the connection hasn't been validated.
///
@property NSXPCInterface *validatorInterface;
@end
@implementation SNTXPCConnection
@@ -88,6 +96,7 @@
[connection resume];
__block BOOL verificationComplete = NO;
[[connection remoteObjectProxy] isConnectionValidWithBlock:^void(BOOL response) {
pid_t pid = self.currentConnection.processIdentifier;
@@ -101,12 +110,19 @@
self.currentConnection.exportedObject = self.exportedObject;
[self invokeAcceptedHandler];
[self.currentConnection resume];
verificationComplete = YES;
} else {
[self invokeRejectedHandler];
[self.currentConnection invalidate];
self.currentConnection = nil;
verificationComplete = YES;
}
}];
// Wait for validation to complete, at most 5s
for (int sleepLoops = 0; sleepLoops < 1000 && !verificationComplete; sleepLoops++) {
usleep(5000);
}
}
}
@@ -152,11 +168,11 @@
[self invokeAcceptedHandler];
// Let remote end know that we accepted. Note: in acception this must come last otherwise
// Let remote end know that we accepted. In acception this must come last otherwise
// the remote end might start sending messages before the interface is fully set-up.
block(YES);
} else {
// Let remote end know that we rejected. Note: in rejection this must come first otherwise
// Let remote end know that we rejected. In rejection this must come first otherwise
// the connection is invalidated before the client ever realizes.
block(NO);
@@ -194,4 +210,13 @@
}
}
#pragma mark Connection tear-down
- (void)invalidate {
if (self.currentConnection) {
[self.currentConnection invalidate];
self.currentConnection = nil;
}
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -17,24 +17,32 @@
@class SNTRule;
@class SNTStoredEvent;
/// Protocol implemented by santad and utilized by santactl
///
/// Protocol implemented by santad and utilized by santactl
///
@protocol SNTDaemonControlXPC
/// Kernel ops
///
/// Kernel ops
///
- (void)cacheCount:(void (^)(uint64_t))reply;
- (void)flushCache:(void (^)(BOOL))reply;
/// Database ops
///
/// Database ops
///
- (void)databaseRuleCounts:(void (^)(uint64_t binary, uint64_t certificate))reply;
- (void)databaseRuleAddRule:(SNTRule *)rule withReply:(void (^)())reply;
- (void)databaseRuleAddRules:(NSArray *)rules withReply:(void (^)())reply;
- (void)databaseEventCount:(void (^)(uint64_t count))reply;
- (void)databaseEventForSHA1:(NSString *)sha1 withReply:(void (^)(SNTStoredEvent *))reply;
- (void)databaseEventForSHA256:(NSString *)sha256 withReply:(void (^)(SNTStoredEvent *))reply;
- (void)databaseEventsPending:(void (^)(NSArray *events))reply;
- (void)databaseRemoveEventsWithIDs:(NSArray *)ids;
/// Misc ops
///
/// Misc ops
///
- (void)clientMode:(void (^)(santa_clientmode_t))reply;
- (void)setClientMode:(santa_clientmode_t)mode withReply:(void (^)())reply;
@@ -42,11 +50,15 @@
@interface SNTXPCControlInterface : NSObject
/// Returns the MachService ID for this service.
///
/// Returns the MachService ID for this service.
///
+ (NSString *)serviceId;
/// Returns an initialized NSXPCInterface for the SNTDaemonControlXPC protocol.
/// Ensures any methods that accept custom classes as arguments are set-up before returning
///
/// Returns an initialized NSXPCInterface for the SNTDaemonControlXPC protocol.
/// Ensures any methods that accept custom classes as arguments are set-up before returning
///
+ (NSXPCInterface *)controlInterface;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -13,18 +13,22 @@
/// limitations under the License.
/// Protocol implemented by SantaNotifier and utilized by santad
@class SNTNotificationMessage;
@class SNTStoredEvent;
@protocol SNTNotifierXPC
- (void)postBlockNotification:(SNTNotificationMessage *)event;
- (void)postBlockNotification:(SNTStoredEvent *)event withCustomMessage:(NSString *)message;
@end
@interface SNTXPCNotifierInterface : NSObject
/// Returns the MachService ID for this service.
///
/// @return the MachService ID for this service.
///
+ (NSString *)serviceId;
/// Returns an initialized NSXPCInterface for the SNTNotifierXPC protocol.
/// Ensures any methods that accept custom classes as arguments are set-up before returning
///
/// @return an initialized NSXPCInterface for the SNTNotifierXPC protocol.
/// Ensures any methods that accept custom classes as arguments are set-up before returning
///
+ (NSXPCInterface *)notifierInterface;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -2,26 +2,22 @@
<!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>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.google.santa-driver</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>KEXT</string>
<key>CFBundleShortVersionString</key>
<string>0.7</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>NSHumanReadableCopyright</key>
<string>Google, Inc.</string>
<key>CFBundleIdentifier</key>
<string>com.google.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleVersion</key>
<string>0.7</string>
<string>TO.BE.FILLED</string>
<key>CFBundleShortVersionString</key>
<string>TO.BE.FILLED</string>
<key>IOKitPersonalities</key>
<dict>
<key>SantaDriver</key>

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -73,7 +73,7 @@ void SantaDecisionManager::free() {
# pragma mark Cache Management
bool SantaDecisionManager::AddToCache(
void SantaDecisionManager::AddToCache(
const char *identifier, santa_action_t decision, uint64_t microsecs) {
IORWLockWrite(cached_decisions_lock_);
@@ -87,25 +87,20 @@ bool SantaDecisionManager::AddToCache(
cached_decisions_->flushCollection();
}
bool result = false;
if (decision == ACTION_REQUEST_CHECKBW) {
SantaMessage *pending = new SantaMessage();
pending->setAction(ACTION_REQUEST_CHECKBW, 0);
result = cached_decisions_->setObject(identifier, pending);
cached_decisions_->setObject(identifier, pending);
pending->release(); // it was retained when added to the dictionary
} else {
SantaMessage *pending = OSDynamicCast(
SantaMessage, cached_decisions_->getObject(identifier));
if (pending) {
pending->setAction(decision, microsecs);
result = true;
}
}
IORWLockUnlock(cached_decisions_lock_);
return result;
}
void SantaDecisionManager::CacheCheck(const char *identifier) {
@@ -142,8 +137,7 @@ santa_action_t SantaDecisionManager::GetFromCache(const char *identifier) {
}
IORWLockUnlock(cached_decisions_lock_);
if (result == ACTION_RESPOND_CHECKBW_ALLOW ||
result == ACTION_RESPOND_CHECKBW_DENY) {
if (CHECKBW_RESPONSE_VALID(result)) {
uint64_t diff_time = GetCurrentUptime();
if (result == ACTION_RESPOND_CHECKBW_ALLOW) {
@@ -195,21 +189,10 @@ santa_action_t SantaDecisionManager::FetchDecision(
return_action = GetFromCache(vnode_id_str);
// If item wasn't in cache, fetch decision from daemon.
if (return_action == ACTION_UNSET) {
if (!CHECKBW_RESPONSE_VALID(return_action)) {
// Add pending request to cache
AddToCache(vnode_id_str, ACTION_REQUEST_CHECKBW, 0);
// Get SHA-1
// TODO(rah): Investigate possible race condition where file is modified
// in between SHA-1 being calculated and response for said file being
// received.
char sha[MAX_SHA1_STRING];
if (!CalculateSHA1ForVnode(credential, vfs_context, vnode, sha)) {
LOGD("Unable to get SHA-1 for file, denying execution");
CacheCheck(vnode_id_str);
return ACTION_RESPOND_CHECKBW_DENY;
}
// Get path
char path[MAX_PATH_LEN];
int name_len = MAX_PATH_LEN;
@@ -219,10 +202,10 @@ santa_action_t SantaDecisionManager::FetchDecision(
// Prepare to send message to daemon
santa_message_t message;
strncpy(message.sha1, sha, MAX_SHA1_STRING);
strncpy(message.path, path, MAX_PATH_LEN);
message.userId = kauth_cred_getuid(credential);
message.pid = proc_selfpid();
message.ppid = proc_selfppid();
message.action = ACTION_REQUEST_CHECKBW;
message.vnode_id = vnode_id;
@@ -240,11 +223,13 @@ santa_action_t SantaDecisionManager::FetchDecision(
for (int i = 0; i < kMaxRequestLoops; ++i) {
IOSleep(kRequestLoopSleepMilliseconds);
return_action = GetFromCache(vnode_id_str);
if (return_action != ACTION_REQUEST_CHECKBW) break;
if (CHECKBW_RESPONSE_VALID(return_action)) break;
}
} while (return_action == ACTION_REQUEST_CHECKBW && proc_exiting(owning_proc_) == 0);
} while (!CHECKBW_RESPONSE_VALID(return_action) &&
proc_exiting(owning_proc_) == 0);
if (return_action == ACTION_UNSET || return_action == ACTION_ERROR) {
// If response is still not valid, the daemon exited
if (!CHECKBW_RESPONSE_VALID(return_action)) {
LOGE("Daemon process did not respond correctly. Allowing executions "
"until it comes back.");
CacheCheck(vnode_id_str);
@@ -257,67 +242,6 @@ santa_action_t SantaDecisionManager::FetchDecision(
# pragma mark Misc
bool SantaDecisionManager::CalculateSHA1ForVnode(const kauth_cred_t credential,
const vfs_context_t context,
const vnode_t vp,
char *out) {
out[0] = '\0';
// Get binary size
uint64_t binary_size;
struct vnode_attr vap;
VATTR_INIT(&vap);
VATTR_WANTED(&vap, va_data_size);
vnode_getattr(vp, &vap, context);
binary_size = vap.va_data_size;
// Initialize the SHA1 context
SHA1_CTX sha1_ctx;
SHA1Init(&sha1_ctx);
// |chunkSize| should equal one page so that where possible
// the kernel can offload the calculation to dedicated hardware.
int chunkSize = PAGE_SIZE_64;
void *readChunk = IOMalloc(chunkSize);
// Credentials needed for vn_rdwr
kauth_cred_t kerncred = vfs_context_ucred(context);
proc_t p = vfs_context_proc(context);
// Read the file in chunks, updating the SHA as we go
for (uint64_t offset = 0; offset < binary_size; offset += chunkSize) {
int readSize;
if (offset + chunkSize > binary_size) {
readSize = (int)(binary_size - offset);
} else {
readSize = chunkSize;
}
int resid; // unused
if (vn_rdwr(UIO_READ, vp, (caddr_t)readChunk, readSize, offset,
UIO_SYSSPACE, IO_NOAUTH, kerncred, &resid, p) != 0) {
IOFree(readChunk, chunkSize);
return false;
}
SHA1Update(&sha1_ctx, readChunk, readSize);
}
// Free |readChunk|
IOFree(readChunk, chunkSize);
// Finalize the SHA-1 into |buf|
char buf[MAX_SHA1_LEN];
SHA1Final(buf, &sha1_ctx);
// Convert the binary SHA into a hex digest string
for (int i = 0; i < MAX_SHA1_LEN; i++) {
snprintf(out + (2*i), 3, "%02x", (unsigned char)buf[i]);
}
return true;
}
uint64_t SantaDecisionManager::GetVnodeIDForVnode(const vfs_context_t context,
const vnode_t vp) {
struct vnode_attr vap;
@@ -387,6 +311,7 @@ kern_return_t SantaDecisionManager::StopListener() {
ClearCache();
LOGD("Vnode listener stopped.");
LOGD("Process listener stopped.");
return kIOReturnSuccess;
}
@@ -395,13 +320,9 @@ kern_return_t SantaDecisionManager::StopListener() {
#pragma mark Kauth Callbacks
extern int process_scope_callback(kauth_cred_t credential,
void *idata,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3) {
extern "C" int process_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) {
if (idata == NULL) {
LOGE("Process callback established without valid decision manager.");
return KAUTH_RESULT_ALLOW;
@@ -409,7 +330,7 @@ extern int process_scope_callback(kauth_cred_t credential,
SantaDecisionManager *sdm = OSDynamicCast(
SantaDecisionManager, reinterpret_cast<OSObject *>(idata));
// Note: this prevents a debugger from attaching to an existing santad
// NOTE: this prevents a debugger from attaching to an existing santad
// process but doesn't prevent starting santad under a debugger. This check
// is only here to try and prevent the user from deadlocking their machine
// by attaching a debugger, so if they work around it and end up deadlocking,
@@ -424,14 +345,9 @@ extern int process_scope_callback(kauth_cred_t credential,
return KAUTH_RESULT_ALLOW;
}
extern int vnode_scope_callback(kauth_cred_t credential,
void *idata,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3) {
extern "C" int vnode_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) {
// The default action is to defer
int returnResult = KAUTH_RESULT_DEFER;
@@ -449,16 +365,20 @@ extern int vnode_scope_callback(kauth_cred_t credential,
vtype vt = vnode_vtype(vnode);
if (vt != VREG) return returnResult;
// Don't operate on ACCESS events, as they're advisory
if (action & KAUTH_VNODE_ACCESS) return returnResult;
// Filter for only WRITE_DATA actions
if (action & KAUTH_VNODE_WRITE_DATA || action & KAUTH_VNODE_APPEND_DATA) {
if (action & KAUTH_VNODE_WRITE_DATA ||
action & KAUTH_VNODE_APPEND_DATA ||
action & KAUTH_VNODE_DELETE) {
char vnode_id_str[MAX_VNODE_ID_STR];
snprintf(vnode_id_str, MAX_VNODE_ID_STR, "%llu",
sdm->GetVnodeIDForVnode(vfs_context, vnode));
// If an execution request is pending, deny write
if (sdm->GetFromCache(vnode_id_str) == ACTION_REQUEST_CHECKBW) {
LOGD("Denying write due to pending execution: %s", vnode_id_str);
*(reinterpret_cast<int *>(arg3)) = EACCES;
return KAUTH_RESULT_DENY;
}

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
#include <IOKit/IOLib.h>
#include <IOKit/IOSharedDataQueue.h>
#include <libkern/c++/OSDictionary.h>
#include <libkern/crypto/sha1.h>
#include <sys/kauth.h>
#include <sys/proc.h>
#include <sys/vnode.h>
@@ -27,30 +26,42 @@
#include "SNTKernelCommon.h"
#include "SNTLogging.h"
/// The maximum number of milliseconds a cached deny message should be
/// considered valid.
///
/// The maximum number of milliseconds a cached deny message should be
/// considered valid.
///
const uint64_t kMaxDenyCacheTimeMilliseconds = 500;
/// The maximum number of milliseconds a cached allow message should be
/// considered valid.
///
/// The maximum number of milliseconds a cached allow message should be
/// considered valid.
///
const uint64_t kMaxAllowCacheTimeMilliseconds = 1000 * 60 * 60 * 24;
/// While waiting for a response from the daemon, this is the number of
/// milliseconds to sleep for before checking the cache for a response.
///
/// While waiting for a response from the daemon, this is the number of
/// milliseconds to sleep for before checking the cache for a response.
///
const int kRequestLoopSleepMilliseconds = 10;
/// While waiting for a response from the daemon, this is the maximum number
/// of loops to wait before sending the request again.
///
/// While waiting for a response from the daemon, this is the maximum number
/// of loops to wait before sending the request again.
///
const int kMaxRequestLoops = 50;
/// Maximum number of entries in the in-kernel cache.
///
/// Maximum number of entries in the in-kernel cache.
///
const int kMaxCacheSize = 10000;
/// SantaDecisionManager is responsible for intercepting Vnode execute actions
/// and responding to the request appropriately.
///
/// Documentation on the Kauth parts can be found here:
/// https://developer.apple.com/library/mac/technotes/tn2127/_index.html
/// SantaDecisionManager is responsible for intercepting Vnode execute actions
/// and responding to the request appropriately.
///
/// Documentation on the Kauth parts can be found here:
/// https://developer.apple.com/library/mac/technotes/tn2127/_index.html
///
class SantaDecisionManager : public OSObject {
OSDeclareDefaultStructors(SantaDecisionManager);
@@ -70,17 +81,11 @@ class SantaDecisionManager : public OSObject {
const vfs_context_t vfs_context,
const vnode_t vnode);
// Hash calculation
bool CalculateSHA1ForVnode(const kauth_cred_t credential,
const vfs_context_t context,
const vnode_t vnode,
char *out);
// Vnode ID string
uint64_t GetVnodeIDForVnode(const vfs_context_t context, const vnode_t vp);
// Cache management
bool AddToCache(const char *identifier,
void AddToCache(const char *identifier,
const santa_action_t decision,
const uint64_t microsecs);
void CacheCheck(const char *identifier);
@@ -119,38 +124,32 @@ class SantaDecisionManager : public OSObject {
kauth_listener_t process_listener_;
};
extern "C" {
/// The callback function for the Vnode scope
/// @param actor's credentials
/// @param data that was passed when the listener was registered
/// @param action that was requested
/// @param VFS context
/// @param Vnode being operated on
/// @param Parent Vnode. May be NULL.
/// @param Pointer to an errno-style error.
extern int vnode_scope_callback(kauth_cred_t credential,
void *idata,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3);
///
/// The kauth callback function for the Vnode scope
/// @param actor's credentials
/// @param data that was passed when the listener was registered
/// @param action that was requested
/// @param VFS context
/// @param Vnode being operated on
/// @param Parent Vnode. May be NULL.
/// @param Pointer to an errno-style error.
///
extern "C" int vnode_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
/// The callback function for the Process scope
/// @param actor's credentials
/// @param data that was passed when the listener was registered
/// @param action that was requested (KAUTH_PROCESS_{CANTRACE,CANSIGNAL})
/// @param target process
/// @param Pointer to an errno-style error.
/// @param unused
/// @param unused
extern int process_scope_callback(kauth_cred_t credential,
void *idata,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3);
} // extern C
///
/// The kauth callback function for the Process scope
/// @param actor's credentials
/// @param data that was passed when the listener was registered
/// @param action that was requested (KAUTH_PROCESS_{CANTRACE,CANSIGNAL})
/// @param target process
/// @param Pointer to an errno-style error.
/// @param unused
/// @param unused
///
extern "C" int process_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
#endif // SANTA__SANTA_DRIVER__SANTADECISIONMANAGER_H

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -21,7 +21,9 @@
#include "SantaDecisionManager.h"
#include "SNTLogging.h"
/// The driver class, which provides just the start/stop functions.
///
/// The driver class, which provides just the start/stop functions.
///
class com_google_SantaDriver : public IOService {
OSDeclareDefaultStructors(com_google_SantaDriver);

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -71,6 +71,7 @@ bool SantaDriverClient::terminate(IOOptionBits options) {
message.action = ACTION_REQUEST_SHUTDOWN;
message.userId = 0;
message.pid = 0;
message.ppid = 0;
message.vnode_id = 0;
fSDM->PostToQueue(message);

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@
#include <IOKit/IOSharedDataQueue.h>
#include <IOKit/IOLib.h>
#include <IOKit/IODataQueueShared.h>
#include <libkern/crypto/sha1.h>
#include <sys/kauth.h>
#include <sys/vnode.h>
#include <sys/proc.h>
@@ -32,13 +31,15 @@
// The maximum number of messages can be kept in the IODataQueue at any time.
const int kMaxQueueEvents = 64;
/// This class is instantiated by IOKit when a new client process attempts to
/// connect to the driver. Starting, stopping, handling connections, allocating
/// shared memory and establishing a data queue is handled here.
///
/// Documentation on how the IOUserClient parts of this code work can be found
/// here:
/// @link https://developer.apple.com/library/mac/samplecode/SimpleUserClient/Listings/User_Client_Info_txt.html
/// This class is instantiated by IOKit when a new client process attempts to
/// connect to the driver. Starting, stopping, handling connections, allocating
/// shared memory and establishing a data queue is handled here.
///
/// Documentation on how the IOUserClient parts of this code work can be found
/// here:
/// @link https://developer.apple.com/library/mac/samplecode/SimpleUserClient/Listings/User_Client_Info_txt.html
///
class com_google_SantaDriverClient : public IOUserClient {
OSDeclareDefaultStructors(com_google_SantaDriverClient);

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -19,8 +19,10 @@
#include "SNTKernelCommon.h"
/// An OSObject wrapper around a @c santa_action_t and a time.
/// Only OSObject subclasses can be inserted into an OSDictionary.
///
/// An OSObject wrapper around a @c santa_action_t and a time.
/// Only OSObject subclasses can be inserted into an OSDictionary.
///
class SantaMessage : public OSObject {
OSDeclareDefaultStructors(SantaMessage)

View File

@@ -2,18 +2,18 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.google.santactl</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>NSHumanReadableCopyright</key>
<string>Google, Inc.</string>
<key>CFBundleIdentifier</key>
<string>com.google.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleShortVersionString</key>
<string>0.7</string>
<key>CFBundleSignature</key>
<string>????</string>
<string>TO.BE.FILLED</string>
<key>CFBundleVersion</key>
<string>0.7</string>
<string>TO.BE.FILLED</string>
<key>CSFlags</key>
<string>kill</string>
</dict>

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,63 +14,85 @@
@class SNTXPCConnection;
/// Protocol that each command must adhere to.
///
/// Protocol that each command must adhere to.
///
@protocol SNTCommand <NSObject>
/// Return YES if command requires root.
///
/// @return YES if command requires root.
///
+ (BOOL)requiresRoot;
/// A small summary of the command, to be printed with the list of available commands
///
/// @return YES if command requires connection to santad.
///
+ (BOOL)requiresDaemonConn;
///
/// A small summary of the command, to be printed with the list of available commands
///
+ (NSString *)shortHelpText;
/// A longer description of the command when the user runs "santactl help x"
///
/// A longer description of the command when the user runs <tt>santactl help x</tt>
///
+ (NSString *)longHelpText;
@optional
/// Either of the following two methods needs to be implemented
/// Called when the user is running the command
/// @param arguments an array of arguments passed in
/// @note This method (or one of the methods it calls) is responsible for calling exit().
+ (void)runWithArguments:(NSArray *)arguments;
/// Called when the user is running the command
/// @param arguments an array of arguments passed in
/// @param connection to santad. Will be nil if connection failed.
/// @note This method (or one of the methods it calls) is responsible for calling exit().
///
/// Called when the user is running the command
/// @param arguments an array of arguments passed in
/// @param daemonConn connection to santad. Will be nil if connection failed or
/// if @c requiresDaemonConn is @c NO
///
/// @note This method (or one of the methods it calls) is responsible for calling exit().
///
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn;
@end
/// Responsible for maintaining the list of available commands by name, printing their help text
/// when requested and launching them when requested. All of the methods in this class are
/// class methods because the @c registerCommand:named: method is called by the @c +load method
/// of each command class and so we cannot rely on its instantiation.
///
/// Responsible for maintaining the list of available commands by name, printing their help text
/// when requested and launching them when requested. All of the methods in this class are
/// class methods because the @c registerCommand:named: method is called by the @c +load method
/// of each command class and so we cannot rely on its instantiation.
///
@interface SNTCommandController : NSObject
/// Register a new command with the specified name. Do not use this directly, use the
/// @c REGISTER_COMMAND_NAME macro instead.
///
/// Register a new command with the specified name. Do not use this directly, use the
/// @c REGISTER_COMMAND_NAME macro instead.
///
+ (void)registerCommand:(Class<SNTCommand>)command named:(NSString *)name;
/// Returns a usage string listing all of the available commands
///
/// @return a usage string listing all of the available commands
///
+ (NSString *)usage;
/// Returns the descriptive text for the given command, if it exists
///
/// @return the descriptive text for the given command, if it exists
///
+ (NSString *)helpForCommandWithName:(NSString *)command;
/// Returns YES if @c commandName exists.
///
/// @return YES if @c commandName exists.
///
+ (BOOL)hasCommandWithName:(NSString *)commandName;
/// Runs the given command with the given arguments.
/// @c commandName the name of a previously-registered command
/// @c arguments an array of arguments to pass to the command
/// @return an integer return code to exit with.
+ (int)runCommandWithName:(NSString *)commandName arguments:(NSArray *)arguments;
///
/// Runs the given command with the given arguments.
///
/// @param commandName the name of a previously-registered command
/// @param arguments an array of arguments to pass to the command
///
+ (void)runCommandWithName:(NSString *)commandName arguments:(NSArray *)arguments;
@end
/// This macro registers a given class as a command with the name passed in @c a (which must be an
/// NSString). Must be placed just inside the implementation of the class, ideally at the top.
/// The class that uses this macro must implement the SNTCommand protcol.
///
/// This macro registers a given class as a command with the name passed in @c a (which must be an
/// NSString). Must be placed just inside the implementation of the class, ideally at the top.
/// The class that uses this macro must implement the @c SNTCommand protcol.
///
#define REGISTER_COMMAND_NAME(a) \
+ (void)load { [SNTCommandController registerCommand:[self class] named:a]; }

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -48,6 +48,7 @@ static NSMutableDictionary *registeredCommands;
[cmdName UTF8String], [cmd shortHelpText]];
}
[helpText appendFormat:@"\nSee 'santactl help <command>' to read about a specific subcommand."];
return helpText;
}
@@ -71,62 +72,41 @@ static NSMutableDictionary *registeredCommands;
options:NSXPCConnectionPrivileged];
daemonConn.remoteInterface = [SNTXPCControlInterface controlInterface];
__block int connected = -1;
daemonConn.acceptedHandler = ^{
connected = 1;
};
daemonConn.rejectedHandler = ^{
connected = 0;
printf("The daemon rejected the connection\n");
exit(1);
};
daemonConn.invalidationHandler = ^{
connected = 0;
printf("An error occurred communicating with the daemon\n");
exit(1);
};
[daemonConn resume];
int idx = 10;
do {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
--idx;
} while (connected == -1 && idx > 0);
if (connected > 0) {
return daemonConn;
} else {
return nil;
}
return daemonConn;
}
+ (BOOL)hasCommandWithName:(NSString *)commandName {
return ([registeredCommands objectForKey:commandName] != nil);
}
+ (int)runCommandWithName:(NSString *)commandName arguments:(NSArray *)arguments {
+ (void)runCommandWithName:(NSString *)commandName arguments:(NSArray *)arguments {
Class<SNTCommand> command = registeredCommands[commandName];
if (command) {
if ([command requiresRoot] && getuid() != 0) {
printf("The command '%s' requires root privileges.\n", [commandName UTF8String]);
return 2;
}
if ([(id)command respondsToSelector:@selector(runWithArguments:daemonConnection:)]) {
[command runWithArguments:arguments daemonConnection:[self connectToDaemon]];
} else if ([(id)command respondsToSelector:@selector(runWithArguments:)]) {
[command runWithArguments:arguments];
} else {
printf("The command '%s' has not been implemented correctly.\n", [commandName UTF8String]);
}
// The command is responsible for quitting.
[[NSRunLoop mainRunLoop] run];
if ([command requiresRoot] && getuid() != 0) {
printf("The command '%s' requires root privileges.\n", [commandName UTF8String]);
exit(2);
}
return 128;
SNTXPCConnection *daemonConn;
if ([command requiresDaemonConn]) {
daemonConn = [self connectToDaemon];
}
[command runWithArguments:arguments daemonConnection:daemonConn];
// The command is responsible for quitting.
[[NSRunLoop mainRunLoop] run];
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,9 +16,9 @@
#include "SNTLogging.h"
#import "SNTBinaryInfo.h"
#import "SNTCertificate.h"
#import "SNTCodesignChecker.h"
#import "SNTFileInfo.h"
@interface SNTCommandBinaryInfo : NSObject<SNTCommand>
@end
@@ -31,16 +31,20 @@ REGISTER_COMMAND_NAME(@"binaryinfo");
return NO;
}
+ (BOOL)requiresDaemonConn {
return NO;
}
+ (NSString *)shortHelpText {
return @"Prints information about the given binary.";
}
+ (NSString *)longHelpText {
return (@"The details provided will be the same ones Santa uses to make a decision about binaries"
@"This includes SHA-1, code signing information and the type of binary");
@"This includes SHA-1, SHA-256, code signing information and the type of binary");
}
+ (void)runWithArguments:(NSArray *)arguments {
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
NSString *filePath = [arguments firstObject];
if (!filePath) {
@@ -48,36 +52,22 @@ REGISTER_COMMAND_NAME(@"binaryinfo");
exit(1);
}
BOOL directory;
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&directory]) {
LOGI(@"File does not exist");
SNTFileInfo *fileInfo = [[SNTFileInfo alloc] initWithPath:filePath];
if (!fileInfo) {
LOGI(@"Invalid file");
exit(1);
}
if (directory) {
LOGI(@"Not a regular file");
exit(1);
}
// Convert to absolute, standardized path
filePath = [filePath stringByStandardizingPath];
if (![filePath isAbsolutePath]) {
NSString *cwd = [[NSFileManager defaultManager] currentDirectoryPath];
filePath = [cwd stringByAppendingPathComponent:filePath];
}
LOGI(@"Info for file: %@", filePath);
LOGI(@"Info for file: %@", [fileInfo path]);
LOGI(@"-----------------------------------------------------------");
LOGI(@"%-20s: %@", "SHA-1", [fileInfo SHA1]);
LOGI(@"%-20s: %@", "SHA-256", [fileInfo SHA256]);
SNTBinaryInfo *ftd = [[SNTBinaryInfo alloc] initWithPath:filePath];
LOGI(@"%-20s: %@", "SHA-1", [ftd SHA1]);
NSArray *archs = [ftd architectures];
NSArray *archs = [fileInfo architectures];
if (archs) {
LOGI(@"%-20s: %@ (%@)", "Type", [ftd machoType], [archs componentsJoinedByString:@", "]);
LOGI(@"%-20s: %@ (%@)", "Type", [fileInfo machoType], [archs componentsJoinedByString:@", "]);
} else {
LOGI(@"%-20s: %@", "Type", [ftd machoType]);
LOGI(@"%-20s: %@", "Type", [fileInfo machoType]);
}
SNTCodesignChecker *csc = [[SNTCodesignChecker alloc] initWithBinaryPath:filePath];
@@ -92,6 +82,7 @@ REGISTER_COMMAND_NAME(@"binaryinfo");
BOOL *stop) {
idx++; // index from 1
LOGI(@" %2lu. %-20s: %@", idx, "SHA-1", c.SHA1);
LOGI(@" %-20s: %@", "SHA-256", c.SHA256);
LOGI(@" %-20s: %@", "Common Name", c.commonName);
LOGI(@" %-20s: %@", "Organization", c.orgName);
LOGI(@" %-20s: %@", "Organizational Unit", c.orgUnit);

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -29,6 +29,10 @@ REGISTER_COMMAND_NAME(@"flushcache");
return YES;
}
+ (BOOL)requiresDaemonConn {
return YES;
}
+ (NSString *)shortHelpText {
return @"Flush the kernel cache";
}

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -14,13 +14,13 @@
#import "SNTCommandController.h"
/**
* santactl is a command-line utility for managing Santa.
* As it can be used for a number of distinct operations, its operation is split into different
* 'commands' which are expected to be the first argument to the binary. The main function below
* is simply responsible for either passing control to the specified command or printing a useful
* usage string.
**/
///
/// santactl is a command-line utility for managing Santa.
/// As it can be used for a number of distinct operations, its operation is split into different
/// 'commands' which are expected to be the first argument to the binary. The main function below
/// is simply responsible for either passing control to the specified command or printing a useful
/// usage string.
///
void print_usage() {
printf("Usage: santactl:\n%s\n", [[SNTCommandController usage] UTF8String]);
@@ -75,6 +75,6 @@ int main(int argc, const char *argv[]) {
return 128;
}
return [SNTCommandController runCommandWithName:commandName arguments:arguments];
[SNTCommandController runCommandWithName:commandName arguments:arguments];
}
}

View File

@@ -0,0 +1,166 @@
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTCommandController.h"
#include "SNTLogging.h"
#import "SNTCertificate.h"
#import "SNTCodesignChecker.h"
#import "SNTConfigurator.h"
#import "SNTDropRootPrivs.h"
#import "SNTFileInfo.h"
#import "SNTRule.h"
#import "SNTXPCConnection.h"
#import "SNTXPCControlInterface.h"
@interface SNTCommandRule : NSObject<SNTCommand>
@property SNTXPCConnection *daemonConn;
@end
@implementation SNTCommandRule
REGISTER_COMMAND_NAME(@"rule");
+ (BOOL)requiresRoot {
return YES;
}
+ (BOOL)requiresDaemonConn {
return YES;
}
+ (NSString *)shortHelpText {
return @"Adds a rule for the given binary or hash.";
}
+ (NSString *)longHelpText {
return (@"santactl rule {add|remove}\n"
@"--whitelist: add to whitelist\n"
@"--blacklist: add to blacklist\n"
@"--silent-blacklist: add to silent blacklist\n"
@"--message {message}: custom message\n"
@"--path {path}: path of binary to add\n"
@"--sha256 {sha256}: hash to add\n"
);
}
+ (void)runWithArguments:(NSArray *)arguments daemonConnection:(SNTXPCConnection *)daemonConn {
SNTConfigurator *config = [SNTConfigurator configurator];
// Ensure we have no privileges
if (!DropRootPrivileges()) {
LOGE(@"Failed to drop root privileges. Exiting.");
exit(1);
}
if ([config syncBaseURL] != nil) {
LOGE(@"SyncBaseURL is set, rules are managed centrally");
exit(1);
}
NSString *action = [arguments firstObject];
// add or remove
if (!action) {
LOGI(@"Missing action");
exit(1);
}
int state = RULESTATE_UNKNOWN;
if ([action compare:@"add" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
} else if ([action compare:@"remove" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
state = RULESTATE_REMOVE;
} else {
LOGI(@"Unknown action, expected add or remove");
exit(1);
}
NSString *customMsg = @"";
NSString *SHA256 = nil;
NSString *filePath = nil;
// parse arguments
for (int i=1; i < [arguments count] ; i++ ) {
NSString* argument = [arguments objectAtIndex:i];
if ([argument compare:@"--whitelist" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
state = RULESTATE_WHITELIST;
} else if ([argument compare:@"--blacklist" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
state = RULESTATE_BLACKLIST;
} else if ([argument compare:@"--silent-blacklist" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
state = RULESTATE_SILENT_BLACKLIST;
} else if ([argument compare:@"--message" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
if (++i > ([arguments count])) {
LOGI(@"No message specified");
}
customMsg = [arguments objectAtIndex:i];
} else if ([argument compare:@"--path" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
if (++i > ([arguments count])) {
LOGI(@"No path specified");
}
filePath = [arguments objectAtIndex:i];
} else if ([argument compare:@"--sha256" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
if (++i > ([arguments count])) {
LOGI(@"No SHA-256 specified");
}
SHA256 = [arguments objectAtIndex:i];
} else {
LOGI(@"Unknown argument %@", argument);
exit(1);
}
}
if (state == RULESTATE_UNKNOWN) {
LOGI(@"No state specified");
exit(1);
}
if (filePath) {
SNTFileInfo *fileInfo = [[SNTFileInfo alloc] initWithPath:filePath];
if (!fileInfo) {
LOGI(@"Not a regular file or executable bundle");
exit(1);
}
SHA256 = [fileInfo SHA256];
} else if (SHA256) {
} else {
LOGI(@"No SHA-256 or binary specified");
exit(1);
}
SNTRule *newRule = [[SNTRule alloc] init];
newRule.shasum = SHA256;
newRule.state = state;
newRule.type = RULETYPE_BINARY;
newRule.customMsg = customMsg;
[[daemonConn remoteObjectProxy] databaseRuleAddRule:newRule withReply:^{
if (state == RULESTATE_REMOVE) {
LOGI(@"Removed rule for SHA-256: %@", [newRule shasum]);
} else {
LOGI(@"Added rule for SHA-256: %@", [newRule shasum]);
}
exit(0);
}];
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
#include <IOKit/kext/KextManager.h>
#import "SNTBinaryInfo.h"
#import "SNTFileInfo.h"
#import "SNTKernelCommon.h"
#import "SNTLogging.h"
#import "SNTXPCConnection.h"
@@ -33,6 +33,10 @@ REGISTER_COMMAND_NAME(@"status");
return NO;
}
+ (BOOL)requiresDaemonConn {
return YES;
}
+ (NSString *)shortHelpText {
return @"Get status about Santa";
}
@@ -54,30 +58,34 @@ REGISTER_COMMAND_NAME(@"status");
LOGI(@"");
// Kext status
__block uint64_t cacheCount = -1;
[[daemonConn remoteObjectProxy] cacheCount:^(uint64_t count) {
cacheCount = count;
}];
do { usleep(5000); } while (cacheCount == -1);
LOGI(@">>> Kernel Info");
LOGI(@"%-30s | %d", "Kernel cache count", cacheCount);
LOGI(@"");
if (daemonConn) {
__block uint64_t cacheCount = -1;
[[daemonConn remoteObjectProxy] cacheCount:^(uint64_t count) {
cacheCount = count;
}];
do { usleep(5000); } while (cacheCount == -1);
LOGI(@">>> Kernel Info");
LOGI(@"%-30s | %d", "Kernel cache count", cacheCount);
LOGI(@"");
// Database counts
__block uint64_t eventCount = 1, binaryRuleCount = -1, certRuleCount = -1;
[[daemonConn remoteObjectProxy] databaseRuleCounts:^(uint64_t binary, uint64_t certificate) {
binaryRuleCount = binary;
certRuleCount = certificate;
}];
[[daemonConn remoteObjectProxy] databaseEventCount:^(uint64_t count) {
eventCount = count;
}];
do { usleep(5000); } while (eventCount == -1 || binaryRuleCount == -1 || certRuleCount == -1);
LOGI(@">>> Database Info");
LOGI(@"%-30s | %d", "Binary Rules", binaryRuleCount);
LOGI(@"%-30s | %d", "Certificate Rules", certRuleCount);
LOGI(@"%-30s | %d", "Events Pending Upload", eventCount);
LOGI(@"");
// Database counts
__block uint64_t eventCount = 1, binaryRuleCount = -1, certRuleCount = -1;
[[daemonConn remoteObjectProxy] databaseRuleCounts:^(uint64_t binary, uint64_t certificate) {
binaryRuleCount = binary;
certRuleCount = certificate;
}];
[[daemonConn remoteObjectProxy] databaseEventCount:^(uint64_t count) {
eventCount = count;
}];
do { usleep(5000); } while (eventCount == -1 || binaryRuleCount == -1 || certRuleCount == -1);
LOGI(@">>> Database Info");
LOGI(@"%-30s | %d", "Binary Rules", binaryRuleCount);
LOGI(@"%-30s | %d", "Certificate Rules", certRuleCount);
LOGI(@"%-30s | %d", "Events Pending Upload", eventCount);
LOGI(@"");
} else {
LOGI(@">>> santad is not running, cannot provide any more information.");
}
exit(0);
}
@@ -91,8 +99,8 @@ REGISTER_COMMAND_NAME(@"status");
return loadedKexts[@(USERCLIENT_ID)][@"CFBundleVersion"];
}
SNTBinaryInfo *driverInfo =
[[SNTBinaryInfo alloc] initWithPath:@"/System/Library/Extensions/santa-driver.kext"];
SNTFileInfo *driverInfo =
[[SNTFileInfo alloc] initWithPath:@"/Library/Extensions/santa-driver.kext"];
if (driverInfo) {
return [driverInfo.bundleVersion stringByAppendingString:@" (unloaded)"];
}
@@ -101,13 +109,13 @@ REGISTER_COMMAND_NAME(@"status");
}
+ (NSString *)daemonVersion {
SNTBinaryInfo *daemonInfo = [[SNTBinaryInfo alloc] initWithPath:@"/usr/libexec/santad"];
SNTFileInfo *daemonInfo = [[SNTFileInfo alloc] initWithPath:@"/usr/libexec/santad"];
return daemonInfo.bundleVersion;
}
+ (NSString *)guiVersion {
SNTBinaryInfo *guiInfo =
[[SNTBinaryInfo alloc] initWithPath:@"/Applications/Santa.app/Contents/MacOS/Santa"];
SNTFileInfo *guiInfo =
[[SNTFileInfo alloc] initWithPath:@"/Applications/Santa.app/Contents/MacOS/Santa"];
return guiInfo.bundleVersion;
}

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,40 +12,65 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// An authenticating NSURLSession, which can do both pinned verification of the SSL server
/// and handle client certificate authentication from the keychain.
///
/// An authenticating NSURLSession, which can do both pinned verification of the SSL server
/// and handle client certificate authentication from the keychain.
///
@interface SNTAuthenticatingURLSession : NSObject<NSURLSessionDelegate>
/// The underlying session. Pass this session to NSURLRequest methods.
///
/// The underlying session. Pass this session to NSURLRequest methods.
///
@property(readonly) NSURLSession *session;
/// If set, this is the user-agent to send with requests, otherwise remains the default
/// CFNetwork-based name.
///
/// If set, this is the user-agent to send with requests, otherwise remains the default
/// CFNetwork-based name.
///
@property(nonatomic) NSString *userAgent;
/// If set, the server that we connect to _must_ match this string. Redirects to other
/// hosts will not be allowed.
///
/// If set, the server that we connect to _must_ match this string. Redirects to other
/// hosts will not be allowed.
///
@property(nonatomic) NSString *serverHostname;
/// This should be PEM data containing one or more certificates to use to verify the server's
/// certificate chain. This will override the trusted roots in the System Roots.
///
/// This should be PEM data containing one or more certificates to use to verify the server's
/// certificate chain. This will override the trusted roots in the System Roots.
///
@property(nonatomic) NSData *serverRootsPemData;
/// If set and client certificate authentication is needed, will search the keychain for a
/// certificate matching this common name and use that for authentication
/// @note: Not case sensitive
/// @note: If multiple matching certificates are found, the first one is used.
/// @note: If this property is not set and neither is |clientCertIssuerCn|, the allowed issuers
/// provided by the server will be used to find a matching certificate.
///
/// If set and client certificate authentication is needed, the pkcs#12 file will be loaded
///
@property(nonatomic) NSString *clientCertFile;
///
/// If set and client certificate authentication is needed, the password being used for
/// loading the clientCertFile
///
@property(nonatomic) NSString *clientCertPassword;
///
/// If set and client certificate authentication is needed, will search the keychain for a
/// certificate matching this common name and use that for authentication
/// @note Not case sensitive
/// @note If multiple matching certificates are found, the first one is used.
/// @note If this property is not set and neither is |clientCertIssuerCn|, the allowed issuers
/// provided by the server will be used to find a matching certificate.
///
@property(nonatomic) NSString *clientCertCommonName;
/// If set and client certificate authentication is needed, will search the keychain for a
/// certificate issued by an issuer with this name and use that for authentication.
///
/// @note: Not case sensitive
/// @note: If multiple matching certificates are found, the first one is used.
/// @note: If this property is not set and neither is |clientCertCommonName|, the allowed issuers
/// provided by the server will be used to find a matching certificate.
/// If set and client certificate authentication is needed, will search the keychain for a
/// certificate issued by an issuer with this name and use that for authentication.
///
/// @note Not case sensitive
/// @note If multiple matching certificates are found, the first one is used.
/// @note If this property is not set and neither is |clientCertCommonName|, the allowed issuers
/// provided by the server will be used to find a matching certificate.
///
@property(nonatomic) NSString *clientCertIssuerCn;
/// Designated initializer

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -75,19 +75,20 @@
}
if (!protectionSpace.receivesCredentialSecurely) {
LOGD(@"Protection Space: secure authentication or protocol cannot be established");
LOGD(@"Protection Space: secure authentication or protocol cannot be established.");
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
return;
}
NSString *authMethod = [protectionSpace authenticationMethod];
if (authMethod == NSURLAuthenticationMethodClientCertificate && NO) {
if (authMethod == NSURLAuthenticationMethodClientCertificate) {
NSURLCredential *cred = [self clientCredentialForProtectionSpace:protectionSpace];
if (cred) {
completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
return;
} else {
LOGE(@"Server asked for client authentication but no usable client certificate found.");
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
return;
}
@@ -97,6 +98,7 @@
completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
return;
} else {
LOGE(@"Server asked for client authentication but no usable client certificate found.");
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
return;
}
@@ -107,104 +109,134 @@
#pragma mark Private Helpers for URLSession:didReceiveChallenge:completionHandler:
/// Handles the process of locating a valid client certificate for authentication.
/// Operates in one of three modes, depending on the configuration in config.plist
///
/// Mode 1: if syncClientAuthCertificateCn is set, look for an identity in the keychain with a
/// matching common name and return it.
/// Mode 2: if syncClientAuthCertificateIssuer is set, look for an identity in the keychain with a
/// matching issuer common name and return it.
/// Mode 3: use the list of issuer details sent down by the server to find an identity in the
/// keychain.
/// Handles the process of locating a valid client certificate for authentication.
/// Operates in one of four modes, depending on the configuration in config.plist
///
/// Mode 1: if syncClientAuthCertificateFile is set, use the identity in the pkcs file
/// Mode 2: if syncClientAuthCertificateCn is set, look for an identity in the keychain with a
/// matching common name and return it.
/// Mode 3: if syncClientAuthCertificateIssuer is set, look for an identity in the keychain with a
/// matching issuer common name and return it.
/// Mode 4: use the list of issuer details sent down by the server to find an identity in the
/// keychain.
///
/// If a valid identity cannot be found, returns nil.
///
/// If a valid identity cannot be found, returns nil.
- (NSURLCredential *)clientCredentialForProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
__block OSStatus err = errSecSuccess;
CFArrayRef cfIdentities = NULL;
err = SecItemCopyMatching((__bridge CFDictionaryRef)@{
(id)kSecClass : (id)kSecClassIdentity,
(id)kSecReturnRef : @YES,
(id)kSecMatchLimit : (id)kSecMatchLimitAll }, (CFTypeRef *)&cfIdentities);
__block SecIdentityRef foundIdentity;
if (err != noErr) {
LOGD(@"Client Trust: Failed to load client identities, SecItemCopyMatching returned: %d",
(int)err);
return nil;
}
NSArray *identities = CFBridgingRelease(cfIdentities);
__block SecIdentityRef _foundIdentity;
// Manually iterate through available identities to find one with an allowed issuer.
[identities enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
SecIdentityRef identityRef = (__bridge SecIdentityRef)obj;
SecCertificateRef certificate = NULL;
err = SecIdentityCopyCertificate(identityRef, &certificate);
if (err != errSecSuccess) {
LOGD(@"Client Trust: Failed to read certificate data: %d. Skipping identity", (int)err);
return;
if (self.clientCertFile) {
NSError *error;
NSData *data = [NSData dataWithContentsOfFile:self.clientCertFile options:0 error:&error];
if (error) {
LOGE(@"Client Trust: Couldn't open client certificate %@: %@",
self.clientCertFile,
[error localizedDescription]);
return nil;
}
SNTCertificate *clientCert = [[SNTCertificate alloc] initWithSecCertificateRef:certificate];
CFRelease(certificate);
NSDictionary *options = (self.clientCertPassword ?
@{(__bridge id)kSecImportExportPassphrase: self.clientCertPassword} :
@{});
// Switch identity finding method depending on config
if (self.clientCertCommonName) {
if ([clientCert.commonName compare:self.clientCertCommonName
options:NSCaseInsensitiveSearch]) {
LOGD(@"Client Trust: Valid client identity %@", clientCert);
_foundIdentity = identityRef;
CFRetain(_foundIdentity);
*stop = YES;
return; // return from enumeration block
CFArrayRef cfIdentities;
err = SecPKCS12Import(
(__bridge CFDataRef)data, (__bridge CFDictionaryRef)options, &cfIdentities);
NSArray *identities = CFBridgingRelease(cfIdentities);
if (err != errSecSuccess) {
LOGE(@"Client Trust: Couldn't load client certificate %@: %d", self.clientCertFile, err);
return nil;
}
foundIdentity = (__bridge SecIdentityRef)identities[0][(__bridge id)kSecImportItemIdentity];
} else {
CFArrayRef cfIdentities;
err = SecItemCopyMatching((__bridge CFDictionaryRef)@{
(id)kSecClass : (id)kSecClassIdentity,
(id)kSecReturnRef : @YES,
(id)kSecMatchLimit : (id)kSecMatchLimitAll }, (CFTypeRef *)&cfIdentities);
if (err != errSecSuccess) {
LOGD(@"Client Trust: Failed to load client identities, SecItemCopyMatching returned: %d",
(int)err);
return nil;
}
NSArray *identities = CFBridgingRelease(cfIdentities);
// Manually iterate through available identities to find one with an allowed issuer.
[identities enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
SecIdentityRef identityRef = (__bridge SecIdentityRef)obj;
SecCertificateRef certificate = NULL;
err = SecIdentityCopyCertificate(identityRef, &certificate);
if (err != errSecSuccess) {
LOGD(@"Client Trust: Failed to read certificate data: %d. Skipping identity.", (int)err);
return;
}
} else if (self.clientCertIssuerCn) {
if ([clientCert.issuerCommonName compare:self.clientCertIssuerCn
options:NSCaseInsensitiveSearch]) {
LOGD(@"Client Trust: Valid client identity %@", clientCert);
_foundIdentity = identityRef;
CFRetain(_foundIdentity);
*stop = YES;
return; // return from enumeration block
}
} else {
for (NSData *allowedIssuer in protectionSpace.distinguishedNames) {
SNTDERDecoder *decoder = [[SNTDERDecoder alloc] initWithData:allowedIssuer];
if (!decoder) continue;
if ([clientCert.issuerCommonName isEqual:decoder.commonName] &&
[clientCert.issuerCountryName isEqual:decoder.countryName] &&
[clientCert.issuerOrgName isEqual:decoder.organizationName] &&
[clientCert.issuerOrgUnit isEqual:decoder.organizationalUnit]) {
LOGD(@"Client Trust: Valid client identity %@", clientCert);
_foundIdentity = identityRef;
CFRetain(_foundIdentity);
SNTCertificate *clientCert = [[SNTCertificate alloc] initWithSecCertificateRef:certificate];
CFRelease(certificate);
// Switch identity finding method depending on config
if (self.clientCertCommonName && clientCert.commonName) {
if ([clientCert.commonName compare:self.clientCertCommonName
options:NSCaseInsensitiveSearch] == NSOrderedSame) {
foundIdentity = identityRef;
*stop = YES;
return; // return from enumeration block
}
}
}
}];
} else if (self.clientCertIssuerCn && clientCert.issuerCommonName) {
if ([clientCert.issuerCommonName compare:self.clientCertIssuerCn
options:NSCaseInsensitiveSearch] == NSOrderedSame) {
foundIdentity = identityRef;
*stop = YES;
return; // return from enumeration block
}
} else {
for (NSData *allowedIssuer in protectionSpace.distinguishedNames) {
SNTDERDecoder *decoder = [[SNTDERDecoder alloc] initWithData:allowedIssuer];
if (!decoder) continue;
if ([clientCert.issuerCommonName isEqual:decoder.commonName] &&
[clientCert.issuerCountryName isEqual:decoder.countryName] &&
[clientCert.issuerOrgName isEqual:decoder.organizationName] &&
[clientCert.issuerOrgUnit isEqual:decoder.organizationalUnit]) {
if (_foundIdentity == NULL) {
return nil;
foundIdentity = identityRef;
*stop = YES;
return; // return from enumeration block
}
}
}
}];
}
return [NSURLCredential credentialWithIdentity:_foundIdentity
certificates:nil
persistence:NSURLCredentialPersistenceForSession];
if (foundIdentity) {
LOGD(@"Client Trust: Valid client identity %@.", foundIdentity);
return [NSURLCredential credentialWithIdentity:foundIdentity
certificates:nil
persistence:NSURLCredentialPersistenceForSession];
} else {
LOGD(@"Client Trust: No valid identity found.");
return nil;
}
}
/// Handles the process of evaluating the server's certificate chain.
/// Operates in one of three modes, depending on the configuration in config.plist
///
/// Mode 1: if syncServerAuthRootsData is set, evaluates the server's certificate chain contains
/// one of the certificates in the PEM data in the config plist.
/// Mode 2: if syncServerAuthRootsFile is set, evaluates the server's certificate chain contains
/// one of the certificates in the PEM data in the file specified.
/// Mode 3: evaluates the server's certificate chain is trusted by the keychain.
/// Handles the process of evaluating the server's certificate chain.
/// Operates in one of three modes, depending on the configuration in config.plist
///
/// Mode 1: if syncServerAuthRootsData is set, evaluates the server's certificate chain contains
/// one of the certificates in the PEM data in the config plist.
/// Mode 2: if syncServerAuthRootsFile is set, evaluates the server's certificate chain contains
/// one of the certificates in the PEM data in the file specified.
/// Mode 3: evaluates the server's certificate chain is trusted by the keychain.
///
/// If the server's certificate chain does not evaluate for any reason, returns nil.
///
/// If the server's certificate chain does not evaluate for any reason, returns nil.
- (NSURLCredential *)serverCredentialForProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
SecTrustRef serverTrust = protectionSpace.serverTrust;
if (serverTrust == NULL) {
@@ -228,7 +260,7 @@
// Set this array of certs as the anchors to trust.
err = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)certRefs);
if (err != errSecSuccess) {
LOGE(@"Server Trust: Could not set anchor certificates");
LOGE(@"Server Trust: Could not set anchor certificates: %d", err);
return nil;
}
}
@@ -237,7 +269,7 @@
SecTrustResultType result = kSecTrustResultInvalid;
err = SecTrustEvaluate(serverTrust, &result);
if (err != errSecSuccess) {
LOGE(@"Server Trust: Unable to evaluate certificate chain for server");
LOGE(@"Server Trust: Unable to evaluate certificate chain for server: %d", err);
return nil;
}

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -42,6 +42,10 @@ REGISTER_COMMAND_NAME(@"sync");
return NO;
}
+ (BOOL)requiresDaemonConn {
return YES;
}
+ (NSString *)shortHelpText {
return @"Synchronizes Santa with the server";
}
@@ -77,14 +81,28 @@ REGISTER_COMMAND_NAME(@"sync");
// Configure server auth
if ([config syncServerAuthRootsFile]) {
NSData *rootsData = [NSData dataWithContentsOfFile:[config syncServerAuthRootsFile]];
NSError *error = nil;
NSData *rootsData = [NSData dataWithContentsOfFile:[config syncServerAuthRootsFile]
options:0
error:&error];
authURLSession.serverRootsPemData = rootsData;
if (!rootsData) {
LOGE(@"Couldn't open server root certificate file %@ with error: %@.",
[config syncServerAuthRootsFile],
[error localizedDescription]);
exit(1);
}
} else if ([config syncServerAuthRootsData]) {
authURLSession.serverRootsPemData = [config syncServerAuthRootsData];
}
// Configure client auth
if ([config syncClientAuthCertificateCn]) {
if ([config syncClientAuthCertificateFile]) {
authURLSession.clientCertFile = [config syncClientAuthCertificateFile];
authURLSession.clientCertPassword = [config syncClientAuthCertificatePassword];
} else if ([config syncClientAuthCertificateCn]) {
authURLSession.clientCertCommonName = [config syncClientAuthCertificateCn];
} else if ([config syncClientAuthCertificateIssuer]) {
authURLSession.clientCertIssuerCn = [config syncClientAuthCertificateIssuer];
@@ -125,18 +143,18 @@ REGISTER_COMMAND_NAME(@"sync");
progress:self.progress
daemonConn:self.daemonConn
completionHandler:^(BOOL success) {
if (success) {
LOGI(@"Preflight complete");
if (self.progress.uploadLogURL) {
[self logUpload];
} else {
[self eventUpload];
}
} else {
LOGE(@"Preflight failed, aborting run");
exit(1);
}
}];
if (success) {
LOGI(@"Preflight complete");
if (self.progress.uploadLogURL) {
[self logUpload];
} else {
[self eventUpload];
}
} else {
LOGE(@"Preflight failed, aborting run");
exit(1);
}
}];
}
- (void)logUpload {
@@ -144,14 +162,14 @@ REGISTER_COMMAND_NAME(@"sync");
progress:self.progress
daemonConn:self.daemonConn
completionHandler:^(BOOL success) {
if (success) {
LOGI(@"Log upload complete");
[self eventUpload];
} else {
LOGE(@"Log upload failed, aborting run");
exit(1);
}
}];
if (success) {
LOGI(@"Log upload complete");
[self eventUpload];
} else {
LOGE(@"Log upload failed, aborting run");
exit(1);
}
}];
}
- (void)eventUpload {
@@ -159,30 +177,30 @@ REGISTER_COMMAND_NAME(@"sync");
progress:self.progress
daemonConn:self.daemonConn
completionHandler:^(BOOL success) {
if (success) {
LOGI(@"Event upload complete");
[self ruleDownload];
} else {
LOGE(@"Event upload failed, aborting run");
exit(1);
}
}];
if (success) {
LOGI(@"Event upload complete");
[self ruleDownload];
} else {
LOGE(@"Event upload failed, aborting run");
exit(1);
}
}];
}
- (void)eventUploadSingleEvent:(NSString *)sha1 {
[SNTCommandSyncEventUpload uploadSingleEventWithSHA1:sha1
session:self.session
progress:self.progress
daemonConn:self.daemonConn
completionHandler:^(BOOL success) {
if (success) {
LOGI(@"Event upload complete");
exit(0);
} else {
LOGW(@"Event upload failed");
exit(1);
}
}];
- (void)eventUploadSingleEvent:(NSString *)sha256 {
[SNTCommandSyncEventUpload uploadSingleEventWithSHA256:sha256
session:self.session
progress:self.progress
daemonConn:self.daemonConn
completionHandler:^(BOOL success) {
if (success) {
LOGI(@"Event upload complete");
exit(0);
} else {
LOGW(@"Event upload failed");
exit(1);
}
}];
}
- (void)ruleDownload {
@@ -190,14 +208,14 @@ REGISTER_COMMAND_NAME(@"sync");
progress:self.progress
daemonConn:self.daemonConn
completionHandler:^(BOOL success) {
if (success) {
LOGI(@"Rule download complete");
[self postflight];
} else {
LOGE(@"Rule download failed, aborting run");
exit(1);
}
}];
if (success) {
LOGI(@"Rule download complete");
[self postflight];
} else {
LOGE(@"Rule download failed, aborting run");
exit(1);
}
}];
}
- (void)postflight {
@@ -205,15 +223,15 @@ REGISTER_COMMAND_NAME(@"sync");
progress:self.progress
daemonConn:self.daemonConn
completionHandler:^(BOOL success) {
if (success) {
LOGI(@"Postflight complete");
LOGI(@"Sync completed successfully");
exit(0);
} else {
LOGE(@"Postflight failed");
exit(1);
}
}];
if (success) {
LOGI(@"Postflight complete");
LOGI(@"Sync completed successfully");
exit(0);
} else {
LOGE(@"Postflight failed");
exit(1);
}
}];
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -22,10 +22,10 @@
daemonConn:(SNTXPCConnection *)daemonConn
completionHandler:(void (^)(BOOL success))handler;
+ (void)uploadSingleEventWithSHA1:(NSString *)SHA1
session:(NSURLSession *)session
progress:(SNTCommandSyncStatus *)progress
daemonConn:(SNTXPCConnection *)daemonConn
completionHandler:(void (^)(BOOL success))handler;
+ (void)uploadSingleEventWithSHA256:(NSString *)SHA256
session:(NSURLSession *)session
progress:(SNTCommandSyncStatus *)progress
daemonConn:(SNTXPCConnection *)daemonConn
completionHandler:(void (^)(BOOL success))handler;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
#include "SNTLogging.h"
#import "SNTCertificate.h"
#import "SNTCommandSyncStatus.h"
#import "SNTStoredEvent.h"
#import "SNTXPCConnection.h"
@@ -44,14 +45,14 @@
}];
}
+ (void)uploadSingleEventWithSHA1:(NSString *)SHA1
session:(NSURLSession *)session
progress:(SNTCommandSyncStatus *)progress
daemonConn:(SNTXPCConnection *)daemonConn
completionHandler:(void (^)(BOOL success))handler {
+ (void)uploadSingleEventWithSHA256:(NSString *)SHA256
session:(NSURLSession *)session
progress:(SNTCommandSyncStatus *)progress
daemonConn:(SNTXPCConnection *)daemonConn
completionHandler:(void (^)(BOOL success))handler {
NSURL *url = [NSURL URLWithString:[@"eventupload/" stringByAppendingString:progress.machineID]
relativeToURL:progress.syncBaseURL];
[[daemonConn remoteObjectProxy] databaseEventForSHA1:SHA1 withReply:^(SNTStoredEvent *event) {
[[daemonConn remoteObjectProxy] databaseEventForSHA256:SHA256 withReply:^(SNTStoredEvent *event) {
if (!event) {
handler(YES);
return;
@@ -76,53 +77,25 @@
NSMutableArray *eventIds = [NSMutableArray arrayWithCapacity:events.count];
for (SNTStoredEvent *event in events) {
NSMutableDictionary *newEvent = [@{
@"file_sha1": event.fileSHA1,
@"file_path": [event.filePath stringByDeletingLastPathComponent],
@"file_name": [event.filePath lastPathComponent],
@"executing_user": event.executingUser,
@"execution_time": @([event.occurrenceDate timeIntervalSince1970]),
@"decision": @(event.decision),
@"logged_in_users": event.loggedInUsers,
@"current_sessions": event.currentSessions} mutableCopy];
if (event.fileBundleID) newEvent[@"file_bundle_id"] = event.fileBundleID;
if (event.fileBundleName) newEvent[@"file_bundle_name"] = event.fileBundleName;
if (event.fileBundleVersion) newEvent[@"file_bundle_version"] = event.fileBundleVersion;
if (event.fileBundleVersionString) {
newEvent[@"file_bundle_version_string"] = event.fileBundleVersionString;
}
if (event.certSHA1) newEvent[@"cert_sha1"] = event.certSHA1;
if (event.certCN) newEvent[@"cert_cn"] = event.certCN;
if (event.certOrg) newEvent[@"cert_org"] = event.certOrg;
if (event.certOU) newEvent[@"cert_ou"] = event.certOU;
if (event.certValidFromDate) {
newEvent[@"cert_valid_from"] = @([event.certValidFromDate timeIntervalSince1970]);
}
if (event.certValidUntilDate) {
newEvent[@"cert_valid_until"] = @([event.certValidUntilDate timeIntervalSince1970]);
}
[uploadEvents addObject:newEvent];
[uploadEvents addObject:[self dictionaryForEvent:event]];
[eventIds addObject:event.idx];
if (eventIds.count >= batchSize) break;
}
NSDictionary *uploadReq = @{@"events": uploadEvents};
NSDictionary *uploadReq = @{ @"events": uploadEvents };
NSData *requestBody;
@try {
requestBody = [NSJSONSerialization dataWithJSONObject:uploadReq options:0 error:nil];
} @catch (NSException *exception) {
LOGE(@"Failed to parse event into JSON");
LOGE(@"Failed to parse event(s) into JSON");
LOGD(@"Parsing error: %@", [exception reason]);
}
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:url];
[req setHTTPMethod:@"POST"];
[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[req setHTTPBody:requestBody];
[[session dataTaskWithRequest:req completionHandler:^(NSData *data,
@@ -138,7 +111,6 @@
NSArray *nextEvents = [events subarrayWithRange:NSMakeRange(eventIds.count,
events.count - eventIds.count)];
if (nextEvents.count == 0) {
handler(YES);
} else {
@@ -153,4 +125,42 @@
}] resume];
}
+ (NSDictionary *)dictionaryForEvent:(SNTStoredEvent *)event {
#define ADDKEY(dict, key, value) if (value) dict[key] = value
NSMutableDictionary *newEvent = [NSMutableDictionary dictionary];
ADDKEY(newEvent, @"file_sha256", event.fileSHA256);
ADDKEY(newEvent, @"file_path", [event.filePath stringByDeletingLastPathComponent]);
ADDKEY(newEvent, @"file_name", [event.filePath lastPathComponent]);
ADDKEY(newEvent, @"executing_user", event.executingUser);
ADDKEY(newEvent, @"execution_time", @([event.occurrenceDate timeIntervalSince1970]));
ADDKEY(newEvent, @"decision", @(event.decision));
ADDKEY(newEvent, @"logged_in_users", event.loggedInUsers);
ADDKEY(newEvent, @"current_sessions", event.currentSessions);
ADDKEY(newEvent, @"file_bundle_id", event.fileBundleID);
ADDKEY(newEvent, @"file_bundle_name", event.fileBundleName);
ADDKEY(newEvent, @"file_bundle_version", event.fileBundleVersion);
ADDKEY(newEvent, @"file_bundle_version_string", event.fileBundleVersionString);
NSMutableArray *signingChain = [NSMutableArray arrayWithCapacity:event.signingChain.count];
for (int i = 0; i < event.signingChain.count; i++) {
SNTCertificate *cert = [event.signingChain objectAtIndex:i];
NSMutableDictionary *certDict = [NSMutableDictionary dictionary];
ADDKEY(certDict, @"sha256", cert.SHA256);
ADDKEY(certDict, @"cn", cert.commonName);
ADDKEY(certDict, @"org", cert.orgName);
ADDKEY(certDict, @"ou", cert.orgUnit);
ADDKEY(certDict, @"valid_from", @([cert.validFrom timeIntervalSince1970]));
ADDKEY(certDict, @"valid_until", @([cert.validUntil timeIntervalSince1970]));
[signingChain addObject:certDict];
}
newEvent[@"signing_chain"] = signingChain;
return newEvent;
#undef ADDKEY
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -34,7 +34,8 @@
NSMutableDictionary *requestDict = [NSMutableDictionary dictionary];
requestDict[@"serial_no"] = [SNTSystemInfo serialNumber];
requestDict[@"hostname"] = [SNTSystemInfo shortHostname];
requestDict[@"santa_version"] = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
requestDict[@"santa_version"] =
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
requestDict[@"os_version"] = [SNTSystemInfo osVersion];
requestDict[@"os_build"] = [SNTSystemInfo osBuild];
requestDict[@"primary_user"] = progress.machineOwner;
@@ -44,6 +45,7 @@
error:nil];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:url];
[req setHTTPMethod:@"POST"];
[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[req setHTTPBody:requestBody];
[[session dataTaskWithRequest:req completionHandler:^(NSData *data,

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -44,18 +44,18 @@
daemonConn:(SNTXPCConnection *)daemonConn
completionHandler:(void (^)(BOOL success))handler {
NSDictionary *requestDict;
if (cursor) {
requestDict = @{@"cursor": cursor};
} else {
requestDict = @{};
NSDictionary *requestDict = (cursor ? @{ @"cursor": cursor } : @{});
if (!progress.downloadedRules) {
progress.downloadedRules = [NSMutableArray array];
}
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:url];
[req setHTTPBody:[NSJSONSerialization dataWithJSONObject:requestDict
options:0
error:nil]];
options:0
error:nil]];
[req setHTTPMethod:@"POST"];
[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[[session dataTaskWithRequest:req completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
@@ -64,19 +64,18 @@
handler(NO);
} else {
NSDictionary *resp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if (!resp) {
LOGE(@"Failed to decode server's response");
handler(NO);
}
NSArray *receivedRules = resp[@"rules"];
if (receivedRules.count == 0) {
handler(YES);
return;
}
NSMutableArray *rules = [[NSMutableArray alloc] initWithCapacity:receivedRules.count];
for (NSDictionary *rule in receivedRules) {
if (![rule isKindOfClass:[NSDictionary class]]) continue;
SNTRule *newRule = [[SNTRule alloc] init];
newRule.SHA1 = rule[@"sha1"];
newRule.shasum = rule[@"shasum"];
newRule.state = [rule[@"state"] intValue];
if (newRule.state <= RULESTATE_UNKNOWN || newRule.state >= RULESTATE_MAX) continue;
@@ -89,23 +88,22 @@
newRule.customMsg = customMsg;
}
[rules addObject:newRule];
[progress.downloadedRules addObject:newRule];
}
[[daemonConn remoteObjectProxy] databaseRuleAddRules:rules withReply:^{
LOGI(@"Downloaded %d rule(s)", rules.count);
if (resp[@"cursor"]) {
[self ruleDownloadWithCursor:resp[@"cursor"]
url:url
session:session
progress:progress
daemonConn:daemonConn
completionHandler:handler];
} else {
if (resp[@"cursor"]) {
[self ruleDownloadWithCursor:resp[@"cursor"]
url:url
session:session
progress:progress
daemonConn:daemonConn
completionHandler:handler];
} else {
[[daemonConn remoteObjectProxy] databaseRuleAddRules:progress.downloadedRules withReply:^{
LOGI(@"Added %d rule(s)", progress.downloadedRules.count);
handler(YES);
}
}];
}];
}
}
}] resume];
}

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -29,4 +29,7 @@
/// Log upload URL sent from server
@property NSURL *uploadLogURL;
/// Rules downloaded from server
@property NSMutableArray *downloadedRules;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,7 @@
///
/// This is a simple ASN.1 decoder that utilizes Apple's SecAsn1Decode
/// to parse the @c distinguishedNames property of NSURLProtectionSpace.
///
@interface SNTDERDecoder : NSObject
@property(readonly) NSString *commonName;
@@ -7,9 +9,13 @@
@property(readonly) NSString *organizationalUnit;
@property(readonly) NSString *countryName;
/// Designated initializer. Pass in one of the NSData objects in the
/// NSURLProtectionSpace.distinguishedNames array
/// Returns nil if decoding fails to find any expected objects
///
/// Designated initializer.
///
/// @param data one of the objects in the
/// NSURLProtectionSpace.distinguishedNames array
/// @return nil if decoding fails to find any expected objects
///
- (instancetype)initWithData:(NSData *)data;
@end

View File

@@ -2,17 +2,17 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.google.santad</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>NSHumanReadableCopyright</key>
<string>Google, Inc.</string>
<key>CFBundleIdentifier</key>
<string>com.google.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleShortVersionString</key>
<string>0.7</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.7</string>
<string>TO.BE.FILLED</string>
<key>CFBundleShortVersionString</key>
<string>TO.BE.FILLED</string>
</dict>
</plist>

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,10 +12,14 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// The main controller class for santad
///
/// The main controller class for santad
///
@interface SNTApplication : NSObject
/// Begins fielding requests from the driver
- (int)run;
///
/// Begins fielding requests from the driver
///
- (void)run;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -111,20 +111,19 @@
}
}
- (int)run {
- (void)run {
LOGI(@"Connected to driver, activating.");
dispatch_queue_t q = dispatch_queue_create("com.google.santad.driver_queue",
DISPATCH_QUEUE_CONCURRENT);
[self.driverManager listenWithBlock:^BOOL(santa_message_t message) {
[self.driverManager listenWithBlock:^(santa_message_t message) {
@autoreleasepool {
switch (message.action) {
case ACTION_REQUEST_SHUTDOWN: {
LOGI(@"Driver requested a shutdown");
// Sleep before exiting to give driver chance to ready itself
sleep(10);
return NO;
exit(0);
}
case ACTION_REQUEST_CHECKBW: {
// Validate the binary aynchronously on a concurrent queue so we don't
@@ -136,23 +135,20 @@
userName = @(user->pw_name);
}
[self.execController validateBinaryWithSHA1:@(message.sha1)
path:@(message.path)
[self.execController validateBinaryWithPath:@(message.path)
userName:userName
pid:@(message.pid)
vnodeId:message.vnode_id];
});
return YES;
break;
}
default: {
LOGE(@"Received request without an action");
return NO;
LOGE(@"Received request without a valid action: %d", message.action);
exit(1);
}
}
}
}];
return 0;
}
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,7 +16,9 @@
@class SNTDriverManager;
/// SNTDaemonControlController handles all of the RPCs from santactl
///
/// SNTDaemonControlController handles all of the RPCs from santactl
///
@interface SNTDaemonControlController : NSObject<SNTDaemonControlXPC>
@property SNTDriverManager *driverManager;

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -51,21 +51,28 @@
}
- (void)databaseRuleAddRule:(SNTRule *)rule withReply:(void (^)())reply {
[[SNTDatabaseController ruleTable] addRule:rule];
reply();
[self databaseRuleAddRules:@[ rule ] withReply:reply];
}
- (void)databaseRuleAddRules:(NSArray *)rules withReply:(void (^)())reply {
[[SNTDatabaseController ruleTable] addRules:rules];
// If any rules were added that were not whitelist, flush cache.
NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF.state != %d", RULESTATE_WHITELIST];
if ([rules filteredArrayUsingPredicate:p].count) {
LOGI(@"Received non-whitelist rule, flushing cache");
[self.driverManager flushCache];
}
reply();
}
- (void)databaseEventCount:(void (^)(uint64_t count))reply {
reply([[SNTDatabaseController eventTable] eventsPendingCount]);
reply([[SNTDatabaseController eventTable] pendingEventsCount]);
}
- (void)databaseEventForSHA1:(NSString *)sha1 withReply:(void (^)(SNTStoredEvent *))reply {
reply([[SNTDatabaseController eventTable] latestEventForSHA1:sha1]);
- (void)databaseEventForSHA256:(NSString *)sha256 withReply:(void (^)(SNTStoredEvent *))reply {
reply([[SNTDatabaseController eventTable] pendingEventForSHA256:sha256]);
}
- (void)databaseEventsPending:(void (^)(NSArray *events))reply {
@@ -73,7 +80,7 @@
}
- (void)databaseRemoveEventsWithIDs:(NSArray *)ids {
[[SNTDatabaseController eventTable] deleteEventsWithIndexes:ids];
[[SNTDatabaseController eventTable] deleteEventsWithIds:ids];
}
#pragma mark Misc

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
// These imports are in the header rather than implementation to keep them in one place, saving
// This is imported in the header rather than implementation to saves
// classes that use this one from also having to import FMDB stuff.
#import <FMDB/FMDB.h>
@@ -20,12 +20,16 @@
@class SNTEventTable;
@class SNTRuleTable;
/// Provides methods to get an instance of one of the database table controllers with a
/// pre-configured database queue.
///
/// Provides methods to get an instance of one of the database table controllers with a
/// pre-configured database queue.
///
@interface SNTDatabaseController : NSObject
/// Returns an instance of the respective table class initialized with an appropriate database queue
/// Will initialize only once, regardless of calling thread.
///
/// Returns an instance of the respective table class initialized with an appropriate
/// database queue. Will initialize only once, regardless of calling thread.
///
+ (SNTEventTable *)eventTable;
+ (SNTRuleTable *)ruleTable;

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -12,23 +12,29 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
// These imports are in the header rather than implementation to keep them in one place, saving
// This is imported in the header rather than implementation to saves
// classes that use this one from also having to import FMDB stuff.
#import <FMDB/FMDB.h>
@interface SNTDatabaseTable : NSObject
/// Designated initializer.
///
/// Designated initializer.
///
- (instancetype)initWithDatabaseQueue:(FMDatabaseQueue *)db;
/// Subclasses should override this method to apply schema updates. The passed in version nubmer
/// is the current version of the table. The return value is the new version of the table. If
/// updating the table failed, return a negative number. If there was no update to apply, return 0.
///
/// Subclasses should override this method to apply schema updates. The passed in version nubmer
/// is the current version of the table. The return value is the new version of the table. If
/// updating the table failed, return a negative number. If there was no update to apply, return 0.
///
- (int)initializeDatabase:(FMDatabase *)db fromVersion:(int)version;
/// Wrappers around the respective FMDatabaseQueue methods. If the object we initialized with was
/// a database queue, these just pass through. If the object we initialized with was an FMDatabase
/// we just call the block with the database, potentially wrapping in a transaction.
///
/// Wrappers around the respective FMDatabaseQueue methods. If the object we initialized with was
/// a database queue, these just pass through. If the object we initialized with was an FMDatabase
/// we just call the block with the database, potentially wrapping in a transaction.
///
- (void)inDatabase:(void (^)(FMDatabase *db))block;
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,21 +16,30 @@
@class SNTNotificationMessage;
/// Manages the connection between daemon and kernel.
///
/// Manages the connection between daemon and kernel.
///
@interface SNTDriverManager : NSObject
/// Handles requests from the kernel using the given block.
/// @note Loops indefinitely until either the callback block returns @c NO or there is an error
/// trying to read data from the data queue.
- (void)listenWithBlock:(BOOL (^)(santa_message_t message))callback;
///
/// Handles requests from the kernel using the given block.
/// @note Loops indefinitely unless there is an error trying to read data from the data queue.
///
- (void)listenWithBlock:(void (^)(santa_message_t message))callback;
/// Sends a response to a query back to the kernel.
///
/// Sends a response to a query back to the kernel.
///
- (kern_return_t)postToKernelAction:(santa_action_t)action forVnodeID:(uint64_t)vnodeId;
/// Get the number of binaries in the kernel's cache.
///
/// Get the number of binaries in the kernel's cache.
///
- (uint64_t)cacheCount;
/// Flush the kernel's binary cache.
///
/// Flush the kernel's binary cache.
///
- (BOOL)flushCache;
@end
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -19,8 +19,6 @@
#include "SNTLogging.h"
#import "SNTNotificationMessage.h"
@interface SNTDriverManager ()
@property IODataQueueMemory *queueMemory;
@property io_connect_t connection;
@@ -49,12 +47,13 @@
serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, classToMatch);
if (!serviceObject) {
LOGD(@"Waiting for Santa driver to become available");
sleep(10);
}
} while (!serviceObject);
CFRelease(classToMatch);
// This calls |initWithTask|, |attach| and |start| in |SantaDriverClient|
// This calls @c initWithTask, @c attach and @c start in @c SantaDriverClient
kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &_connection);
IOObjectRelease(serviceObject);
if (kr != kIOReturnSuccess) {
@@ -62,7 +61,7 @@
return nil;
}
// Call |open| in |SantaDriverClient|
// Call @c open in @c SantaDriverClient
kr = IOConnectCallMethod(_connection, kSantaUserClientOpen, 0, 0, 0, 0, 0, 0, 0, 0);
if (kr == kIOReturnExclusiveAccess) {
@@ -82,7 +81,7 @@
# pragma mark Incoming messages
- (void)listenWithBlock:(BOOL (^)(santa_message_t message))callback {
- (void)listenWithBlock:(void (^)(santa_message_t message))callback {
kern_return_t kr;
santa_message_t vdata;
UInt32 dataSize;
@@ -116,28 +115,19 @@
}
self.queueMemory = (IODataQueueMemory *)address;
BOOL breakOut = NO;
dataSize = sizeof(vdata);
while (IODataQueueWaitForAvailableData(self.queueMemory,
self.receivePort) == kIOReturnSuccess) {
while (IODataQueueDataAvailable(self.queueMemory)) {
dataSize = sizeof(vdata);
kr = IODataQueueDequeue(self.queueMemory, &vdata, &dataSize);
if (kr == kIOReturnSuccess) {
if (! callback(vdata)) {
breakOut = YES;
break;
}
callback(vdata);
} else {
LOGD(@"Error receiving data: %d", kr);
breakOut = YES;
break;
exit(2);
}
}
if (breakOut) {
break;
}
}
IOConnectUnmapMemory(self.connection, kIODefaultMemoryType, mach_task_self(), address);

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -17,27 +17,45 @@
@class SNTNotificationMessage;
@class SNTStoredEvent;
/// Responsible for managing the event table in the Santa database.
///
/// Responsible for managing the event table.
///
@interface SNTEventTable : SNTDatabaseTable
/// Add event to the database
- (void)addStoredEvent:(SNTStoredEvent *)event;
///
/// Add event to the database.
/// @param event the event to store.
/// @return YES if event was successfully stored.
///
- (BOOL)addStoredEvent:(SNTStoredEvent *)event;
/// Number of events in database.
- (int)eventsPendingCount;
/// Retrieves all events in the database
/// @return NSArray of SNTStoredEvent
///
/// Retrieves all events in the database
/// @return NSArray of SNTStoredEvent's
///
- (NSArray *)pendingEvents;
/// Retrieve an event from the database.
/// @return a single SNTStoredEvent
- (SNTStoredEvent *)latestEventForSHA1:(NSString *)sha1;
///
/// Retrieves number of events in database without fetching every event.
/// @return Number of events in database.
///
- (NSUInteger)pendingEventsCount;
/// Delete a single event from the database using its index.
- (void)deleteEventWithIndex:(NSNumber *)index;
///
/// Retrieve an event from the database.
/// @return a single SNTStoredEvent.
///
- (SNTStoredEvent *)pendingEventForSHA256:(NSString *)sha256;
/// Delete multiple events from the database with an array of indexes.
- (void)deleteEventsWithIndexes:(NSArray *)indexes;
///
/// Delete a single event from the database using its index.
///
- (void)deleteEventWithId:(NSNumber *)id;
///
/// Delete multiple events from the database with an array of IDs.
/// @param indexes an array of event IDs.
///
- (void)deleteEventsWithIds:(NSArray *)ids;
@end

View File

@@ -1,4 +1,4 @@
/// Copyright 2014 Google Inc. All rights reserved.
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
#import "SNTCertificate.h"
#import "SNTLogging.h"
#import "SNTNotificationMessage.h"
#import "SNTStoredEvent.h"
@implementation SNTEventTable
@@ -27,25 +26,10 @@
if (version < 1) {
[db executeUpdate:@"CREATE TABLE 'events' ("
"'idx' INTEGER PRIMARY KEY AUTOINCREMENT,"
"'fileSHA1' TEXT NOT NULL,"
"'filePath' TEXT NOT NULL,"
"'fileBundleID' TEXT,"
"'fileBundleVersion' TEXT,"
"'fileBundleVersionString' TEXT,"
"'fileBundleName' TEXT,"
"'certSHA1' TEXT,"
"'certCN' TEXT,"
"'certOrg' TEXT,"
"'certOU' TEXT,"
"'certValidFromDate' REAL,"
"'certValidUntilDate' REAL,"
"'occurrenceDate' REAL,"
"'executingUser' TEXT,"
"'decision' INT,"
"'loggedInUsers' BLOB,"
"'currentSessions' BLOB"
"'filesha256' TEXT NOT NULL,"
"'eventdata' BLOB"
@");"];
[db executeUpdate:@"CREATE INDEX event_filesha1 ON events (fileSHA1);"];
[db executeUpdate:@"CREATE INDEX filesha256 ON events (filesha256);"];
newVersion = 1;
}
@@ -55,120 +39,50 @@
#pragma mark Loading / Storing
- (void)addStoredEvent:(SNTStoredEvent *)event {
if (!event.fileSHA1 ||
- (BOOL)addStoredEvent:(SNTStoredEvent *)event {
if (!event.fileSHA256 ||
!event.filePath ||
!event.occurrenceDate ||
!event.executingUser ||
!event.decision) return;
!event.decision) return NO;
NSMutableDictionary *parameters = [@{@"fileSHA1": event.fileSHA1,
@"filePath": event.filePath,
@"occurrenceDate": event.occurrenceDate,
@"executingUser": event.executingUser,
@"decision": @(event.decision)} mutableCopy];
if (event.certSHA1) parameters[@"certSHA1"] = event.certSHA1;
if (event.certCN) parameters[@"certCN"] = event.certCN;
if (event.certOrg) parameters[@"certOrg"] = event.certOrg;
if (event.certOU) parameters[@"certOU"] = event.certOU;
if (event.certValidFromDate) parameters[@"certValidFromDate"] = event.certValidFromDate;
if (event.certValidUntilDate) parameters[@"certValidUntilDate"] = event.certValidUntilDate;
if (event.fileBundleID) parameters[@"fileBundleID"] = event.fileBundleID;
if (event.fileBundleName) parameters[@"fileBundleName"] = event.fileBundleName;
if (event.fileBundleVersion) parameters[@"fileBundleVersion"] = event.fileBundleVersion;
if (event.fileBundleVersionString) {
parameters[@"fileBundleVersionString"] = event.fileBundleVersionString;
}
if (event.loggedInUsers) {
NSData *usersData = [NSKeyedArchiver archivedDataWithRootObject:event.loggedInUsers];
parameters[@"loggedInUsers"] = usersData;
}
if (event.currentSessions ) {
NSData *sessionsData = [NSKeyedArchiver archivedDataWithRootObject:event.currentSessions];
parameters[@"currentSessions"] = sessionsData;
}
NSString *paramString = [[parameters allKeys] componentsJoinedByString:@","];
NSString *paramStringColon = [paramString stringByReplacingOccurrencesOfString:@","
withString:@",:"];
paramStringColon = [@":" stringByAppendingString:paramStringColon];
NSString *sql = [NSString stringWithFormat:@"INSERT INTO 'events' (%@) VALUES (%@)",
paramString,
paramStringColon];
NSData *eventData = [NSKeyedArchiver archivedDataWithRootObject:event];
__block BOOL success = NO;
[self inTransaction:^(FMDatabase *db, BOOL *rollback) {
if (![db executeUpdate:sql withParameterDictionary:parameters]) {
LOGD(@"Failed to save event");
}
success = [db executeUpdate:@"INSERT INTO 'events' (filesha256, eventdata) VALUES (?, ?)",
event.fileSHA256, eventData];
}];
return success;
}
- (SNTStoredEvent *)eventFromResultSet:(FMResultSet *)rs {
SNTStoredEvent *event = [[SNTStoredEvent alloc] init];
NSData *eventData = [rs dataForColumn:@"eventdata"];
if (!eventData) return nil;
SNTStoredEvent *event = [NSKeyedUnarchiver unarchiveObjectWithData:eventData];
event.idx = @([rs intForColumn:@"idx"]);
event.fileSHA1 = [rs stringForColumn:@"fileSHA1"];
event.filePath = [rs stringForColumn:@"filePath"];
event.occurrenceDate = [rs dateForColumn:@"occurrenceDate"];
event.executingUser = [rs stringForColumn:@"executingUser"];
event.decision = [rs intForColumn:@"decision"];
event.certSHA1 = [rs stringForColumn:@"certSHA1"];
event.certCN = [rs stringForColumn:@"certCN"];
event.certOrg = [rs stringForColumn:@"certOrg"];
event.certOU = [rs stringForColumn:@"certOU"];
event.certValidFromDate = [rs dateForColumn:@"certValidFromDate"];
event.certValidUntilDate = [rs dateForColumn:@"certValidUntilDate"];
event.fileBundleID = [rs stringForColumn:@"fileBundleID"];
event.fileBundleName = [rs stringForColumn:@"fileBundleName"];
event.fileBundleVersion = [rs stringForColumn:@"fileBundleVersion"];
event.fileBundleVersionString = [rs stringForColumn:@"fileBundleVersionString"];
NSData *currentSessions = [rs dataForColumn:@"currentSessions"];
NSData *loggedInUsers = [rs dataForColumn:@"loggedInUsers"];
if (currentSessions) {
event.currentSessions = [NSKeyedUnarchiver unarchiveObjectWithData:currentSessions];
}
if (loggedInUsers) {
event.loggedInUsers = [NSKeyedUnarchiver unarchiveObjectWithData:loggedInUsers];
}
return event;
}
#pragma mark Querying/Retreiving
- (int)eventsPendingCount {
__block int eventsPending = 0;
- (NSUInteger)pendingEventsCount {
__block NSUInteger eventsPending = 0;
[self inDatabase:^(FMDatabase *db) {
eventsPending = [db intForQuery:@"SELECT COUNT(*) FROM events"];
}];
return eventsPending;
}
- (BOOL)existingEventForBinary:(SNTNotificationMessage *)event {
__block BOOL result = NO;
NSString *qry = @"SELECT fileSHA1 FROM events WHERE fileSHA1=? LIMIT 1";
[self inDatabase:^(FMDatabase *db) {
result = [db boolForQuery:qry, event.SHA1];
}];
return result;
}
- (SNTStoredEvent *)latestEventForSHA1:(NSString *)sha1 {
- (SNTStoredEvent *)pendingEventForSHA256:(NSString *)sha256 {
__block SNTStoredEvent *storedEvent;
[self inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:@"SELECT * FROM events WHERE fileSHA1=? "
@"ORDER BY occurrenceDate DESC LIMIT 1;", sha1];
FMResultSet *rs = [db executeQuery:@"SELECT * FROM events WHERE filesha256=? LIMIT 1;",
sha256];
if ([rs next]) {
storedEvent = [self eventFromResultSet:rs];
@@ -198,15 +112,15 @@
#pragma mark Deleting
- (void)deleteEventWithIndex:(NSNumber *)index {
- (void)deleteEventWithId:(NSNumber *)index {
[self inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"DELETE FROM events WHERE idx=?", index];
}];
}
- (void)deleteEventsWithIndexes:(NSArray *)indexes {
- (void)deleteEventsWithIds:(NSArray *)indexes {
for (NSNumber *index in indexes) {
[self deleteEventWithIndex:index];
[self deleteEventWithId:index];
}
}

Some files were not shown because too many files have changed in this diff Show More