Compare commits

...

76 Commits

Author SHA1 Message Date
Tom Burgin
ebc93954be SantaGUI: Fix message text. Add support for Dark Mode. (#354) 2019-02-21 16:53:20 -05:00
Russell Hancox
cb4d2984b3 SantaCache: Fix possible divide by zero in bucket count calculation (#353) 2019-02-20 17:56:42 -05:00
Russell Hancox
4c2018ef67 SantaCache: Fix flaky test (#352) 2019-02-20 13:18:40 -05:00
Russell Hancox
06d8295d0a Project: Use apple_resource_group for test resources. Fix bazelrc (#351) 2019-02-19 12:20:30 -05:00
Tom Burgin
ef8e9975e9 c++11 features (#350) 2019-02-15 17:14:10 -05:00
Russell Hancox
31509f4b9c Project: Minor tidy-ups (#349) 2019-02-15 16:59:32 -05:00
Tom Burgin
497c1f393f project format (#347)
* starlark format

* Source/santa-driver -> Source/santa_driver

* buildifier

* kernel_tests unloads the driver

* review updates

* review updates
2019-02-15 15:38:06 -05:00
Tom Burgin
8334a245c7 cleanup unused includes (#346) 2019-02-15 11:12:38 -05:00
Tom Burgin
e8826a2941 add licenses and default_visibility to each BUILD file (#345)
* add licenses and default_visibility to each BUILD file

* remove default_visibility the bins are public

* oops
2019-02-15 11:03:28 -05:00
Tom Burgin
ef040c1e7d resurrect action=BUNDLE logs (#344)
They were lost in the refactoring of the logging utility 4a2cf9d722.
2019-02-11 13:46:37 -05:00
Russell Hancox
dc692c8256 Project: Move tests with the code they're testing (#343)
Add helper to make declaring unit tests easier
Add unit_tests test_suite containing all unit tests
Fix reload rule
Update to workspace-relative header locations that were missed before
2019-02-06 15:09:09 -05:00
Russell Hancox
e9c7bfc087 Project: Make all imports workspace-relative, remove include attributes from all rules. (#339) 2019-01-22 14:24:11 -05:00
Russell Hancox
22c72625c8 Project: Split BUILD file into several. Part 1/3 (#338)
* Project: Split BUILD file into several. Part 1/3

The tests fail in this PR because the rules need updating. I'll fix them in a follow-up PR.
2019-01-22 12:06:48 -05:00
Tom Burgin
65a2212890 BUILD: buildifier formatting (#336) 2019-01-17 16:23:37 -05:00
Russell Hancox
0a7c08cafc santactl/version: Make version command not crash with new Santa.app location (#335) 2019-01-16 17:16:39 -05:00
Tom Burgin
831a32160b BUILD: Some tweaks (#334) 2019-01-16 16:49:54 -05:00
Russell Hancox
b186419e54 Sync: Remove LogUpload. (#333)
Fixes #331
2019-01-07 14:27:44 -05:00
Russell Hancox
1dc579c00f Project: Fix badges in README (#332) 2019-01-07 12:28:57 -05:00
Russell Hancox
abdd6c319a Project: Update docs for switch to bazel (#330)
* Project: Update docs for switch to bazel

I also made it so the santactl compilation won't include debug-only commands in release builds and the release rule will fail on a non-opt build.
2019-01-04 19:45:00 -05:00
Russell Hancox
5dd93fadfa Project: Convert to bazel, part 2 (#329)
Project: Convert to bazel, part 2

The main thing to call out in this PR is that Santa.app is now embedded inside santa-driver.kext along with everything else. The package will handle updating this automatically but it should be called out in release notes to make everyone aware.

* Switch to using macos_kernel_extension and macos_xpc_service, stop using product_type.
* Have Bazel embed all related binaries inside santa-driver.kext, including Santa.app. This simplifies the :release and :reload rules.
* Add commands for unload, load and reload, removing any need to keep the Rakefile around 😃
* Make the :kernel_tests rule a command that replicates what the Rakefile did for this.
* Added a project-wide .bazelrc that always generates dSYMs

Documentation changes to follow, as all the building instructions are now out of date.
2019-01-04 16:23:35 -05:00
Russell Hancox
e6fcbf59df Proj: Convert to Bazel build, remove other build systems. (#326)
This necessitated fixing some warnings, updating the resource
locations inside some tests and updating the Travis config.

I'll send a follow-up PR shortly that adds the fuzzing targets and updates the Rakefile and documentation.
2018-12-14 11:57:32 -05:00
Tom Burgin
9fd04ed301 SantaPrefixTree: Fix a bug and add some more tests (#324)
* SantaPrefixTree: Fix a threading bug.
Tests: Add logic tests for SantaPrefixTree.

* clean up

* don't ifdef so much

* more #define less #ifdef

* less lambda more of rah's ideas
2018-12-03 17:08:16 -05:00
Tom Burgin
e4b5f595ce * Add note about vnode map. (#323)
* Fix logic tests under Xcode 10.1.
2018-11-19 12:44:28 -05:00
Tom Burgin
212b02589b Update README.md (#319) 2018-11-12 10:50:28 -05:00
Tom Burgin
42c3631995 Update uninstall.sh (#318)
I think this was added by accident.
2018-11-09 16:13:38 -05:00
Tom Burgin
2695355dd2 add in-kernel filemod prefix filter (#313)
* add in-kernel filemod prefix filter

* byte lookup

* added pruning and tests

* clang-format

* add TODO

* don't need seen

* review updates

* reset filter on client connect

* DisconnectClient: reset filter
AddPrefix: when a branch is needed create the whole branch immediately

* don't use strlen in HasPrefix
use strnlen in AddPrefix
up max nodes to 1024

* use new[] and delete[] for the prune "stack"
revert clang-format changes to kernel tests
remove reset node count

* words

* count not size
2018-11-08 15:37:30 -05:00
Darío Hereñú
db0cd861d6 README: Paragraph formatting L157 to L168 (proposal) (#317) 2018-11-08 13:12:23 -05:00
Victor Vrantchan
57d6a962de update deployment documentation (#312)
- SyncBaseURL is not overridable by the server.
- ATS requires a self signed certificate to exist in the system roots. Providing roots enables in the Santa configuration enables pinning.

Closes #309
2018-11-05 13:06:49 -05:00
Russell Hancox
91608d7366 santad: Document implicit rule ordering (#315)
Also add a test to ensure this doesn't change one day without us noticing
2018-11-02 12:12:19 -04:00
Russell Hancox
7d4f1ffc45 config: Ensure syncBaseURL ends with a / (#311)
* config: Ensure syncBaseURL ends with a /

Without the trailing / the last path component is removed by `URLWithString:relativeToURL:`
2018-10-09 18:27:04 -04:00
Victor Vrantchan
ba539bb555 docs: remove space before period. (#308) 2018-10-07 15:09:17 -04:00
Victor Vrantchan
d9ecbf06c0 Document recent changes to sync server configuration (#307)
- bundles_enabled became enable_bundles.
- enabled_transitive_whitelisting was added.

Both changes were implemented in #300
2018-10-07 15:09:04 -04:00
Tom Burgin
01df4623c7 santa-driver: add back the root and non-root caches (#302)
* santa-driver: add back the root and non-root caches

* cachehistogram: clarify buckets and entries

* review changes
2018-09-26 12:41:04 -04:00
Tom Burgin
c9cb91a22e ocspd also seems integral to cs validation (#301) 2018-09-26 08:45:39 -04:00
Russell Hancox
1f9d60aecc common: Allow transitive whitelisting to be controlled by sync servers. (#300)
Also rename TransitiveWhitelistingEnabled -> EnableTransitiveWhitelisting and BundlesEnabled -> EnableBundles
2018-09-26 08:43:31 -04:00
nguyen-phillip
52c5b5aade add newline to output of "santactl help sync" (#299) 2018-09-25 13:55:52 -04:00
Tom Burgin
2d98173c51 fix cache invalidation on macOS Mojave (#298) 2018-09-21 15:22:34 -04:00
Tom Burgin
5e3f13be70 intentional fall-through (#297)
* intentional fall-through

* russell's idea
2018-09-20 18:40:23 -04:00
Tom Burgin
90b894b88a santad: add critical system binaries (#296)
* santad: add critical system binaries

* review updates

* use a getter
2018-09-20 17:17:12 -04:00
nguyen-phillip
6dc7387881 Add transitive whitelisting to Santa (#224)
Add transitive whitelisting.

Binaries may be identified with WHITELIST_COMPILER rules.  Any executable they output will then be marked locally with a transitive whitelist rule and allowed to run if the TransitiveWhitelistingEnabled config key is true.
2018-07-20 11:47:04 -04:00
Tom Burgin
b14b017d72 santa-driver: add IOMatchCategory (#292) 2018-07-18 11:33:09 -04:00
Tom Burgin
d0ede18bf4 MOLCertificate --> 1.9 (#290) 2018-07-06 12:56:15 -04:00
Alessandro Gario
6d223aea03 Various fixes (documentation, and an additional check on the JSON received from the syncserver) (#288)
* santa-driver: Fix documentation warnings
* SantaCache: Fix documentation warnings
* santactl: Always make sure that the syncserver JSON is a dictionary
2018-07-06 09:42:22 -04:00
Alessandro Gario
f7986b0a05 Update MOLXPCConnection; add support for unprivileged XPC interfaces (#287)
* Update MOLXPCConnection; add support for unprivileged XPC interfaces

* Code review changes
2018-07-05 17:20:49 -04:00
Alessandro Gario
629e70287c Add CMake support, implement fuzzers (#284)
The new CMake project allows the user to select which SDK version
to use. The Xcode path is also configurable to support non-standard
installation paths and/or systems with multiple versions installed.

Code signing can now be configured via command line, using the
CODESIGN_IDENTITY environment variable.

New fuzzing targets (libFuzzer)
 - SantaCache
 - santactl
 - santad

New make targets:
 - tests: Runs the tests
 - fuzz: Runs the fuzzer
 - redist: Regenerates the redistributable folder
 - install: Installs Santa
2018-06-29 14:15:16 -04:00
Russell Hancox
3c2a88144c santad: Wait for driver appearance using IOKit notifications. (#278)
Continue loading without driver, report status in santactl.
2018-06-12 16:15:41 -04:00
dgw
3651f18566 readme: s/precendence/precedence/ (#283) 2018-06-12 15:01:42 -04:00
Russell Hancox
472fea75b1 KernelTests: Simplify kernel tests (#282)
This change does 2 major things:

1) Makes the test runnable from within Xcode, unloading any running
santad and santa-driver, loading the just-built driver from the same folder and
then running each test.

2) Makes each test responsible for declaring what should happen to
incoming requests from the driver, instead of keeping all of that
code near the top of the file. This makes each test much clearer in what
should be happening.
2018-06-12 09:53:20 -04:00
Russell Hancox
e1b5438865 santa-driver: Re-factor some destruction methods (#281) 2018-06-11 12:54:29 -04:00
Russell Hancox
fbbf523333 santa-driver: Stop catching hasdirtyblks, the loader handles this (#280) 2018-06-06 18:56:00 -04:00
Russell Hancox
15fa53d744 santa-driver: Switch to a struct for vnode IDs, holding both the file… (#276)
santa-driver: Switch to a struct for vnode IDs, holding both the filesystem ID and vnode ID.

Also drop the separate caches for root/non-root as this doesn't offer any benefit anymore.
2018-06-05 06:43:49 -04:00
Russell Hancox
9595f80fde santad: Don't get code signature info for non Mach-O's. (#277) 2018-06-05 06:43:11 -04:00
Russell Hancox
61a67e45c1 SantaCache: Add command to print histogram of bucket distribution (#275)
* SantaCache: Add santactl command to print histogram of bucket distribution.

This currently only prints the distribution of the non-root cache. In the near future I'll unify the caches again which stops this being a problem.
2018-06-01 17:02:39 -04:00
Russell Hancox
143e690dab SantaCache: Add very basic distribution test (#273)
* SantaCache: Add very basic distribution test
2018-06-01 13:11:24 -04:00
Russell Hancox
ebd507f143 Project: Update cocoapods, again (#274) 2018-06-01 12:01:21 -04:00
Russell Hancox
f71bc0a8f7 santa-driver: Fix cache CAS operations, which haven't been working (#272)
* santa-driver: Fix cache CAS operations, which haven't really been working.
2018-06-01 11:38:25 -04:00
Russell Hancox
edc0c72464 SantaCache: Templatize key types (#271) 2018-05-30 15:50:23 -04:00
Tom Burgin
c3ce4f718b Update configuration.md (#270) 2018-05-30 11:06:45 -04:00
Tom Burgin
40ee482973 Update SNTSyslogEventLog.m (#269)
remove extra space
2018-05-29 16:39:18 -04:00
Mitchell Grenier
a5d2e6fdd2 Optional MachineID for Logs (#256)
* First draft, no UUID caching

* Cache UUID in SNTEventLog super class

* Add a configuration flag for UUID decoration

* Port from UUID to MachineID

* KVO complicance

* Remove extra newline I accidentally introduced
2018-05-29 16:16:21 -04:00
Tom Burgin
e9a835a642 log deny because of dirty vnode (#267)
* log dirty vnode blocks

* review update
2018-05-25 14:16:16 -04:00
Tom Burgin
ac7b95ceb6 santa-driver: do not invalidate cached decisions on KAUTH_VNODE_ACCESS (#266)
* santa-driver: do not invalidate cached decisions on KAUTH_VNODE_ACCESS

* downtown
2018-05-25 10:47:48 -04:00
Russell Hancox
055b2d8ede Update project for Xcode 9.1, add codesigning flags (#264)
* Project: Update project to Xcode 9.1 and handle all the new warnings that entails.

* Project: Add library-validation and kill flags to codesigning options
2018-05-22 10:13:59 -04:00
Russell Hancox
a75cd0a0f5 Update README.md (#263)
Update the sync client section to point at known open-source solutions, remove the Xcode 7.3.1 build requirement
2018-05-18 12:26:37 -04:00
Matthew Suozzo
2b1ddf9a4e Fix typo in sync help text (#259) 2018-05-09 21:53:51 -04:00
Tom Burgin
b70442e483 Project: Use MOLXPCConnection (#258)
* Project: Use MOLXPCConnection

* review fixes
2018-05-09 11:40:35 -04:00
Tom Burgin
798b0fab15 fileinfo: whitelist bundle extensions when performing an ancestor search (#257)
* fileinfo: whitelist bundle extensions when performing an ancestor search

* fix tests

* conform to russell's every whim
2018-05-07 13:57:58 -04:00
Russell Hancox
e8630132d7 Project: make building on case-sensitive volumes work (#255) 2018-04-27 12:58:54 -04:00
Russell Hancox
273ae5f21a santad: Missed an import (#254) 2018-04-27 10:51:53 -04:00
Tom Burgin
06b688fef4 Update .travis.yml (#253) 2018-04-26 17:23:32 -04:00
Russell Hancox
59cc038ab2 All: stop using @import for reasons. (#252) 2018-04-26 17:19:19 -04:00
Tom Burgin
ea5a6c3438 downstream --> upstream changes (#251) 2018-04-25 16:16:56 -04:00
Tom Burgin
e2adfdf3cf Add EventLog Docs (#250) 2018-04-24 16:33:53 -04:00
Tom Burgin
5ee6531627 santad / santactl: validate all architectures within universal binaries (#249) 2018-04-24 16:11:49 -04:00
Tom Burgin
1cf8ee09e1 sync-state: Mitigate com.apple.ManagedClient flapping (#248)
* sync-state: Mitigate com.apple.ManagedClient flapping

* 10 min
2018-04-09 13:34:33 -04:00
Tom Burgin
4a2cf9d722 santad: event logger (#246)
* kext symbols

* santad: Create FileLog and Syslog options

* review updates

* review updates

* be a good citizen and let go of things you do not need
2018-04-03 13:15:12 -04:00
208 changed files with 6837 additions and 6364 deletions

1
.bazelrc Normal file
View File

@@ -0,0 +1 @@
build --apple_generate_dsym --define=apple.propagate_embedded_extra_outputs=yes

12
.gitignore vendored
View File

@@ -1,11 +1,3 @@
.DS_Store
Build
santa-*
!santa-driver
!*.md
Pods
Santa.xcodeproj/xcuserdata
Santa.xcodeproj/project.xcworkspace
Santa.xcworkspace/xcuserdata
Santa.xcworkspace/xcshareddata
Source/DevelopmentTeam.xcconfig
default.profraw
bazel-*

View File

@@ -1,14 +1,12 @@
---
language: objective-c
cache:
- bundler
- cocoapods
sudo: false
osx_image: xcode7
before_install:
- gem install cocoapods xcpretty
- pod setup >/dev/null
addons:
homebrew:
taps: bazelbuild/tap
packages: bazelbuild/tap/bazel
script:
- xcodebuild -workspace Santa.xcworkspace -scheme All -derivedDataPath build build test CODE_SIGN_IDENTITY='' | xcpretty -sc && exit ${PIPESTATUS[0]}
- bazel build :release --show_progress_rate_limit=30.0 -c opt --apple_generate_dsym --color=no --verbose_failures --sandbox_debug
- bazel test :unit_tests --show_progress_rate_limit=30.0 --test_output=errors --color=no --verbose_failures --sandbox_debug

158
BUILD Normal file
View File

@@ -0,0 +1,158 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0
exports_files(["LICENSE"])
load("@build_bazel_rules_apple//apple:versioning.bzl", "apple_bundle_version")
load("//:helper.bzl", "run_command")
load("//:version.bzl", "SANTA_VERSION")
# The version label for mac_* rules.
apple_bundle_version(
name = "version",
build_version = SANTA_VERSION,
short_version_string = SANTA_VERSION,
)
# Used to detect optimized builds
config_setting(
name = "opt_build",
values = {"compilation_mode": "opt"},
)
################################################################################
# Loading/Unloading/Reloading
################################################################################
run_command(
name = "unload",
cmd = """
sudo launchctl unload /Library/LaunchDaemons/com.google.santad.plist 2>/dev/null
sudo kextunload -b com.google.santa-driver 2>/dev/null
launchctl unload /Library/LaunchAgents/com.google.santagui.plist 2>/dev/null
""",
)
run_command(
name = "load",
cmd = """
sudo launchctl load /Library/LaunchDaemons/com.google.santad.plist
launchctl load /Library/LaunchAgents/com.google.santagui.plist
""",
)
run_command(
name = "reload",
srcs = ["//Source/santa_driver"],
cmd = """
set -e
rm -rf /tmp/bazel_santa_reload
unzip -d /tmp/bazel_santa_reload \
$${BUILD_WORKSPACE_DIRECTORY}/bazel-bin/Source/santa_driver/santa_driver.zip >/dev/null
echo "You may be asked for your password for sudo"
sudo BINARIES=/tmp/bazel_santa_reload CONF=$${BUILD_WORKSPACE_DIRECTORY}/Conf \
$${BUILD_WORKSPACE_DIRECTORY}/Conf/install.sh
rm -rf /tmp/bazel_santa_reload
echo "Time to stop being naughty"
""",
)
################################################################################
# Release rules - used to create a release tarball
################################################################################
genrule(
name = "release",
srcs = [
"//Source/santa_driver",
"Conf/install.sh",
"Conf/uninstall.sh",
"Conf/com.google.santad.plist",
"Conf/com.google.santagui.plist",
"Conf/com.google.santa.asl.conf",
"Conf/com.google.santa.newsyslog.conf",
"Conf/Package/Makefile",
"Conf/Package/postinstall",
"Conf/Package/preinstall",
],
outs = ["santa-" + SANTA_VERSION + ".tar.gz"],
cmd = select({
"//conditions:default": """
echo "ERROR: Trying to create a release tarball without optimization."
echo "Please add '-c opt' flag to bazel invocation"
""",
":opt_build": """
# Extract santa_driver.zip
for SRC in $(SRCS); do
if [[ $$(basename $${SRC}) == "santa_driver.zip" ]]; then
mkdir -p $(@D)/binaries
unzip -q $${SRC} -d $(@D)/binaries >/dev/null
fi
done
# Copy config files
for SRC in $(SRCS); do
if [[ "$$(dirname $${SRC})" == *"Conf" ]]; then
mkdir -p $(@D)/conf
cp $${SRC} $(@D)/conf/
fi
done
# Gather together the dSYMs. Throw an error if no dSYMs were found
for SRC in $(SRCS); do
case $${SRC} in
*santa-driver.kext.dSYM*Info.plist)
mkdir -p $(@D)/dsym
cp -LR $$(dirname $$(dirname $${SRC})) $(@D)/dsym/santa-driver.kext.dSYM
;;
*santad.dSYM*Info.plist)
mkdir -p $(@D)/dsym
cp -LR $$(dirname $$(dirname $${SRC})) $(@D)/dsym/santad.dSYM
;;
*santactl.dSYM*Info.plist)
mkdir -p $(@D)/dsym
cp -LR $$(dirname $$(dirname $${SRC})) $(@D)/dsym/santactl.dSYM
;;
*santabs.xpc.dSYM*Info.plist)
mkdir -p $(@D)/dsym
cp -LR $$(dirname $$(dirname $${SRC})) $(@D)/dsym/santabs.xpc.dSYM
;;
*Santa.app.dSYM*Info.plist)
mkdir -p $(@D)/dsym
cp -LR $$(dirname $$(dirname $${SRC})) $(@D)/dsym/Santa.app.dSYM
;;
esac
done
# Cause a build failure if the dSYMs are missing.
if [[ ! -d "$(@D)/dsym" ]]; then
echo "dsym dir missing: Did you forget to use --apple_generate_dsym?"
echo "This flag is required for the 'release' target."
exit 1
fi
# Update all the timestamps to now. Bazel avoids timestamps to allow
# builds to be hermetic and cacheable but for releases we want the
# timestamps to be more-or-less correct.
find $(@D)/{binaries,conf,dsym} -exec touch {} \;
# Create final output tar
tar -C $(@D) -czpf $(@) binaries dsym conf
""",
}),
heuristic_label_expansion = 0,
)
test_suite(
name = "unit_tests",
tests = [
"//Source/common:SNTFileInfoTest",
"//Source/santa_driver:SantaCacheTest",
"//Source/santa_driver:SantaPrefixTreeTest",
"//Source/santactl:SNTCommandFileInfoTest",
"//Source/santactl:SNTCommandSyncTest",
"//Source/santad:SNTEventTableTest",
"//Source/santad:SNTExecutionControllerTest",
"//Source/santad:SNTRuleTableTest",
],
)

View File

@@ -32,6 +32,7 @@ PACKAGE_VERSION:=$(shell curl -fs https://api.github.com/repos/google/santa/rele
# | |-- com.google.santad.plist
# | |-- com.google.santagui.plist
# | +-- com.google.santa.asl.conf
# | +-- com.google.santa.newsyslog.conf
# +--dsym
# |-- santa-driver.kext.dSYM
# |-- Santa.app.dSYM
@@ -44,6 +45,7 @@ PAYLOAD:=pack-Library-Extensions-santa-driver.kext \
pack-Library-LaunchDaemons-com.google.santad.plist \
pack-Library-LaunchAgents-com.google.santagui.plist \
pack-etc-asl-com.google.santa.asl.conf \
pack-etc-newsyslog.d-com.google.santa.newsyslog.conf \
pack-script-preinstall \
pack-script-postinstall
@@ -52,6 +54,7 @@ Santa.app: download
com.google.santad.plist: download
com.google.santagui.plist: download
com.google.santa.asl.conf: download
com.google.santa.newsyslog.conf: download
download:
$(if $(PACKAGE_VERSION),, $(error GitHub API returned unexpected result. Wait a while and try again))
@@ -65,6 +68,12 @@ pack-etc-asl-com.google.santa.asl.conf: com.google.santa.asl.conf l_private_etc
@sudo chmod 755 ${WORK_D}/private/etc/asl
@sudo install -m 644 -o root -g wheel com.google.santa.asl.conf ${WORK_D}/private/etc/asl
pack-etc-newsyslog.d-com.google.santa.newsyslog.conf: com.google.santa.newsyslog.conf l_private_etc
@sudo mkdir -p ${WORK_D}/private/etc/newsyslog.d
@sudo chown root:wheel ${WORK_D}/private/etc/newsyslog.d
@sudo chmod 755 ${WORK_D}/private/etc/newsyslog.d
@sudo install -m 644 -o root -g wheel com.google.santa.newsyslog.conf ${WORK_D}/private/etc/newsyslog.d
pack-Library-Extensions-santa-driver.kext: santa-driver.kext l_Library
@sudo mkdir -p ${WORK_D}/Library/Extensions
@sudo ${DITTO} --noqtn santa-driver.kext ${WORK_D}/Library/Extensions/santa-driver.kext
@@ -79,6 +88,7 @@ myclean:
@rm -rf santa-driver.kext
@rm -f config.plist
@rm -f com.google.santa.asl.conf
@rm -f com.google.santa.newsyslog.conf
@rm -f com.google.santad.plist
@rm -f com.google.santagui.plist
@rm -f install.sh

View File

@@ -17,6 +17,7 @@ sleep 1
/bin/rm /usr/sbin/santactl
/bin/launchctl remove com.google.santasync
/bin/rm /Library/LaunchDaemons/com.google.santasync.plist
/bin/rm -rf /Applications/Santa.app
sleep 1

View File

@@ -0,0 +1,2 @@
# logfilename [owner:group] mode count size(KiB) when flags [/pid_file] # [sig_num]
/var/db/santa/santa.log root:wheel 644 10 25000 * NZ

View File

@@ -20,7 +20,5 @@
<true />
<key>ProcessType</key>
<string>Interactive</string>
<key>ThrottleInterval</key>
<integer>1</integer>
</dict>
</plist>

View File

@@ -6,7 +6,7 @@
<string>com.google.santagui</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Santa.app/Contents/MacOS/Santa</string>
<string>/Library/Extensions/santa-driver.kext/Contents/Resources/Santa.app/Contents/MacOS/Santa</string>
<string>--syslog</string>
</array>
<key>RunAtLoad</key>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Minimal Configuration -->
<key>ClientMode</key>
<integer>1</integer>
<!-- For documentation of other keys, see the following URL:
https://github.com/google/santa/wiki/Configuration-Keys -->
</dict>
</plist>

View File

@@ -5,43 +5,53 @@ if [[ $EUID -ne 0 ]]; then
exit 1
fi
if [[ -d "binaries" ]]; then
SOURCE="."
elif [[ -d "../binaries" ]]; then
SOURCE=".."
else
echo "Can't find binaries, run install.sh from inside the conf directory" 1>&2
exit 1
if [[ -z "${BINARIES}" || -z "${CONF}" ]]; then
if [[ -d "binaries" ]]; then
BINARIES="${PWD}/binaries"
CONF="${PWD}/conf"
elif [[ -d "../binaries" ]]; then
BINARIES="${PWD}/../binaries"
CONF="${PWD}/../conf"
else
echo "Can't find binaries, run install.sh from inside the conf directory" 1>&2
exit 1
fi
fi
# Determine if anyone is logged into the GUI
GUI_USER=$(/usr/bin/stat -f '%u' /dev/console)
# Unload santad and scheduled sync job.
/bin/launchctl remove com.google.santad >/dev/null 2>&1
# Unload kext.
/sbin/kextunload -b com.google.santa-driver >/dev/null 2>&1
# Determine if anyone is logged into the GUI
GUI_USER=$(/usr/bin/stat -f '%u' /dev/console)
# Unload GUI agent if someone is logged in.
[[ -n "$GUI_USER" ]] && \
/bin/launchctl asuser ${GUI_USER} /bin/launchctl remove /Library/LaunchAgents/com.google.santagui.plist
/bin/launchctl asuser ${GUI_USER} /bin/launchctl remove com.google.santagui
# Cleanup cruft from old versions
/bin/launchctl remove com.google.santasync >/dev/null 2>&1
/bin/rm /Library/LaunchDaemons/com.google.santasync.plist >/dev/null 2>&1
/bin/rm /usr/libexec/santad >/dev/null 2>&1
/bin/rm /usr/sbin/santactl >/dev/null 2>&1
/bin/rm -rf /Applications/Santa.app 2>&1
/bin/rm -rf /Library/Extensions/santa-driver.kext 2>&1
# Copy new files.
/bin/cp -r ${SOURCE}/binaries/santa-driver.kext /Library/Extensions
/bin/cp -r ${SOURCE}/binaries/Santa.app /Applications
mkdir -p /usr/local/bin
/bin/ln -s /Library/Extensions/santa-driver.kext/Contents/MacOS/santactl /usr/local/bin
/bin/cp -r ${BINARIES}/santa-driver.kext /Library/Extensions
/bin/mkdir -p /usr/local/bin
/bin/ln -s /Library/Extensions/santa-driver.kext/Contents/MacOS/santactl /usr/local/bin 2>/dev/null
/bin/cp ${SOURCE}/conf/com.google.santad.plist /Library/LaunchDaemons
/bin/cp ${SOURCE}/conf/com.google.santagui.plist /Library/LaunchAgents
/bin/cp ${SOURCE}/conf/com.google.santa.asl.conf /etc/asl/
if [ ! -d /var/db/santa ] ; then
/bin/mkdir /var/db/santa
fi
/bin/cp ${CONF}/com.google.santad.plist /Library/LaunchDaemons
/bin/cp ${CONF}/com.google.santagui.plist /Library/LaunchAgents
/bin/cp ${CONF}/com.google.santa.asl.conf /etc/asl/
/bin/cp ${CONF}/com.google.santa.newsyslog.conf /etc/newsyslog.d/
# Reload syslogd to pick up ASL configuration change.
/usr/bin/killall -HUP syslogd
@@ -54,6 +64,7 @@ mkdir -p /usr/local/bin
# Load GUI agent if someone is logged in.
[[ -n "$GUI_USER" ]] && \
/bin/launchctl asuser ${GUI_USER} /bin/launchctl load /Library/LaunchAgents/com.google.santagui.plist
/bin/launchctl asuser ${GUI_USER} \
/bin/launchctl load /Library/LaunchAgents/com.google.santagui.plist
exit 0

View File

@@ -19,7 +19,9 @@ user=$(/usr/bin/stat -f '%u' /dev/console)
/bin/rm -f /Library/LaunchAgents/com.google.santagui.plist
/bin/rm -f /Library/LaunchDaemons/com.google.santad.plist
/bin/rm -f /private/etc/asl/com.google.santa.asl.conf
/bin/rm -f /private/etc/newsyslog.d/com.google.santa.newsyslog.conf
/bin/rm -f /usr/local/bin/santactl # just a symlink
#uncomment to remove the config file and all databases, log files
#/bin/rm -rf /var/db/santa
#/bin/rm -f /var/log/santa*

View File

@@ -22,12 +22,12 @@ Two configuration methods can be used to control Santa: a local configuration pr
| BannedBlockMessage | String | This is the message shown to the user when a binary is blocked because of a rule if that rule doesn't provide a custom message. If this is not configured a reasonable default is provided. |
| ModeNotificationMonitor | String | The notification text to display when the client goes into Monitor mode. Defaults to "Switching into Monitor mode". |
| ModeNotificationLockdown | String | The notification text to display when the client goes into Lockdown mode. Defaults to "Switching into Lockdown mode". |
| SyncBaseURL* | String | The base URL of the sync server. |
| SyncBaseURL | String | The base URL of the sync server. |
| ClientAuthCertificateFile | String | If set, this contains the location of a PKCS#12 certificate to be used for sync authentication. |
| ClientAuthCertificatePassword | String | Contains the password for the PKCS#12 certificate. |
| ClientAuthCertificateCN | String | 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. |
| ClientAuthCertificateIssuerCN | String | 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. |
| ServerAuthRootsData | Data | 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. |
| ServerAuthRootsData | Data | If set, this is valid PEM containing one or more certificates to be used for certificate pinning. To comply with [ATS](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW57) the certificate chain must also be trusted in the keychain. |
| ServerAuthRootsFile | String | The same as the above but is a path to a file on disk containing the PEM data. |
| MachineOwner | String | The machine owner. |
| MachineID | String | The machine ID. |
@@ -35,6 +35,9 @@ Two configuration methods can be used to control Santa: a local configuration pr
| MachineOwnerKey | String | The key to use on MachineOwnerPlist. |
| MachineIDPlist | String | The path to a plist that contains the MachineOwnerKey / value pair. |
| MachineIDKey | String | The key to use on MachineIDPlist. |
| EventLogType | String | Defines how event logs are stored. Options are 1) syslog: Sent to ASL or ULS (if built with the 10.12 SDK or later). 2) filelog: Sent to a file on disk. Use EventLogPath to specify a path. Defaults to filelog |
| EventLogPath | String | If EventLogType is set to filelog, EventLogPath will provide the path to save logs. Defaults to /var/db/santa/santa.log. If you change this value ensure you also update com.google.santa.newsyslog.conf with the new path. |
| EnableMachineIDDecoration | Bool | If YES, this appends the MachineID to the end of each log line. Defaults to NO. |
*overridable by the sync server: run `santactl status` to check the current running config
@@ -169,7 +172,8 @@ Configuration profiles have a `.mobileconfig` file extension. There are many way
| fcm_token* | String | The FCM token used by Santa to listen for FCM messages. Unique for every machine. No default. |
| fcm_full_sync_interval* | Integer | The full sync interval if a fcm_token is set. Defaults to 14400 secs (4 hours). |
| fcm_global_rule_sync_deadline* | Integer | The max time to wait before performing a rule sync when a global rule sync FCM message is received. This allows syncing to be staggered for global events to avoid spikes in server load. Defaults to 600 secs (10 min). |
| bundles_enabled* | Bool | If set to `True` the bundle scanning feature is enabled. Defaults to `False`. |
| enable_bundles* | Bool | If set to `True` the bundle scanning feature is enabled. Defaults to `False`. |
| enabled_transitive_whitelisting | Bool | If set to `True` the transitive whitelisting feature is enabled. Defaults to `False`. |
*Held only in memory. Not persistent upon process restart.

View File

@@ -8,7 +8,7 @@ Binary rules use the SHA-256 hash of the entire binary as an identifier. This is
##### Certificate Rules
Certificate rules are formed from the SHA-256 fingerprint of an X.509 leaf signing certificate. This is a powerful rule type that has a much broader reach than an individual binary rule . A signing certificate can sign any number of binaries. Whitelisting or blacklisting just a few key signing certificates can cover the bulk of an average user's binaries. The leaf signing certificate is the only part of the chain that is evaluated. Though the whole chain is available for viewing.
Certificate rules are formed from the SHA-256 fingerprint of an X.509 leaf signing certificate. This is a powerful rule type that has a much broader reach than an individual binary rule. A signing certificate can sign any number of binaries. Whitelisting or blacklisting just a few key signing certificates can cover the bulk of an average user's binaries. The leaf signing certificate is the only part of the chain that is evaluated. Though the whole chain is available for viewing.
```sh
⇒ santactl fileinfo /Applications/Dropbox.app --key "Signing Chain"

View File

@@ -1,8 +1,8 @@
# Building
Santa makes use of [rake](https://ruby.github.io/rake/) for building and testing Santa. All of the [releases](https://github.com/google/santa/releases) are made using this same process. Santa's releases are codesigned with Google's KEXT signing certificate. This allows Santa to be loaded with SIP fully enabled.
Santa uses [Bazel](https://bazel.build) for building, testing and releases.
The `master` branch on GitHub is the source-of-truth with features developed
in personal forks.
#### Cloning
@@ -13,33 +13,53 @@ git clone https://github.com/google/santa
cd santa
```
The above command will default to using the `master` branch. If you wanted to build, run or test a specific version of Santa use this command.
The above command will default to using the `master` branch. All releases are
built from tagged commits, so if you wanted to build, run or test a specific
release you can checkout that tag:
```sh
git checkout <version, i.e. 0.9.19>
git checkout 0.9.30
```
If you want to list all the tags in reverse order:
```sh
git tag --sort=-creatordate
```
#### Building
Build a debug version of Santa. This keeps all the debug symbols, adds additional logs and does not optimize the compiled output. For speed sensitive tests make sure to benchmark a release version too.
Build a debug version of Santa:
```sh
rake build:debug
bazel build :santa-driver
```
Build a release version of Santa.
Build a release (optimized) version of Santa:
```sh
rake build:release
bazel build :santa-driver -c opt
```
Both of these just output the binaries that makeup Santa in the default Xcode build location. To actually run what was built, see the next section.
The output for these commands will be a `santa-driver.zip` file under
`bazel-bin` which, when extracted, will contain all of Santa and should be
installed under `/Library/Extensions`. However, if you're working on Santa
and want a quick way to reload everything, see the next section.
#### Running
On macOS 10.11+ System Integrity Protection (SIP) prevents loading of kernel extensions that are not signed by an Apple KEXT signing certificate. To be able to load and test a non-release version of Santa, SIP will have to be configured to allow non-Apple KEXT signing certificates.
When working on Santa, it's useful to have a way to quickly reload all of the
Santa components. For this reason, there's a special rule in the Santa BUILD
file that will compile a new santa-driver, unload Santa if it's running,
install the new Santa in the right place and attempt to load it.
__This is only to be done a machine that is actively developing, unloading and loading kernel extensions.__
On macOS 10.11+ System Integrity Protection (SIP) prevents loading of kernel
extensions that are not signed by an Apple KEXT signing certificate. To be able
to load and test a non-release version of Santa, SIP will have to be configured
to allow non-Apple KEXT signing certificates.
__This is only to be done a machine that is actively developing, unloading and
loading kernel extensions.__
1. Boot into Recovery Mode: Reboot and hold down `command+r`
2. From the utilities menu select `Terminal`
@@ -51,22 +71,37 @@ You should now be able to load and run a non-release version of Santa.
Build and run a debug version of Santa.
```sh
rake reload:debug
bazel run :reload
```
Build and run a release version of Santa.
```sh
rake reload:release
bazel run :reload -c opt
```
#### Using Xcode
While Bazel is a very convenient and powerful build system, it can still be
useful to use Xcode for actually working on the code. If you'd like to use
Xcode you can use [Tulsi](https://tulsi.bazel.build) to generate an `.xcodeproj`
from the BUILD file which will use Bazel for actually doing the builds.
#### Debugging
Xcode and lldb can be used to debug Santa, just like any other project. Instead of clicking the play button to launch and attach to a process, you can attach to an already running, or soon to by running, component of Santa. To do this select the Debug menu and choose `Attach to Process by PID or Name… `. Below are the four components of Santa and who to debug the process as.
Xcode and lldb can be used to debug Santa, similarly to any other project, with
some exceptions. Instead of clicking the play button to launch and attach to a
process, you can attach to an already running, or soon to by running, component
of Santa. To do this select the Debug menu and choose `Attach to Process by PID
or Name… `. Below are the four components of Santa and who to debug the process
as.
Note: santa-driver (the kernel extension) cannot be debugged by attaching with Xcode.
Note: santa-driver (the kernel extension) cannot be debugged by attaching with
Xcode.
Note: Xcode can attach to santad without interruption, however any breakpoints in the decision making codepath can deadlock the machine. Using lldb directly to attach to santad will deadlock the machine.
Note: Xcode can attach to santad without interruption, however any breakpoints
in the decision making codepath can deadlock the machine. Using lldb directly
to attach to santad will deadlock the machine.
| process | user |
| -------- | ---- |
@@ -75,12 +110,17 @@ Note: Xcode can attach to santad without interruption, however any breakpoints i
| santactl | me |
| santabs | root |
Xcode will then wait for the process to start. Issue this command to restart all the Santa processes in debug mode.
Xcode will then wait for the process to start. Issue this command to restart
all the Santa processes in debug mode.
*The Santa (GUI) process is the only component of Santa that can be launched and debugged from Xcode directly. All the other components are launched with privileges and/or are scoped to an XPC service that launchd scopes to a hosting bundle. Thus the need for the `Attach to Process by PID or Name…` technique. See the [ipc](../details/ipc.md) document for for details.
*The Santa (GUI) process is the only component of Santa that can be launched
and debugged from Xcode directly. All the other components are launched with
privileges and/or are scoped to an XPC service that launchd scopes to a hosting
bundle. Thus the need for the `Attach to Process by PID or Name…` technique.
See the [ipc](../details/ipc.md) document for for details.
```sh
rake reload:debug
bazel run :reload
```
Now the process is attached in Xcode and you can debug your day away.
@@ -90,19 +130,21 @@ Now the process is attached in Xcode and you can debug your day away.
Run all the logic / unit tests
```sh
rake tests:logic
bazel test :logic_tests
```
Run all of santa-driver kernel extension tests
```sh
rake tests:kernel
bazel run :kernel_tests
```
#### Releases
Creates a release build of Santa with a version based of the newest tag. Also saves the dsym files for each component of Santa. This makes debugging and interpreting future crashes or kernel panics much easier.
Creates a release build of Santa with a version based of the newest tag. Also
saves the dsym files for each component of Santa. This makes debugging and
interpreting future crashes or kernel panics much easier.
```sh
rake dist
bazel run :release
```

4
Fuzzing/libFuzzer/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
bin
llvm-*.src
llvm-*.src.tar.xz

109
Fuzzing/libFuzzer/build.sh Executable file
View File

@@ -0,0 +1,109 @@
#!/usr/bin/env bash
LLVM_VERSION='5.0.1'
LLVM_COMPILERRT_TARBALL_NAME="llvm-${LLVM_VERSION}.src.tar.xz"
LLVM_COMPILERRT_SRC_FOLDER_NAME=`echo "${LLVM_COMPILERRT_TARBALL_NAME}" | cut -d '.' -f 1-4`
LLVM_COMPILERRT_TARBALL_URL="http://releases.llvm.org/${LLVM_VERSION}/${LLVM_COMPILERRT_TARBALL_NAME}"
LIBFUZZER_FOLDER="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
LOG_FILE=`mktemp`
main() {
echo "libFuzzer build script"
echo " > Checking dependencies..."
checkDependencies || return 1
echo " > Entering libFuzzer folder..."
cd "${LIBFUZZER_FOLDER}" > /dev/null 2>&1
if [ $? -ne 0 ] ; then
echo "Failed to enter the libFuzzer folder: ${LIBFUZZER_FOLDER}"
return 1
fi
if [ ! -f "${LLVM_COMPILERRT_TARBALL_NAME}" ] ; then
echo " > Downloading the LLVM tarball..."
curl "${LLVM_COMPILERRT_TARBALL_URL}" -o "${LLVM_COMPILERRT_TARBALL_NAME}" > "${LOG_FILE}" 2>&1
if [ $? -ne 0 ] ; then
dumpLogFile "Failed to download the LLVM tarball"
return 1
fi
else
echo " > An existing LLVM tarball was found"
fi
if [ -d "${LLVM_COMPILERRT_SRC_FOLDER_NAME}" ] ; then
echo " > Deleting existing LLVM folder..."
rm -rf "${LLVM_COMPILERRT_SRC_FOLDER_NAME}" > "${LOG_FILE}" 2>&1
if [ $? -ne 0 ] ; then
dumpLogFile "Failed to delete the existing source folder"
return 1
fi
fi
echo " > Extracting the LLVM tarball..."
tar xf "${LLVM_COMPILERRT_TARBALL_NAME}" > "${LOG_FILE}" 2>&1
if [ $? -ne 0 ] ; then
rm "${LLVM_COMPILERRT_TARBALL_NAME}" "${LLVM_COMPILERRT_SRC_FOLDER_NAME}"
dumpLogFile "Failed to extract the LLVM tarball"
return 1
fi
if [ -d "bin" ] ; then
echo " > Deleting existing bin folder..."
rm -rf "bin" > "${LOG_FILE}" 2>&1
if [ $? -ne 0 ] ; then
dumpLogFile "Failed to delete the existing bin folder"
return 1
fi
fi
mkdir "bin" > "${LOG_FILE}" 2>&1
if [ $? -ne 0 ] ; then
dumpLogFile "Failed to create the bin folder"
return 1
fi
echo " > Building libFuzzer..."
( cd "bin" && "../${LLVM_COMPILERRT_SRC_FOLDER_NAME}/lib/Fuzzer/build.sh" ) > "${LOG_FILE}" 2>&1
if [ $? -ne 0 ] ; then
dumpLogFile "Failed to build the library"
return 1
fi
printf "\nFinished building libFuzzer\n"
rm "${LOG_FILE}"
return 0
}
checkDependencies() {
executable_list=( "clang++" "curl" "tar" )
for executable in "${executable_list[@]}" ; do
which "${executable}" > /dev/null 2>&1
if [ $? -ne 0 ] ; then
echo "The following program was not found: ${executable}"
return 1
fi
done
return 0
}
dumpLogFile() {
if [ $# -eq 1 ] ; then
local message="$1"
else
local message="An error has occurred"
fi
printf "${message}\n"
printf "Log file follows\n===\n"
cat "${LOG_FILE}"
printf "\n===\n"
rm "${LOG_FILE}"
}
main $@
exit $?

3
Fuzzing/santacache/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
santacache.dSYM
santacache

Binary file not shown.

View File

@@ -0,0 +1,41 @@
/// Copyright 2018 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#include <SantaCache.h>
#include <iostream>
#include <cstdint>
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
static SantaCache<uint64_t, uint64_t> decision_cache(5000, 2);
std::uint64_t fields[2] = {};
if (size > 16) {
std::cout << "Invalid size! Start with -max_len=16\n";
return 1;
}
std::memcpy(fields, data, size);
decision_cache.set(fields[0], fields[1]);
auto returned_value = decision_cache.get(fields[0]);
if (returned_value != fields[1]) {
std::cout << fields[0] << ", " << fields[1] << " -> " << returned_value << "\n";
return 1;
}
return 0;
}

View File

@@ -0,0 +1,16 @@
{
"rules": [
{
"rule_type": "BINARY",
"policy": "BLACKLIST",
"sha256": "2dc104631939b4bdf5d6bccab76e166e37fe5e1605340cf68dab919df58b8eda",
"custom_msg": "blacklist firefox"
},
{
"rule_type": "CERTIFICATE",
"policy": "BLACKLIST",
"sha256": "e7726cf87cba9e25139465df5bd1557c8a8feed5c7dd338342d8da0959b63c8d",
"custom_msg": "blacklist dash app certificate"
}
]
}

View File

@@ -0,0 +1,62 @@
/// Copyright 2018 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#include <iostream>
#include <cstdint>
#include <vector>
#include <SNTCommandSyncRuleDownload.h>
#include <SNTCommandSyncState.h>
#include <SNTCommandSyncConstants.h>
#include <SNTRule.h>
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
NSData *buffer = [NSData dataWithBytes:static_cast<const void *>(data) length:size];
if (!buffer) {
return 0;
}
NSError *error;
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:buffer options:0 error:&error];
if (!response) {
return 0;
}
if (![response isKindOfClass:[NSDictionary class]]) {
return 0;
}
if (![response objectForKey:kRules]) {
return 0;
}
SNTCommandSyncState *state = [[SNTCommandSyncState alloc] init];
if (!state) {
return 0;
}
SNTCommandSyncRuleDownload *obj = [[SNTCommandSyncRuleDownload alloc] initWithState:state];
if (!obj) {
return 0;
}
for (NSDictionary *ruleDict in response[kRules]) {
SNTRule *rule = [obj ruleFromDictionary:ruleDict];
if (rule) {
std::cerr << "Rule: " << [[rule description] UTF8String] << "\n";
}
}
return 0;
}

View File

@@ -0,0 +1 @@
К'.p▒└G╗М┐║ЙSЮ╝и▌РУерЭxt1iАЫШ9ы*H╩4R"═©$-├Уww╙+Р╝╘[┼иу╧oС┬ОwRpЗя≤х°е

View File

@@ -0,0 +1,55 @@
/// Copyright 2018 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#include <iostream>
#include <cstdint>
#import <MOLXPCConnection/MOLXPCConnection.h>
#import "SNTCommandController.h"
#import "SNTRule.h"
#import "SNTXPCControlInterface.h"
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
if (size > 16) {
std::cerr << "Invalid buffer size of " << size
<< " (should be <= 16)" << std::endl;
return 1;
}
santa_vnode_id_t vnodeID = {};
std::memcpy(&vnodeID, data, size);
MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
daemonConn.invalidationHandler = ^{
printf("An error occurred communicating with the daemon, is it running?\n");
exit(1);
};
[daemonConn resume];
[[daemonConn remoteObjectProxy] checkCacheForVnodeID:vnodeID
withReply:^(santa_action_t action) {
if (action == ACTION_RESPOND_ALLOW) {
std::cerr << "File exists in [whitelist] kernel cache" << std::endl;;
} else if (action == ACTION_RESPOND_DENY) {
std::cerr << "File exists in [blacklist] kernel cache" << std::endl;;
} else if (action == ACTION_UNSET) {
std::cerr << "File does not exist in cache" << std::endl;;
}
}];
return 0;
}

View File

@@ -0,0 +1,51 @@
/// Copyright 2018 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#include <iostream>
#include <cstdint>
#import <MOLXPCConnection/MOLXPCConnection.h>
#import "SNTCommandController.h"
#import "SNTRule.h"
#import "SNTXPCControlInterface.h"
#pragma pack(push, 1)
#pragma pack(pop)
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
auto *eventId = reinterpret_cast<const std::uint64_t *>(data);
std::size_t eventIdCount = size / sizeof(std::uint64_t);
if (eventIdCount == 0) {
return 0;
}
MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
daemonConn.invalidationHandler = ^{
printf("An error occurred communicating with the daemon, is it running?\n");
exit(1);
};
[daemonConn resume];
NSMutableSet *eventIds = [NSMutableSet setWithCapacity:eventIdCount];
for (std::size_t i = 0; i < eventIdCount; i++) {
auto id = [NSNumber numberWithInteger:eventId[i]];
[eventIds addObject:id];
}
[[daemonConn remoteObjectProxy] databaseRemoveEventsWithIDs:[eventIds allObjects]];
return 0;
}

View File

@@ -0,0 +1,73 @@
/// Copyright 2018 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#include <iostream>
#include <cstdint>
#import <MOLXPCConnection/MOLXPCConnection.h>
#import "SNTCommandController.h"
#import "SNTRule.h"
#import "SNTXPCControlInterface.h"
#pragma pack(push, 1)
struct InputData {
std::uint32_t cleanSlate;
std::uint32_t state;
std::uint32_t type;
char hash[33];
};
#pragma pack(pop)
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
if (size > sizeof(InputData)) {
std::cerr << "Invalid buffer size of " << size
<< " (should be <= " << sizeof(InputData)
<< ")" << std::endl;
return 1;
}
InputData input_data = {};
std::memcpy(&input_data, data, size);
SNTRule *newRule = [[SNTRule alloc] init];
newRule.state = (SNTRuleState) input_data.state;
newRule.type = (SNTRuleType) input_data.type;
newRule.shasum = @(input_data.hash);
newRule.customMsg = @"";
MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
daemonConn.invalidationHandler = ^{
printf("An error occurred communicating with the daemon, is it running?\n");
exit(1);
};
[daemonConn resume];
[[daemonConn remoteObjectProxy] databaseRuleAddRules:@[newRule]
cleanSlate:NO
reply:^(NSError *error) {
if (!error) {
if (newRule.state == SNTRuleStateRemove) {
printf("Removed rule for SHA-256: %s.\n", [newRule.shasum UTF8String]);
} else {
printf("Added rule for SHA-256: %s.\n", [newRule.shasum UTF8String]);
}
}
}];
return 0;
}

54
Podfile
View File

@@ -1,54 +0,0 @@
platform :osx, "10.9"
inhibit_all_warnings!
target :Santa do
pod 'MOLCertificate'
pod 'MOLCodesignChecker'
end
target :santad do
pod 'FMDB'
pod 'MOLCertificate'
pod 'MOLCodesignChecker'
target :santabs do
pod 'FMDB'
pod 'MOLCertificate'
pod 'MOLCodesignChecker'
end
end
target :santactl do
pod 'FMDB'
pod 'MOLAuthenticatingURLSession'
pod 'MOLCertificate'
pod 'MOLCodesignChecker'
pod 'MOLFCMClient', '~> 1.3'
end
target :LogicTests do
pod 'FMDB'
pod 'MOLAuthenticatingURLSession'
pod 'MOLCertificate'
pod 'MOLCodesignChecker'
pod 'OCMock'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name != 'Release' then
break
end
# This is necessary to get FMDB to not NSLog stuff.
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ''
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] <<= "NDEBUG=1"
# Enable more compiler optimizations.
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = 'fast'
config.build_settings['LLVM_LTO'] = 'YES'
end
end
end

View File

@@ -1,32 +0,0 @@
PODS:
- FMDB (2.7.2):
- FMDB/standard (= 2.7.2)
- FMDB/standard (2.7.2)
- MOLAuthenticatingURLSession (2.4):
- MOLCertificate (~> 1.8)
- MOLCertificate (1.8)
- MOLCodesignChecker (1.9):
- MOLCertificate (~> 1.8)
- MOLFCMClient (1.7):
- MOLAuthenticatingURLSession (~> 2.4)
- OCMock (3.4.1)
DEPENDENCIES:
- FMDB
- MOLAuthenticatingURLSession
- MOLCertificate
- MOLCodesignChecker
- MOLFCMClient (~> 1.3)
- OCMock
SPEC CHECKSUMS:
FMDB: 6198a90e7b6900cfc046e6bc0ef6ebb7be9236aa
MOLAuthenticatingURLSession: c238aa1c9a7b1077eb39a6f40204bfe76a7d204e
MOLCertificate: c999513316d511c69f290fbf313dfe8dca4ad592
MOLCodesignChecker: 303c01755646a0045c97f9f0b0fe5945ead42130
MOLFCMClient: ee45348909351f232e2759c580329072ae7e02d4
OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3
PODFILE CHECKSUM: acd378b3727c923d912e09812da344f7375c14fe
COCOAPODS: 1.4.0

245
README.md
View File

@@ -1,54 +1,82 @@
Santa
[![Build Status](https://travis-ci.org/google/santa.png?branch=master)](https://travis-ci.org/google/santa)
[![Documentation Status](https://readthedocs.org/projects/santa/badge/?version=latest)](https://santa.readthedocs.io/en/latest/?badge=latest)
=====
# Santa [![Build Status][build-status-img]][build-status-link] [![Documentation Status][doc-status-img]][doc-status-link]
[build-status-img]: https://travis-ci.org/google/santa.png?branch=master
[build-status-link]: https://travis-ci.org/google/santa
[doc-status-img]: https://readthedocs.org/projects/santa/badge/?version=latest
[doc-status-link]: https://santa.readthedocs.io/en/latest/?badge=latest
<p align="center">
<a href="#santa--">
<img src="./Source/SantaGUI/Resources/Images.xcassets/AppIcon.appiconset/santa-hat-icon-128.png" alt="Santa Icon" />
</a>
<img src="./Source/SantaGUI/Resources/Images.xcassets/AppIcon.appiconset/santa-hat-icon-128.png" alt="Santa Icon" />
</p>
Santa is a binary whitelisting/blacklisting system for macOS. It consists of
a kernel extension that monitors for executions, a userland daemon that makes
execution decisions based on the contents of a SQLite database, a GUI agent that
notifies the user in case of a block decision and a command-line utility for
managing the system and synchronizing the database with a server.
Santa is not yet at 1.0. We're writing more tests, fixing bugs, working on TODOs
and finishing up a security audit.
Santa is a binary whitelisting/blacklisting system for macOS. It consists of a
kernel extension that monitors for executions, a userland daemon that makes
execution decisions based on the contents of a SQLite database, a GUI agent
that notifies the user in case of a block decision and a command-line utility
for managing the system and synchronizing the database with a server.
It is named Santa because it keeps track of binaries that are naughty or nice.
Santa is a project of Google's Macintosh Operations Team.
Docs
========
The Santa docs are stored in the [Docs](https://github.com/google/santa/blob/master/Docs) directory. A Read the Docs instance is available here: https://santa.readthedocs.io.
# Docs
Admin-Related Features
========
The Santa docs are stored in the
[Docs](https://github.com/google/santa/blob/master/Docs) directory. A Read the
Docs instance is available here: https://santa.readthedocs.io.
* Multiple modes: In the default MONITOR mode, all binaries except
those marked as blacklisted will be allowed to run, whilst being logged and recorded in the events database. In LOCKDOWN mode, only whitelisted binaries are
allowed to run.
The docs include deployment options, details on how parts of Santa work and
instructions for developing Santa itself.
* Event logging: When the kext is loaded, all binary launches are logged.
When in either mode, all unknown or denied binaries are stored in the database to enable later aggregation.
# Get Help
* Certificate-based rules, with override levels: Instead of relying on a binary's hash (or 'fingerprint'), executables can be whitelisted/blacklisted by their signing
certificate. You can therefore trust/block all binaries by a given publisher that were signed with that cert across version updates. A
binary can only be whitelisted by its certificate if its signature validates
correctly, but a rule for a binary's fingerprint will override a decision for a
certificate; i.e. you can whitelist a certificate while blacklisting a binary
signed with that certificate, or vice-versa.
If you have questions or otherwise need help getting started,
the [santa-dev](https://groups.google.com/forum/#!forum/santa-dev) group is a
great place.
* Path-based rules (via NSRegularExpression/ICU): This allows a similar feature to that found in Managed Client (the precursor to configuration profiles, which used the same implementation mechanism), Application Launch Restrictions via the mcxalr binary. This implementation carries the added benefit of being configurable via regex, and not relying on LaunchServices. As detailed in the wiki, when evaluating rules this holds the lowest precendence.
If you believe you have a bug, feel free to report [an
issue](https://github.com/google/santa/isues) and we'll respond as soon as we
can.
* Failsafe cert rules: You cannot put in a deny rule that would block the certificate used to sign launchd, a.k.a. pid 1, and therefore all components used in macOS. The binaries in every OS update (and in some cases entire new versions) are therefore auto-whitelisted. This does not affect binaries from Apple's App Store, which use various certs that change regularly for common apps. Likewise, you cannot blacklist Santa itself, and Santa uses a distinct separate cert than other Google apps.
Intentions and Expectations
===========================
# Admin-Related Features
* Multiple modes: In the default MONITOR mode, all binaries except those marked
as blacklisted will be allowed to run, whilst being logged and recorded in
the events database. In LOCKDOWN mode, only whitelisted binaries are allowed
to run.
* Event logging: When the kext is loaded, all binary launches are logged. When
in either mode, all unknown or denied binaries are stored in the database to
enable later aggregation.
* Certificate-based rules, with override levels: Instead of relying on a
binary's hash (or 'fingerprint'), executables can be whitelisted/blacklisted
by their signing certificate. You can therefore trust/block all binaries by a
given publisher that were signed with that cert across version updates. A
binary can only be whitelisted by its certificate if its signature validates
correctly, but a rule for a binary's fingerprint will override a decision for
a certificate; i.e. you can whitelist a certificate while blacklisting a
binary signed with that certificate, or vice-versa.
* Path-based rules (via NSRegularExpression/ICU): This allows a similar feature
to that found in Managed Client (the precursor to configuration profiles,
which used the same implementation mechanism), Application Launch
Restrictions via the mcxalr binary. This implementation carries the added
benefit of being configurable via regex, and not relying on LaunchServices.
As detailed in the wiki, when evaluating rules this holds the lowest
precedence.
* Failsafe cert rules: You cannot put in a deny rule that would block the
certificate used to sign launchd, a.k.a. pid 1, and therefore all components
used in macOS. The binaries in every OS update (and in some cases entire new
versions) are therefore auto-whitelisted. This does not affect binaries from
Apple's App Store, which use various certs that change regularly for common
apps. Likewise, you cannot blacklist Santa itself, and Santa uses a distinct
separate cert than other Google apps.
# Intentions and Expectations
No single system or process will stop *all* attacks, or provide 100% security.
Santa is written with the intention of helping protect users from themselves.
People often download malware and trust it, giving the malware credentials, or
@@ -57,120 +85,99 @@ centrally managed component, Santa can help stop the spread of malware among a
large fleet of machines. Independently, Santa can aid in analyzing what is
running on your computer.
Santa is part of a defense-in-depth strategy, and you should continue to protect
hosts in whatever other ways you see fit.
Santa is part of a defense-in-depth strategy, and you should continue to
protect hosts in whatever other ways you see fit.
Get Help
========
If you have questions or otherwise need help getting started, the
[santa-dev](https://groups.google.com/forum/#!forum/santa-dev) group is a
great place. Please consult the [wiki](https://github.com/google/santa/wiki) and [issues](https://github.com/google/santa/issues) as well.
# Security and Performance-Related Features
Security and Performance-Related Features
============
* In-kernel caching: whitelisted binaries are cached in the kernel so the
processing required to make a request is only done if the binary
isn't already cached.
processing required to make a request is only done if the binary isn't
already cached.
* Userland components validate each other: each of the userland components (the
daemon, the GUI agent and the command-line utility) communicate with each other
using XPC and check that their signing certificates are identical before any
communication is accepted.
daemon, the GUI agent and the command-line utility) communicate with each
other using XPC and check that their signing certificates are identical
before any communication is accepted.
* Kext uses only KPIs: the kernel extension only uses provided kernel
programming interfaces to do its job. This means that the kext code should
continue to work across OS versions.
programming interfaces to do its job. This means that the kext code should
continue to work across OS versions.
Known Issues
============
Santa is not yet at 1.0 and we have some known issues to be aware of:
# Known Issues
* Santa only blocks execution (execve and variants), it doesn't protect against
dynamic libraries loaded with dlopen, libraries on disk that have been replaced, or
libraries loaded using `DYLD_INSERT_LIBRARIES`. As of version 0.9.1 we *do* address [__PAGEZERO missing issues](b87482e) that were exploited in some versions of macOS. We are working on also protecting against similar avenues of attack.
dynamic libraries loaded with dlopen, libraries on disk that have been
replaced, or libraries loaded using `DYLD_INSERT_LIBRARIES`. As of version
0.9.1 we *do* address [__PAGEZERO missing issues](b87482e) that were
exploited in some versions of macOS. We are working on also protecting
against similar avenues of attack.
* Kext communication security: the kext will only accept a connection from a
single client at a time and said client must be running as root. We haven't yet
found a good way to ensure the kext only accepts connections from a valid client.
single client at a time and said client must be running as root. We haven't
yet found a good way to ensure the kext only accepts connections from a valid
client.
* Database protection: the SQLite database is installed with permissions so that
only the root user can read/write it. We're considering approaches to secure
this further.
* Sync client: The `santactl` command-line client includes a flag to synchronize with a management server, which uploads events that have occurred on the
machine and downloads new rules. We're still very heavily working on this
server (which is AppEngine-based and will be open-sourced in the future), so the
sync client code is unfinished. It does show the 'API' that we're expecting to
use so if you'd like to write your own management server, feel free to look at
how the client currently works (and suggest changes!)
* Database protection: the SQLite database is installed with permissions so
that only the root user can read/write it. We're considering approaches to
secure this further.
* Scripts: Santa is currently written to ignore any execution that isn't a
binary. This is because after weighing the administration cost vs the benefit,
we found it wasn't worthwhile. Additionally, a number of applications make use
of temporary generated scripts, which we can't possibly whitelist and not doing
so would cause problems. We're happy to revisit this (or at least make it an
option) if it would be useful to others.
binary. This is because after weighing the administration cost vs the
benefit, we found it wasn't worthwhile. Additionally, a number of
applications make use of temporary generated scripts, which we can't possibly
whitelist and not doing so would cause problems. We're happy to revisit this
(or at least make it an option) if it would be useful to others.
* Documentation: This is currently limited.
# Sync Servers
* Tests: There aren't enough of them.
* The `santactl` command-line client includes a flag to synchronize with a
management server, which uploads events that have occurred on the machine and
downloads new rules. There are several open-source servers you can sync with:
Screenshots
===========
* [Upvote](https://github.com/google/upvote) - An AppEngine-based server
that implements social voting to make managing a large fleet easier.
* [Moroz](https://github.com/groob/moroz) - A simple golang server that
serves hardcoded rules from simple configuration files.
* [Zentral](https://github.com/zentralopensource/zentral/wiki) - A
centralized service that pulls data from multiple sources and deploy
configurations to multiple services.
A tool like Santa doesn't really lend itself to screenshots, so here's a video instead.
* Alternatively, `santactl` can configure rules locally (without a sync
server).
<p align="center">
<img src="https://zippy.gfycat.com/MadFatalAmphiuma.gif" alt="Santa Block Video" />
</p>
# Screenshots
Building
========
Firstly, make sure you're using Xcode 7.3.1 as currently we do not support
building with Xcode 8.
A tool like Santa doesn't really lend itself to screenshots, so here's a video
instead.
```sh
git clone https://github.com/google/santa
cd santa
<p align="center"> <img src="https://zippy.gfycat.com/MadFatalAmphiuma.gif"
alt="Santa Block Video" /> </p>
# Build a debug build. This will install any necessary CocoaPods, create the
# workspace and build, outputting the full log only if an error occurred.
# If CocoaPods is not installed, you'll be prompted to install it.
#
# For other build/install/run options, run rake without any arguments
rake build:debug
```
Note: the Xcode project is setup to use any installed "Mac Developer" certificate
and for security-reasons parts of Santa will not operate properly if not signed.
For more details on building see the [building.md](https://github.com/google/santa/blob/master/Docs/development/building.md) document.
Kext Signing
============
# Kext Signing
Kernel extensions on macOS 10.9 and later must be signed using an Apple-provided
Developer ID certificate with a kernel extension flag. Without it, the only way
to load an extension is to enable kext-dev-mode or disable SIP, depending on the
OS version.
to load an extension is to enable kext-dev-mode or disable SIP, depending on
the OS version.
There are two possible solutions for this, for distribution purposes:
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.
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.
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.
Contributing
============
Patches to this project are very much welcome. Please see the [CONTRIBUTING](https://github.com/google/santa/blob/master/CONTRIBUTING.md)
# Contributing
Patches to this project are very much welcome. Please see the
[CONTRIBUTING](https://github.com/google/santa/blob/master/CONTRIBUTING.md)
file.
Disclaimer
==========
# Disclaimer
This is **not** an official Google product.

225
Rakefile
View File

@@ -1,225 +0,0 @@
require 'openssl'
WORKSPACE = 'Santa.xcworkspace'
DEFAULT_SCHEME = 'All'
OUTPUT_PATH = 'Build'
BINARIES = ['Santa.app', 'santa-driver.kext']
DSYMS = ['Santa.app.dSYM', 'santa-driver.kext.dSYM', 'santad.dSYM', 'santactl.dSYM']
XCPRETTY_DEFAULTS = '-sc'
XCODEBUILD_DEFAULTS = "-workspace #{WORKSPACE} -derivedDataPath #{OUTPUT_PATH} -parallelizeTargets"
DEVTEAM_FILE = 'Source/DevelopmentTeam.xcconfig'
DEVTEAM_CERT_CN = 'Mac Developer'
$DISABLE_XCPRETTY = false
task :default do
system("rake -sT")
end
def xcodebuild(opts)
command = "xcodebuild #{XCODEBUILD_DEFAULTS} #{opts}"
if not $DISABLE_XCPRETTY
command << " | xcpretty #{XCPRETTY_DEFAULTS} && exit ${PIPESTATUS[0]}"
end
if system command
puts "\e[32mPass\e[0m"
else
raise "\e[31mFail\e[0m"
end
end
def xcodebuilddir
if not $xcode_build_dir
output = `xcodebuild #{XCODEBUILD_DEFAULTS} -scheme All -showBuildSettings`
if match = output.match(/BUILD_DIR = (.*)/)
$xcode_build_dir = match.captures.first
puts "Found Xcode build dir #{$xcode_build_dir}"
end
end
$xcode_build_dir
end
task :init do
unless File.exists?(WORKSPACE) and File.exists?('Pods')
puts "Pods missing, running 'pod install'"
system "pod install" or raise "CocoaPods is not installed. Install with 'sudo gem install cocoapods'"
end
unless system 'xcpretty -v >/dev/null 2>&1'
puts "xcpretty is not installed. Install with 'sudo gem install xcpretty'"
$DISABLE_XCPRETTY = true
end
cert_pem = `security find-certificate -p -c '#{DEVTEAM_CERT_CN}'`
cert = OpenSSL::X509::Certificate.new cert_pem
team_id = cert.subject.to_a.find {|f| f[0] == "OU"}[1]
File.open(DEVTEAM_FILE, 'w') { |f|
f.puts("// This file is auto-generated. Do not edit manually")
f.puts("DEVELOPMENT_TEAM = #{team_id}")
}
end
task :remove_existing do
system 'sudo rm -rf /Library/Extensions/santa-driver.kext'
system 'sudo rm -rf /Applications/Santa.app'
end
desc "Clean"
task :clean => :init do
puts "Cleaning"
FileUtils.rm_rf(OUTPUT_PATH)
xcodebuild("-scheme All clean")
end
# Build
namespace :build do
desc "Build: Debug"
task :debug do
Rake::Task['build:build'].invoke("Debug")
end
desc "Build: Release"
task :release do
Rake::Task['build:build'].invoke("Release")
end
task :build, [:configuration] => :init do |t, args|
config = args[:configuration]
puts "Building with configuration: #{config}"
xcodebuild("-scheme All -configuration #{config} build")
end
end
# Install
namespace :install do
desc "Install: Debug"
task :debug do
Rake::Task['install:install'].invoke("Debug")
end
desc "Install: Release"
task :release do
Rake::Task['install:install'].invoke("Release")
end
task :install, [:configuration] do |t, args|
config = args[:configuration]
system 'sudo cp conf/com.google.santad.plist /Library/LaunchDaemons'
system 'sudo cp conf/com.google.santagui.plist /Library/LaunchAgents'
system 'sudo cp conf/com.google.santa.asl.conf /etc/asl'
system '/usr/bin/killall -HUP syslogd'
Rake::Task['build:build'].invoke(config)
puts "Installing with configuration: #{config}"
Rake::Task['remove_existing'].invoke()
system "sudo cp -r #{xcodebuilddir}/#{config}/santa-driver.kext /Library/Extensions"
system "sudo cp -r #{xcodebuilddir}/#{config}/Santa.app /Applications"
end
end
# Dist
task :dist do
desc "Create distribution folder"
Rake::Task['clean'].invoke()
Rake::Task['build:build'].invoke("Release")
dist_path = "santa-#{`defaults read #{xcodebuilddir}/Release/santa-driver.kext/Contents/Info.plist CFBundleVersion`.strip}"
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("#{xcodebuilddir}/Release/#{x}", "#{dist_path}/binaries")
end
DSYMS.each do |x|
FileUtils.cp_r("#{xcodebuilddir}/Release/#{x}", "#{dist_path}/dsym")
end
Dir.glob("Conf/*") {|x| File.directory?(x) or FileUtils.cp(x, "#{dist_path}/conf")}
puts "Distribution folder #{dist_path} created"
end
# Tests
namespace :tests do
desc "Tests: Logic"
task :logic => [:init] do
puts "Running logic tests"
xcodebuild("-scheme LogicTests test")
end
desc "Tests: Kernel"
task :kernel do
Rake::Task['unload'].invoke()
Rake::Task['install:debug'].invoke()
Rake::Task['load_kext'].invoke
FileUtils.mkdir_p("/tmp/santa_kerneltests_tmp")
begin
puts "\033[?25l\033[12h" # hide cursor
puts "Running kernel tests"
system "cd /tmp/santa_kerneltests_tmp && sudo #{xcodebuilddir}/Debug/KernelTests"
rescue Exception
ensure
puts "\033[?25h\033[12l\n\n" # unhide cursor
FileUtils.rm_rf("/tmp/santa_kerneltests_tmp")
Rake::Task['unload_kext'].execute
end
end
end
# Load/Unload
task :unload_daemon do
puts "Unloading daemon"
system "sudo launchctl unload /Library/LaunchDaemons/com.google.santad.plist 2>/dev/null"
end
task :unload_kext do
puts "Unloading kernel extension"
system "sudo kextunload -b com.google.santa-driver 2>/dev/null"
end
task :unload_gui do
puts "Unloading GUI agent"
system "launchctl unload /Library/LaunchAgents/com.google.santagui.plist 2>/dev/null"
end
desc "Unload"
task :unload => [:unload_daemon, :unload_kext, :unload_gui]
task :load_daemon do
puts "Loading daemon"
system "sudo launchctl load /Library/LaunchDaemons/com.google.santad.plist"
end
task :load_kext do
puts "Loading kernel extension"
system "sudo kextload /Library/Extensions/santa-driver.kext"
end
task :load_gui do
puts "Loading GUI agent"
system "launchctl load /Library/LaunchAgents/com.google.santagui.plist 2>/dev/null"
end
desc "Load"
task :load => [:load_kext, :load_daemon, :load_gui]
namespace :reload do
desc "Reload: Debug"
task :debug do
Rake::Task['unload'].invoke()
Rake::Task['install:debug'].invoke()
Rake::Task['load'].invoke()
end
desc "Reload: Release"
task :release do
Rake::Task['unload'].invoke()
Rake::Task['install:release'].invoke()
Rake::Task['load'].invoke()
end
end

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?><Workspace version='1.0'><FileRef location='group:Santa.xcodeproj'/><FileRef location='group:Pods/Pods.xcodeproj'/></Workspace>

54
Source/SantaGUI/BUILD Normal file
View File

@@ -0,0 +1,54 @@
licenses(["notice"]) # Apache 2.0
exports_files([
"Resources/Images.xcassets/AppIcon.appiconset/santa-hat-icon-256.png",
])
load("@build_bazel_rules_apple//apple:macos.bzl", "macos_application")
objc_library(
name = "SantaGUI_lib",
srcs = [
"SNTAboutWindowController.h",
"SNTAboutWindowController.m",
"SNTAccessibleTextField.h",
"SNTAccessibleTextField.m",
"SNTAppDelegate.h",
"SNTAppDelegate.m",
"SNTMessageWindow.h",
"SNTMessageWindow.m",
"SNTMessageWindowController.h",
"SNTMessageWindowController.m",
"SNTNotificationManager.h",
"SNTNotificationManager.m",
"main.m",
],
data = [
"Resources/AboutWindow.xib",
"Resources/MessageWindow.xib",
],
sdk_frameworks = [
"IOKit",
"SecurityInterface",
],
deps = [
"//Source/common:SNTBlockMessage_SantaGUI",
"//Source/common:SNTConfigurator",
"//Source/common:SNTXPCControlInterface",
"//Source/common:SNTXPCNotifierInterface",
"@MOLCodesignChecker",
"@MOLXPCConnection",
],
)
macos_application(
name = "SantaGUI",
app_icons = glob(["Resources/Images.xcassets/**"]),
bundle_id = "com.google.SantaGUI",
bundle_name = "Santa",
infoplists = ["Resources/SantaGUI-Info.plist"],
minimum_os_version = "10.9",
version = "//:version",
visibility = ["//visibility:public"],
deps = [":SantaGUI_lib"],
)

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="16D32" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SNTAboutWindowController">
@@ -13,10 +13,10 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Santa" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="F0z-JX-Cv5">
<window title="Santa" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="200"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<rect key="screenRect" x="0.0" y="0.0" width="3840" height="1577"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="480" height="200"/>
<autoresizingMask key="autoresizingMask"/>
@@ -29,12 +29,13 @@
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Santa" id="VVj-gU-bzy">
<font key="font" size="34" name="HelveticaNeue-UltraLight"/>
<color key="textColor" red="0.1869618941" green="0.1869618941" blue="0.1869618941" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uh6-q0-RzL">
<rect key="frame" x="18" y="65" width="444" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" id="CcT-ul-1eA">
<font key="font" metaFont="system"/>
<string key="title">Santa is an application whitelisting system for macOS.

View File

@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="16F73" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<development version="6300" identifier="xcode"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SNTMessageWindowController">
@@ -19,16 +18,17 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Santa Blocked Execution" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="none" id="9Bq-yh-54f" customClass="SNTMessageWindow">
<window title="Santa Blocked Execution" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" visibleAtLaunch="NO" animationBehavior="none" id="9Bq-yh-54f" customClass="SNTMessageWindow">
<windowStyleMask key="styleMask" utility="YES"/>
<rect key="contentRect" x="167" y="107" width="540" height="479"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<rect key="screenRect" x="0.0" y="0.0" width="3840" height="1577"/>
<view key="contentView" id="Iwq-Lx-rLv">
<rect key="frame" x="0.0" y="0.0" width="540" height="479"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kiB-jZ-69S">
<rect key="frame" x="16" y="451" width="37" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Hidden Button" alternateTitle="This button exists so neither of the other two buttons is pre-selected when the dialog opens." bezelStyle="rounded" alignment="center" borderStyle="border" focusRingType="none" transparent="YES" imageScaling="proportionallyDown" inset="2" id="XGa-Sl-F4t">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@@ -40,28 +40,14 @@
<outlet property="nextKeyView" destination="7ua-5a-uSd" id="vl5-A8-O0H"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="t8c-Fx-e5h">
<rect key="frame" x="228" y="408" width="85" height="41"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" refusesFirstResponder="YES" sendsActionOnEndEditing="YES" title="Santa" id="7YA-iB-Zma">
<font key="font" metaFont="systemUltraLight" size="34"/>
<color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
</userDefinedRuntimeAttributes>
</textFieldCell>
<connections>
<outlet property="nextKeyView" destination="7ua-5a-uSd" id="z5y-RR-IEH"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cD5-Su-lXR" customClass="SNTAccessibleTextField">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cD5-Su-lXR" customClass="SNTAccessibleTextField">
<rect key="frame" x="43" y="369" width="454" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="450" id="XgJ-EV-tBa"/>
</constraints>
<textFieldCell key="cell" selectable="YES" refusesFirstResponder="YES" 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"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
@@ -104,7 +90,7 @@
</constraints>
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Binary Name" id="E7T-9h-ofr">
<font key="font" metaFont="system"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
@@ -129,7 +115,7 @@
</constraints>
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Code signing information" placeholderString="" id="ztA-La-XgT">
<font key="font" metaFont="system"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
@@ -180,7 +166,7 @@
</constraints>
<textFieldCell key="cell" lineBreakMode="charWrapping" selectable="YES" sendsActionOnEndEditing="YES" title="SHA-256" id="X4W-9e-eIu">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
@@ -226,7 +212,7 @@
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Parent Name" id="ieo-WK-aDD">
<font key="font" metaFont="system"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
@@ -254,7 +240,7 @@
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="7ua-5a-uSd">
<rect key="frame" x="154" y="33" width="112" height="25"/>
<rect key="frame" x="154" y="34" width="112" height="23"/>
<constraints>
<constraint firstAttribute="width" priority="900" constant="112" id="Pec-Pa-4aZ"/>
</constraints>
@@ -278,7 +264,7 @@ DQ
</constraints>
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Binary Path" id="H1b-Ui-CYo">
<font key="font" metaFont="system"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
@@ -299,7 +285,7 @@ DQ
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="BbV-3h-mmL" userLabel="Dismiss Button">
<rect key="frame" x="278" y="33" width="110" height="25"/>
<rect key="frame" x="278" y="34" width="110" height="23"/>
<constraints>
<constraint firstAttribute="width" constant="110" id="6Uh-Bd-N64"/>
<constraint firstAttribute="height" constant="22" id="GH6-nw-6rD"/>
@@ -325,7 +311,7 @@ DQ
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Executing User" id="HRT-Be-ePf">
<font key="font" metaFont="system"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
@@ -349,7 +335,7 @@ DQ
</constraints>
<textFieldCell key="cell" lineBreakMode="charWrapping" selectable="YES" sendsActionOnEndEditing="YES" title="Calculating..." id="yJa-yL-X9a">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
@@ -366,11 +352,11 @@ DQ
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1000 related binaries" id="AVM-vB-hB8">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<box horizontalHuggingPriority="750" title="Line" boxType="custom" borderType="line" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="4Li-ul-zIi">
<box horizontalHuggingPriority="750" boxType="custom" borderType="line" title="Line" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="4Li-ul-zIi">
<rect key="frame" x="168" y="132" width="1" height="207"/>
<constraints>
<constraint firstAttribute="width" constant="1" id="0o1-Jh-epf"/>
@@ -386,7 +372,7 @@ DQ
</constraints>
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="Application Name" id="3UG-ca-d1k">
<font key="font" metaFont="systemBold"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
@@ -418,6 +404,20 @@ DQ
</binding>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="t8c-Fx-e5h">
<rect key="frame" x="229" y="408" width="82" height="41"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" refusesFirstResponder="YES" sendsActionOnEndEditing="YES" title="Santa" id="7YA-iB-Zma">
<font key="font" metaFont="systemUltraLight" size="34"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="accessibilityElement" value="NO"/>
</userDefinedRuntimeAttributes>
</textFieldCell>
<connections>
<outlet property="nextKeyView" destination="7ua-5a-uSd" id="z5y-RR-IEH"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstItem="oFj-ol-xpL" firstAttribute="leading" secondItem="Iwq-Lx-rLv" secondAttribute="leading" constant="10" id="0AD-PS-5V1"/>

View File

@@ -9,20 +9,24 @@
<key>NSHumanReadableCopyright</key>
<string>Google, Inc.</string>
<key>CFBundleIdentifier</key>
<string>com.google.${PRODUCT_NAME:rfc1034identifier}GUI</string>
<string>com.google.SantaGUI</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<string>Santa</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<string>Santa</string>
<key>CFBundleVersion</key>
<string>TO.BE.FILLED</string>
<string>${SANTA_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>TO.BE.FILLED</string>
<string>${SANTA_VERSION}</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<string>${MACOSX_VERSION_MIN}</string>
<key>LSUIElement</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
</dict>
</plist>

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Cocoa;
#import <Cocoa/Cocoa.h>
@interface SNTAboutWindowController : NSWindowController

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTAboutWindowController.h"
#import "Source/SantaGUI/SNTAboutWindowController.h"
#import "SNTConfigurator.h"
#import "Source/common/SNTConfigurator.h"
@implementation SNTAboutWindowController

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Cocoa;
#import <Cocoa/Cocoa.h>
/**
An NSTextField subclass that provides an accessiblity label equal to:

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTAccessibleTextField.h"
#import "Source/SantaGUI/SNTAccessibleTextField.h"
@implementation SNTAccessibleTextField

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Cocoa;
#import <Cocoa/Cocoa.h>
///
/// Initiates and manages the connection to santad

View File

@@ -12,20 +12,21 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTAppDelegate.h"
#import "Source/SantaGUI/SNTAppDelegate.h"
#import "SNTAboutWindowController.h"
#import "SNTConfigurator.h"
#import "SNTNotificationManager.h"
#import "SNTStrengthify.h"
#import "SNTXPCConnection.h"
#import "SNTXPCControlInterface.h"
#import <MOLXPCConnection/MOLXPCConnection.h>
#import "Source/common/SNTConfigurator.h"
#import "Source/common/SNTStrengthify.h"
#import "Source/common/SNTXPCControlInterface.h"
#import "Source/SantaGUI/SNTAboutWindowController.h"
#import "Source/SantaGUI/SNTNotificationManager.h"
@interface SNTAppDelegate ()
@property SNTAboutWindowController *aboutWindowController;
@property SNTNotificationManager *notificationManager;
@property SNTXPCConnection *daemonListener;
@property SNTXPCConnection *bundleListener;
@property MOLXPCConnection *daemonListener;
@property MOLXPCConnection *bundleListener;
@end
@implementation SNTAppDelegate
@@ -45,12 +46,17 @@
self.daemonListener.invalidationHandler = nil;
[self.daemonListener invalidate];
self.daemonListener = nil;
self.bundleListener.invalidationHandler = nil;
[self.bundleListener invalidate];
self.bundleListener = nil;
}];
[workspaceNotifications addObserverForName:NSWorkspaceSessionDidBecomeActiveNotification
object:nil
queue:[NSOperationQueue currentQueue]
usingBlock:^(NSNotification *note) {
[self attemptDaemonReconnection];
[self attemptBundleReconnection];
}];
[self createDaemonConnection];
@@ -72,8 +78,8 @@
// Create listener for return connection from daemon.
NSXPCListener *listener = [NSXPCListener anonymousListener];
self.daemonListener = [[SNTXPCConnection alloc] initServerWithListener:listener];
self.daemonListener.exportedInterface = [SNTXPCNotifierInterface notifierInterface];
self.daemonListener = [[MOLXPCConnection alloc] initServerWithListener:listener];
self.daemonListener.privilegedInterface = [SNTXPCNotifierInterface notifierInterface];
self.daemonListener.exportedObject = self.notificationManager;
self.daemonListener.acceptedHandler = ^{
dispatch_semaphore_signal(sema);
@@ -85,9 +91,10 @@
[self.daemonListener resume];
// Tell daemon to connect back to the above listener.
SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
[daemonConn resume];
[[daemonConn remoteObjectProxy] setNotificationListener:listener.endpoint];
[daemonConn invalidate];
// Now wait for the connection to come in.
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
@@ -96,6 +103,8 @@
}
- (void)attemptDaemonReconnection {
self.daemonListener.invalidationHandler = nil;
[self.daemonListener invalidate];
[self performSelectorInBackground:@selector(createDaemonConnection) withObject:nil];
}
@@ -106,8 +115,8 @@
// Create listener for return connection from the bundle service.
NSXPCListener *listener = [NSXPCListener anonymousListener];
self.bundleListener = [[SNTXPCConnection alloc] initServerWithListener:listener];
self.bundleListener.exportedInterface = [SNTXPCNotifierInterface bundleNotifierInterface];
self.bundleListener = [[MOLXPCConnection alloc] initServerWithListener:listener];
self.bundleListener.privilegedInterface = [SNTXPCNotifierInterface bundleNotifierInterface];
self.bundleListener.exportedObject = self.notificationManager;
self.bundleListener.acceptedHandler = ^{
dispatch_semaphore_signal(sema);
@@ -119,9 +128,10 @@
[self.bundleListener resume];
// Tell santabs to connect back to the above listener.
SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
[daemonConn resume];
[[daemonConn remoteObjectProxy] setBundleNotificationListener:listener.endpoint];
[daemonConn invalidate];
// Now wait for the connection to come in.
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
@@ -130,6 +140,8 @@
}
- (void)attemptBundleReconnection {
self.bundleListener.invalidationHandler = nil;
[self.bundleListener invalidate];
[self performSelectorInBackground:@selector(createBundleConnection) withObject:nil];
}

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Cocoa;
#import <Cocoa/Cocoa.h>
///
/// An NSPanel that can become key/main and can fade in/out.

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTMessageWindow.h"
#import "Source/SantaGUI/SNTMessageWindow.h"
@implementation SNTMessageWindow

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Cocoa;
#import <Cocoa/Cocoa.h>
@class SNTStoredEvent;

View File

@@ -12,16 +12,15 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTMessageWindowController.h"
@import SecurityInterface.SFCertificatePanel;
#import "Source/SantaGUI/SNTMessageWindowController.h"
#import <MOLCertificate/MOLCertificate.h>
#import <SecurityInterface/SFCertificatePanel.h>
#import "SNTBlockMessage.h"
#import "SNTConfigurator.h"
#import "SNTMessageWindow.h"
#import "SNTStoredEvent.h"
#import "Source/common/SNTBlockMessage.h"
#import "Source/common/SNTConfigurator.h"
#import "Source/common/SNTStoredEvent.h"
#import "Source/SantaGUI/SNTMessageWindow.h"
@interface SNTMessageWindowController ()
/// The custom message to display for this event

View File

@@ -12,10 +12,10 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Cocoa;
#import <Cocoa/Cocoa.h>
#import "SNTMessageWindowController.h"
#import "SNTXPCNotifierInterface.h"
#import "Source/common/SNTXPCNotifierInterface.h"
#import "Source/SantaGUI/SNTMessageWindowController.h"
///
/// Keeps track of pending notifications and ensures only one is presented to the user at a time.

View File

@@ -12,15 +12,16 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTNotificationManager.h"
#import "Source/SantaGUI/SNTNotificationManager.h"
#import "SNTBlockMessage.h"
#import "SNTConfigurator.h"
#import "SNTLogging.h"
#import "SNTStoredEvent.h"
#import "SNTStrengthify.h"
#import "SNTXPCConnection.h"
#import "SNTXPCControlInterface.h"
#import <MOLXPCConnection/MOLXPCConnection.h>
#import "Source/common/SNTBlockMessage.h"
#import "Source/common/SNTConfigurator.h"
#import "Source/common/SNTLogging.h"
#import "Source/common/SNTStoredEvent.h"
#import "Source/common/SNTStrengthify.h"
#import "Source/common/SNTXPCControlInterface.h"
@interface SNTNotificationManager ()
@@ -31,7 +32,7 @@
@property(readonly) NSMutableArray *pendingNotifications;
/// The connection to the bundle service
@property SNTXPCConnection *bundleServiceConnection;
@property MOLXPCConnection *bundleServiceConnection;
/// A semaphore to block bundle hashing until a connection is established
@property dispatch_semaphore_t bundleServiceSema;
@@ -192,7 +193,7 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
}
- (void)setBundleServiceListener:(NSXPCListenerEndpoint *)listener {
SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithListener:listener];
MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithListener:listener];
c.remoteInterface = [SNTXPCBundleServiceInterface bundleServiceInterface];
[c resume];
self.bundleServiceConnection = c;
@@ -203,6 +204,8 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
if (self.currentWindowController) {
[self updateBlockNotification:self.currentWindowController.event withBundleHash:nil];
}
self.bundleServiceConnection.invalidationHandler = nil;
[self.bundleServiceConnection invalidate];
};
dispatch_semaphore_signal(self.bundleServiceSema);
@@ -245,9 +248,10 @@ static NSString * const silencedNotificationsKey = @"SilencedNotifications";
}
// Send the results to santad. It will decide if they need to be synced.
SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
MOLXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
[daemonConn resume];
[[daemonConn remoteObjectProxy] syncBundleEvent:event relatedEvents:events];
[daemonConn invalidate];
// Update the UI with the bundle hash. Also make the openEventButton available.
[self updateBlockNotification:event withBundleHash:bh];

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Cocoa;
#import <Cocoa/Cocoa.h>
#import "SNTAppDelegate.h"
#import "Source/SantaGUI/SNTAppDelegate.h"
int main(int argc, const char *argv[]) {
@autoreleasepool {

181
Source/common/BUILD Normal file
View File

@@ -0,0 +1,181 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0
load("//:helper.bzl", "santa_unit_test")
objc_library(
name = "SNTBlockMessage",
srcs = ["SNTBlockMessage.m"],
hdrs = ["SNTBlockMessage.h"],
deps = [
":SNTConfigurator",
":SNTStoredEvent",
],
)
objc_library(
name = "SNTBlockMessage_SantaGUI",
srcs = ["SNTBlockMessage.m"],
hdrs = ["SNTBlockMessage.h"],
deps = [
":SNTConfigurator",
":SNTStoredEvent",
],
defines = ["SANTAGUI"],
)
objc_library(
name = "SNTCachedDecision",
srcs = ["SNTCachedDecision.m"],
hdrs = ["SNTCachedDecision.h"],
deps = [
":SNTCommonEnums",
":SNTKernelCommon",
],
)
cc_library(
name = "SNTCommonEnums",
hdrs = ["SNTCommonEnums.h"],
)
objc_library(
name = "SNTConfigurator",
srcs = ["SNTConfigurator.m"],
hdrs = ["SNTConfigurator.h"],
deps = [
":SNTCommonEnums",
":SNTLogging",
":SNTStrengthify",
":SNTSystemInfo",
],
)
objc_library(
name = "SNTDropRootPrivs",
srcs = ["SNTDropRootPrivs.m"],
hdrs = ["SNTDropRootPrivs.h"],
)
objc_library(
name = "SNTFileInfo",
srcs = ["SNTFileInfo.m"],
hdrs = ["SNTFileInfo.h"],
deps = [
"@FMDB",
"@MOLCodesignChecker",
],
)
cc_library(
name = "SNTKernelCommon",
hdrs = ["SNTKernelCommon.h"],
)
cc_library(
name = "SNTLoggingKernel",
hdrs = ["SNTLogging.h"],
)
objc_library(
name = "SNTLogging",
srcs = ["SNTLogging.m"],
hdrs = ["SNTLogging.h"],
)
objc_library(
name = "SNTRule",
srcs = ["SNTRule.m"],
hdrs = ["SNTRule.h"],
deps = [":SNTCommonEnums"],
)
objc_library(
name = "SNTStoredEvent",
srcs = ["SNTStoredEvent.m"],
hdrs = ["SNTStoredEvent.h"],
deps = [
":SNTCommonEnums",
"@MOLCertificate",
],
)
cc_library(
name = "SNTStrengthify",
hdrs = ["SNTStrengthify.h"],
)
objc_library(
name = "SNTSystemInfo",
srcs = ["SNTSystemInfo.m"],
hdrs = ["SNTSystemInfo.h"],
sdk_frameworks = ["IOKit"],
)
objc_library(
name = "SNTXPCBundleServiceInterface",
srcs = ["SNTXPCBundleServiceInterface.m"],
hdrs = ["SNTXPCBundleServiceInterface.h"],
deps = [":SNTStoredEvent"],
)
objc_library(
name = "SNTXPCControlInterface",
srcs = ["SNTXPCControlInterface.m"],
hdrs = ["SNTXPCControlInterface.h"],
deps = [
":SNTStoredEvent",
":SNTXPCUnprivilegedControlInterface",
"@MOLXPCConnection",
],
)
objc_library(
name = "SNTXPCNotifierInterface",
srcs = ["SNTXPCNotifierInterface.m"],
hdrs = ["SNTXPCNotifierInterface.h"],
deps = [
":SNTCommonEnums",
":SNTXPCBundleServiceInterface",
],
)
objc_library(
name = "SNTXPCSyncdInterface",
srcs = ["SNTXPCSyncdInterface.m"],
hdrs = ["SNTXPCSyncdInterface.h"],
deps = [
":SNTCommonEnums",
":SNTStoredEvent",
],
)
objc_library(
name = "SNTXPCUnprivilegedControlInterface",
srcs = ["SNTXPCUnprivilegedControlInterface.m"],
hdrs = ["SNTXPCUnprivilegedControlInterface.h"],
deps = [
":SNTCommonEnums",
":SNTKernelCommon",
":SNTRule",
":SNTStoredEvent",
":SNTXPCBundleServiceInterface",
"@MOLCertificate",
"@MOLXPCConnection",
],
)
santa_unit_test(
name = "SNTFileInfoTest",
srcs = ["SNTFileInfoTest.m"],
resources = [
"testdata/bad_pagezero",
"testdata/missing_pagezero",
],
structured_resources = glob([
"testdata/BundleExample.app/**",
"testdata/DirectoryBundle/**",
]),
deps = [":SNTFileInfo"],
)

View File

@@ -13,9 +13,9 @@
/// limitations under the License.
#ifdef SANTAGUI
@import Cocoa;
#import <Cocoa/Cocoa.h>
#else
@import Foundation;
#import <Foundation/Foundation.h>
#endif
@class SNTStoredEvent;

View File

@@ -12,11 +12,11 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTBlockMessage.h"
#import "Source/common/SNTBlockMessage.h"
#import "SNTConfigurator.h"
#import "SNTLogging.h"
#import "SNTStoredEvent.h"
#import "Source/common/SNTConfigurator.h"
#import "Source/common/SNTLogging.h"
#import "Source/common/SNTStoredEvent.h"
@implementation SNTBlockMessage
@@ -26,10 +26,24 @@
@"body {"
@" font-family: 'Lucida Grande', 'Helvetica', sans-serif;"
@" font-size: 13px;"
@" color: #666;"
@" color: %@;"
@" text-align: center;"
@"}"
// Supported in beta WebKit. Not sure if it is dynamic when used with NSAttributedString.
@"@media (prefers-color-scheme: dark) {"
@" body {"
@" color: #ddd;"
@" }"
@"}"
@"</style></head><body>";
// Support Dark Mode. Note, the returned NSAttributedString is static and does not update when
// the OS switches modes.
NSString *mode = [NSUserDefaults.standardUserDefaults stringForKey:@"AppleInterfaceStyle"];
BOOL dark = [mode isEqualToString:@"Dark"];
htmlHeader = [NSString stringWithFormat:htmlHeader, dark ? @"#ddd" : @"#333"];
NSString *htmlFooter = @"</body></html>";
NSString *message;
@@ -51,7 +65,7 @@
NSString *fullHTML = [NSString stringWithFormat:@"%@%@%@", htmlHeader, message, htmlFooter];
#ifdef NSAppKitVersionNumber10_0
#ifdef SANTAGUI
NSData *htmlData = [fullHTML dataUsingEncoding:NSUTF8StringEncoding];
return [[NSAttributedString alloc] initWithHTML:htmlData documentAttributes:NULL];
#else

View File

@@ -12,16 +12,17 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
#import "SNTCommonEnums.h"
#import "Source/common/SNTCommonEnums.h"
#import "Source/common/SNTKernelCommon.h"
///
/// Store information about executions from decision making for later logging.
///
@interface SNTCachedDecision : NSObject
@property uint64_t vnodeId;
@property santa_vnode_id_t vnodeId;
@property SNTEventState decision;
@property NSString *decisionExtra;
@property NSString *sha256;

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTCachedDecision.h"
#import "Source/common/SNTCachedDecision.h"
@implementation SNTCachedDecision
@end

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
///
/// These enums are used in various places throughout the Santa client code.
@@ -33,6 +33,9 @@ typedef NS_ENUM(NSInteger, SNTRuleState) {
SNTRuleStateBlacklist = 2,
SNTRuleStateSilentBlacklist = 3,
SNTRuleStateRemove = 4,
SNTRuleStateWhitelistCompiler = 5,
SNTRuleStateWhitelistTransitive = 6,
};
typedef NS_ENUM(NSInteger, SNTClientMode) {
@@ -58,6 +61,9 @@ typedef NS_ENUM(NSInteger, SNTEventState) {
SNTEventStateAllowBinary = 1 << 25,
SNTEventStateAllowCertificate = 1 << 26,
SNTEventStateAllowScope = 1 << 27,
SNTEventStateAllowCompiler = 1 << 28,
SNTEventStateAllowTransitive = 1 << 29,
SNTEventStateAllowPendingTransitive = 1 << 30,
// Block and Allow masks
SNTEventStateBlock = 0xFF << 16,
@@ -80,6 +86,13 @@ typedef NS_ENUM(NSInteger, SNTBundleEventAction) {
SNTBundleEventActionSendEvents,
};
// Indicates where to store event logs.
typedef NS_ENUM(NSInteger, SNTEventLogType) {
SNTEventLogTypeSyslog,
SNTEventLogTypeFilelog,
};
static const char *kKextPath = "/Library/Extensions/santa-driver.kext";
static const char *kSantaDPath = "/Library/Extensions/santa-driver.kext/Contents/MacOS/santad";
static const char *kSantaCtlPath = "/Library/Extensions/santa-driver.kext/Contents/MacOS/santactl";
static const char *kSantaAppPath = "/Library/Extensions/santa-driver.kext/Contents/Resources/Santa.app";

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
#import "SNTCommonEnums.h"
#import "Source/common/SNTCommonEnums.h"
///
/// Singleton that provides an interface for managing configuration values on disk
@@ -72,6 +72,57 @@
///
@property(readonly, nonatomic) NSRegularExpression *fileChangesRegex;
///
/// A list of ignore prefixes which are checked in-kernel.
/// This is more performant than FileChangesRegex when ignoring whole directory trees.
///
/// For example adding a prefix of "/private/tmp/" will turn off file change log generation
/// in-kernel for that entire tree. Since they are ignored by the kernel, they never reach santad
/// and are not seen by the fileChangesRegex. Note the trailing "/", without it any file or
/// directory starting with "/private/tmp" would be ignored.
///
/// By default "/." and "/dev/" are added.
///
/// Memory in the kernel is precious. A total of MAXPATHLEN (1024) nodes are allowed.
/// Using all 1024 nodes will result in santa-driver allocating ~2MB of wired memory.
/// An ASCII character uses 1 node. An UTF-8 encoded Unicode character uses 1-4 nodes.
/// Prefixes are added to the running config in-order, one by one. The prefix will be ignored if
/// (the running config's current size) + (the prefix's size) totals up to more than 1024 nodes.
/// The running config is stored in a prefix tree.
/// Prefixes that share prefixes are effectively de-duped; their shared node sized components only
/// take up 1 node. For example these 3 prefixes all have a common prefix of "/private/".
/// They will only take up 21 nodes instead of 39.
///
/// "/private/tmp/"
/// "/private/var/"
/// "/private/new/"
///
/// -> [t] -> [m] -> [p] -> [/]
///
/// [/] -> [p] -> [r] -> [i] -> [v] -> [a] -> [t] -> [e] -> [/] -> [v] -> [a] -> [r] -> [/]
///
/// -> [n] -> [e] -> [w] -> [/]
///
/// Prefixes with Unicode characters work similarly. Assuming a UTF-8 encoding these two prefixes
/// are actually the same for the first 3 nodes. They take up 7 nodes instead of 10.
///
/// "/🤘"
/// "/🖖"
///
/// -> [0xa4] -> [0x98]
///
/// [/] -> [0xf0] -> [0x9f]
///
/// -> [0x96] -> [0x96]
///
/// To disable file change logging completely add "/".
/// TODO(bur): Make this default if no FileChangesRegex is set.
///
/// Filters are only applied on santad startup.
/// TODO(bur): Support add / remove of filters while santad is running.
///
@property(readonly, nonatomic) NSArray *fileChangesPrefixFilters;
///
/// Enable __PAGEZERO protection, defaults to YES
/// If this flag is set to NO, 32-bit binaries that are missing
@@ -79,6 +130,32 @@
///
@property(readonly, nonatomic) BOOL enablePageZeroProtection;
///
/// Defines how event logs are stored. Options are:
/// SNTEventLogTypeSyslog: Sent to ASL or ULS (if built with the 10.12 SDK or later).
/// SNTEventLogTypeFilelog: Sent to a file on disk. Use eventLogPath to specify a path.
/// Defaults to SNTEventLogTypeFilelog.
/// For mobileconfigs use EventLogType as the key and syslog or filelog strings as the value.
///
/// @note: This property is KVO compliant, but should only be read once at santad startup.
///
@property(readonly, nonatomic) SNTEventLogType eventLogType;
///
/// If eventLogType is set to Filelog, eventLogPath will provide the path to save logs.
/// Defaults to /var/db/santa/santa.log.
///
/// @note: This property is KVO compliant, but should only be read once at santad startup.
///
@property(readonly, nonatomic) NSString *eventLogPath;
///
/// Enabling this appends the Santa machine ID to the end of each log line. If nothing
/// has been overriden, this is the host's UUID.
/// Defaults to NO.
///
@property(readonly, nonatomic) BOOL enableMachineIDDecoration;
#pragma mark - GUI Settings
///
@@ -170,7 +247,16 @@
/// If YES, enables bundle detection for blocked events. This property is not stored on disk.
/// Its value is set by a sync server that supports bundles. Defaults to NO.
///
@property BOOL bundlesEnabled;
@property BOOL enableBundles;
#pragma mark Transitive Whitelisting Settings
///
/// If YES, binaries marked with SNTRuleStateWhitelistCompiler rules are allowed to transitively
/// whitelist any executables that they produce. If NO, SNTRuleStateWhitelistCompiler rules are
/// interpreted as if they were simply SNTRuleStateWhitelist rules. Defaults to NO.
///
@property BOOL enableTransitiveWhitelisting;
#pragma mark Server Auth Settings

View File

@@ -12,13 +12,13 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTConfigurator.h"
#import "Source/common/SNTConfigurator.h"
#include <sys/stat.h>
#import "SNTLogging.h"
#import "SNTStrengthify.h"
#import "SNTSystemInfo.h"
#import "Source/common/SNTLogging.h"
#import "Source/common/SNTStrengthify.h"
#import "Source/common/SNTSystemInfo.h"
@interface SNTConfigurator ()
/// A NSUserDefaults object set to use the com.google.santa suite.
@@ -68,9 +68,16 @@ static NSString *const kModeNotificationLockdown = @"ModeNotificationLockdown";
static NSString *const kEnablePageZeroProtectionKey = @"EnablePageZeroProtection";
static NSString *const kFileChangesRegexKey = @"FileChangesRegex";
static NSString *const kFileChangesPrefixFiltersKey = @"FileChangesPrefixFilters";
static NSString *const kEventLogType = @"EventLogType";
static NSString *const kEventLogPath = @"EventLogPath";
static NSString *const kEnableMachineIDDecoration = @"EnableMachineIDDecoration";
// The keys managed by a sync server or mobileconfig.
static NSString *const kClientModeKey = @"ClientMode";
static NSString *const kEnableTransitiveWhitelistingKey = @"EnableTransitiveWhitelisting";
static NSString *const kWhitelistRegexKey = @"WhitelistRegex";
static NSString *const kBlacklistRegexKey = @"BlacklistRegex";
@@ -87,8 +94,10 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
Class date = [NSDate class];
Class string = [NSString class];
Class data = [NSData class];
Class array = [NSArray class];
_syncServerKeyTypes = @{
kClientModeKey : number,
kEnableTransitiveWhitelistingKey : number,
kWhitelistRegexKey : re,
kBlacklistRegexKey : re,
kFullSyncLastSuccess : date,
@@ -97,7 +106,9 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
};
_forcedConfigKeyTypes = @{
kClientModeKey : number,
kEnableTransitiveWhitelistingKey : number,
kFileChangesRegexKey : re,
kFileChangesPrefixFiltersKey : array,
kWhitelistRegexKey : re,
kBlacklistRegexKey : re,
kEnablePageZeroProtectionKey : number,
@@ -121,6 +132,9 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
kMachineOwnerPlistKeyKey : string,
kMachineIDPlistFileKey : string,
kMachineIDPlistKeyKey : string,
kEventLogType : string,
kEventLogPath : string,
kEnableMachineIDDecoration : number,
};
_defaults = [NSUserDefaults standardUserDefaults];
[_defaults addSuiteNamed:@"com.google.santa"];
@@ -187,6 +201,10 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
return [self configStateSet];
}
+ (NSSet *)keyPathsForValuesAffectingFileChangesPrefixFiltersKey {
return [self configStateSet];
}
+ (NSSet *)keyPathsForValuesAffectingSyncBaseURL {
return [self configStateSet];
}
@@ -267,6 +285,22 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
return [self syncStateSet];
}
+ (NSSet *)keyPathsForValuesAffectingEventLogType {
return [self configStateSet];
}
+ (NSSet *)keyPathsForValuesAffectingEventLogPath {
return [self configStateSet];
}
+ (NSSet *)keyPathsForValuesAffectingEnableMachineIDDecoration {
return [self configStateSet];
}
+ (NSSet *)keyPathsForValuesAffectingEnableTransitiveWhitelisting {
return [self syncAndConfigStateSet];
}
#pragma mark Public Interface
- (SNTClientMode)clientMode {
@@ -291,6 +325,18 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
}
}
- (BOOL)enableTransitiveWhitelisting {
NSNumber *n = self.syncState[kEnableTransitiveWhitelistingKey];
if (n) {
return [n boolValue];
}
return [self.configState[kEnableTransitiveWhitelistingKey] boolValue];
}
- (void)setEnableTransitiveWhitelisting:(BOOL)enabled {
[self updateSyncStateForKey:kEnableTransitiveWhitelistingKey value:@(enabled)];
}
- (NSRegularExpression *)whitelistPathRegex {
return self.syncState[kWhitelistRegexKey] ?: self.configState[kWhitelistRegexKey];
}
@@ -311,8 +357,20 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
return self.configState[kFileChangesRegexKey];
}
- (NSArray *)fileChangesPrefixFilters {
NSArray *filters = self.configState[kFileChangesPrefixFiltersKey];
for (id filter in filters) {
if (![filter isKindOfClass:[NSString class]]) {
LOGE(@"Ignoring FileChangesPrefixFilters: array contains a non-string %@", filter);
return nil;
}
}
return filters;
}
- (NSURL *)syncBaseURL {
NSString *urlString = self.configState[kSyncBaseURLKey];
if (![urlString hasSuffix:@"/"]) urlString = [urlString stringByAppendingString:@"/"];
NSURL *url = [NSURL URLWithString:urlString];
if (urlString && !url) LOGW(@"SyncBaseURL is not a valid URL!");
return url;
@@ -429,6 +487,20 @@ static NSString *const kSyncCleanRequired = @"SyncCleanRequired";
return machineId.length ? machineId : [SNTSystemInfo hardwareUUID];
}
- (SNTEventLogType)eventLogType {
NSString *s = [self.configState[kEventLogType] lowercaseString];
return [s isEqualToString:@"syslog"] ? SNTEventLogTypeSyslog : SNTEventLogTypeFilelog;
}
- (NSString *)eventLogPath {
return self.configState[kEventLogPath] ?: @"/var/db/santa/santa.log";
}
- (BOOL)enableMachineIDDecoration {
NSNumber *number = self.configState[kEnableMachineIDDecoration];
return number ? [number boolValue] : NO;
}
#pragma mark Private
///

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
///
/// Simple function to check and drop root privileges.

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTDropRootPrivs.h"
#import "Source/common/SNTDropRootPrivs.h"
BOOL DropRootPrivileges() {
if (getuid() == 0 || geteuid() == 0 || getgid() == 0 || getegid() == 0) {

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
@class MOLCodesignChecker;
@@ -212,6 +212,11 @@
///
- (NSUInteger)fileSize;
///
/// @return The underlying file handle.
///
@property(readonly) NSFileHandle *fileHandle;
///
/// @return Returns an instance of MOLCodeSignChecker initialized with the file's binary path.
/// Both the MOLCodesignChecker and any resulting NSError are cached and returned on subsequent

View File

@@ -12,18 +12,19 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTFileInfo.h"
#import "Source/common/SNTFileInfo.h"
#import <CommonCrypto/CommonDigest.h>
#import <fmdb/FMDB.h>
#import <MOLCodesignChecker/MOLCodesignChecker.h>
#include <mach-o/arch.h>
#include <mach-o/loader.h>
#include <mach-o/swap.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#import <FMDB/FMDB.h>
// Simple class to hold the data of a mach_header and the offset within the file
// in which that header was found.
@@ -287,7 +288,8 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
- (BOOL)isMissingPageZero {
// This method only checks i386 arch because the kernel enforces this for other archs
// See bsd/kern/mach_loader.c, search for enforce_hard_pagezero.
MachHeaderWithOffset *x86Header = self.machHeaders[[self nameForCPUType:CPU_TYPE_X86]];
MachHeaderWithOffset *x86Header = self.machHeaders[[self nameForCPUType:CPU_TYPE_X86
cpuSubType:CPU_SUBTYPE_I386_ALL]];
if (!x86Header) return NO;
struct mach_header *mh = (struct mach_header *)[x86Header.data bytes];
@@ -315,6 +317,26 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
#pragma mark Bundle Information
///
/// Directories with a "Contents/Info.plist" entry can be mistaken as a bundle. To be considered an
/// ancestor, the bundle must have a valid extension.
///
- (NSSet *)allowedAncestorExtensions {
static NSSet *set;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSSet setWithArray:@[
@"app",
@"bundle",
@"framework",
@"kext",
@"xctest",
@"xpc",
]];
});
return set;
}
///
/// Try and determine the bundle that the represented executable is contained within, if any.
///
@@ -325,18 +347,21 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
///
/// This method walks up the path until a bundle is found, if any.
///
/// @param ancestor YES this will return the highest NSBundle found in the tree. No will return the
/// the lowest.
/// @param ancestor YES this will return the highest NSBundle, with a valid extension, found in the
/// tree. NO will return the the lowest NSBundle, without validating the extension.
///
-(NSBundle *)findBundleWithAncestor:(BOOL)ancestor {
- (NSBundle *)findBundleWithAncestor:(BOOL)ancestor {
NSBundle *bundle;
NSMutableArray *pathComponents = [[self.path pathComponents] mutableCopy];
// Ignore the root path "/", for some reason this is considered a bundle.
while (pathComponents.count > 1) {
NSBundle *bndl = [NSBundle bundleWithPath:[NSString pathWithComponents:pathComponents]];
if (bndl && [bndl objectForInfoDictionaryKey:@"CFBundleIdentifier"]) {
bundle = bndl;
if ([bndl objectForInfoDictionaryKey:@"CFBundleIdentifier"]) {
if (!ancestor ||
[[self allowedAncestorExtensions] containsObject:bndl.bundlePath.pathExtension]) {
bundle = bndl;
}
if (!ancestor) break;
}
[pathComponents removeLastObject];
@@ -443,7 +468,7 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
if (machHeader) {
struct mach_header *mh = (struct mach_header *)[machHeader bytes];
MachHeaderWithOffset *mhwo = [[MachHeaderWithOffset alloc] initWithData:machHeader offset:0];
machHeaders[[self nameForCPUType:mh->cputype]] = mhwo;
machHeaders[[self nameForCPUType:mh->cputype cpuSubType:mh->cpusubtype]] = mhwo;
} else {
NSRange range = NSMakeRange(0, sizeof(struct fat_header));
NSData *fatHeader = [self safeSubdataWithRange:range];
@@ -459,11 +484,12 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
int offset = OSSwapBigToHostInt32(fat_arch[i].offset);
int size = OSSwapBigToHostInt32(fat_arch[i].size);
int cputype = OSSwapBigToHostInt(fat_arch[i].cputype);
int cpusubtype = OSSwapBigToHostInt(fat_arch[i].cpusubtype);
range = NSMakeRange(offset, size);
NSData *machHeader = [self parseSingleMachHeader:[self safeSubdataWithRange:range]];
if (machHeader) {
NSString *key = [self nameForCPUType:cputype];
NSString *key = [self nameForCPUType:cputype cpuSubType:cpusubtype];
MachHeaderWithOffset *mhwo = [[MachHeaderWithOffset alloc] initWithData:machHeader
offset:offset];
machHeaders[key] = mhwo;
@@ -647,20 +673,15 @@ extern NSString *const NSURLQuarantinePropertiesKey WEAK_IMPORT_ATTRIBUTE;
///
/// Return a human-readable string for a cpu_type_t.
///
- (NSString *)nameForCPUType:(cpu_type_t)cpuType {
switch (cpuType) {
case CPU_TYPE_X86:
return @"i386";
case CPU_TYPE_X86_64:
return @"x86-64";
case CPU_TYPE_POWERPC:
return @"ppc";
case CPU_TYPE_POWERPC64:
return @"ppc64";
default:
return @"unknown";
- (NSString *)nameForCPUType:(cpu_type_t)cpuType cpuSubType:(cpu_subtype_t)cpuSubType {
const NXArchInfo *archInfo = NXGetArchInfoFromCpuType(cpuType, cpuSubType);
NSString *arch;
if (archInfo && archInfo->name) {
arch = @(archInfo->name);
} else {
arch = [NSString stringWithFormat:@"%i:%i", cpuType, cpuSubType];
}
return nil;
return arch;
}
///

View File

@@ -12,15 +12,25 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import XCTest;
#import <XCTest/XCTest.h>
#import "SNTFileInfo.h"
#import "Source/common/SNTFileInfo.h"
@interface SNTFileInfoTest : XCTestCase
@end
@implementation SNTFileInfoTest
- (NSString *)directoryBundle {
NSString *rp = [[NSBundle bundleForClass:[self class]] resourcePath];
return [rp stringByAppendingPathComponent:@"testdata/DirectoryBundle"];
}
- (NSString *)bundleExample {
NSString *rp = [[NSBundle bundleForClass:[self class]] resourcePath];
return [rp stringByAppendingPathComponent:@"testdata/BundleExample.app"];
}
- (void)testPathStandardizing {
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:@"/Applications/Safari.app"];
XCTAssertNotNil(sut);
@@ -120,8 +130,7 @@
}
- (void)testBundle {
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"BundleExample"
ofType:@"app"];
NSString *path = [self bundleExample];
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
XCTAssertNotNil([sut bundle]);
@@ -134,19 +143,18 @@
}
- (void)testAncestorBundle {
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"BundleExample"
ofType:@"app"];
NSString *path = [self bundleExample];
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
sut.useAncestorBundle = YES;
XCTAssertNotNil([sut bundle]);
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.LogicTests");
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.santa.UnitTest.SNTFileInfoTest");
XCTAssertNotNil([sut bundleVersion]);
XCTAssertNotNil([sut bundleShortVersionString]);
NSString *ancestorBundlePath = path;
for (int i = 0; i < 3; i++) {
for (int i = 0; i < 4; i++) {
ancestorBundlePath = [ancestorBundlePath stringByDeletingLastPathComponent];
}
XCTAssertEqualObjects([sut bundlePath], ancestorBundlePath);
@@ -159,15 +167,33 @@
XCTAssertNotNil([sut bundle]);
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.LogicTests");
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.santa.UnitTest.SNTFileInfoTest");
XCTAssertNotNil([sut bundleVersion]);
XCTAssertNotNil([sut bundleShortVersionString]);
XCTAssertEqualObjects([sut bundlePath], path);
}
- (void)testDirectoryBundleIsNotAncestor {
NSString *path = [self directoryBundle];
NSString *directoryBundle = @"/tmp/DirectoryBundle";
NSFileManager *fm = [NSFileManager defaultManager];
[fm removeItemAtPath:directoryBundle error:NULL];
[fm copyItemAtPath:path toPath:directoryBundle error:NULL];
path = [directoryBundle stringByAppendingString:@"/Contents/Resources/BundleExample.app"];
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
sut.useAncestorBundle = YES;
XCTAssertNotNil([sut bundle]);
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.santa.BundleExample");
XCTAssertEqualObjects([sut bundleName], @"BundleExample");
XCTAssertEqualObjects([sut bundleVersion], @"1");
XCTAssertEqualObjects([sut bundleShortVersionString], @"1.0");
XCTAssertEqualObjects([sut bundlePath], path);
}
- (void)testBundleCacheReset {
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"BundleExample"
ofType:@"app"];
NSString *path = [self bundleExample];
SNTFileInfo *sut = [[SNTFileInfo alloc] initWithPath:path];
XCTAssertNotNil([sut bundle]);
@@ -182,12 +208,12 @@
XCTAssertNotNil([sut bundle]);
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.LogicTests");
XCTAssertEqualObjects([sut bundleIdentifier], @"com.google.santa.UnitTest.SNTFileInfoTest");
XCTAssertNotNil([sut bundleVersion]);
XCTAssertNotNil([sut bundleShortVersionString]);
NSString *ancestorBundlePath = path;
for (int i = 0; i < 3; i++) {
for (int i = 0; i < 4; i++) {
ancestorBundlePath = [ancestorBundlePath stringByDeletingLastPathComponent];
}
XCTAssertEqualObjects([sut bundlePath], ancestorBundlePath);

View File

@@ -21,9 +21,6 @@
#ifndef SANTA__COMMON__KERNELCOMMON_H
#define SANTA__COMMON__KERNELCOMMON_H
// Defines the lengths of paths and Vnode IDs passed around.
#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"
#define USERCLIENT_ID "com.google.santa-driver"
@@ -36,11 +33,16 @@
enum SantaDriverMethods {
kSantaUserClientOpen,
kSantaUserClientAllowBinary,
kSantaUserClientAllowCompiler,
kSantaUserClientDenyBinary,
kSantaUserClientAcknowledgeBinary,
kSantaUserClientClearCache,
kSantaUserClientRemoveCacheEntry,
kSantaUserClientCacheCount,
kSantaUserClientCheckCache,
kSantaUserClientCacheBucketCount,
kSantaUserClientFilemodPrefixFilterAdd,
kSantaUserClientFilemodPrefixFilterReset,
// Any methods supported by the driver should be added above this line to
// ensure this remains the count of methods.
@@ -49,7 +51,7 @@ enum SantaDriverMethods {
typedef enum {
QUEUETYPE_DECISION,
QUEUETYPE_LOG
QUEUETYPE_LOG,
} santa_queuetype_t;
// Enum defining actions that can be passed down the IODataQueue and in
@@ -66,6 +68,10 @@ typedef enum {
ACTION_RESPOND_DENY = 21,
ACTION_RESPOND_TOOLONG = 22,
ACTION_RESPOND_ACK = 23,
ACTION_RESPOND_ALLOW_COMPILER = 24,
// The following response is stored only in the kernel decision cache.
// It is removed by SNTCompilerController
ACTION_RESPOND_ALLOW_PENDING_TRANSITIVE = 25,
// NOTIFY
ACTION_NOTIFY_EXEC = 30,
@@ -74,18 +80,39 @@ typedef enum {
ACTION_NOTIFY_LINK = 33,
ACTION_NOTIFY_EXCHANGE = 34,
ACTION_NOTIFY_DELETE = 35,
ACTION_NOTIFY_WHITELIST = 36,
// ERROR
ACTION_ERROR = 99,
} santa_action_t;
#define RESPONSE_VALID(x) \
(x == ACTION_RESPOND_ALLOW || x == ACTION_RESPOND_DENY)
(x == ACTION_RESPOND_ALLOW || \
x == ACTION_RESPOND_DENY || \
x == ACTION_RESPOND_ALLOW_COMPILER || \
x == ACTION_RESPOND_ALLOW_PENDING_TRANSITIVE)
// Struct to manage vnode IDs
typedef struct santa_vnode_id_t {
uint64_t fsid;
uint64_t fileid;
#ifdef __cplusplus
bool operator==(const santa_vnode_id_t& rhs) const {
return fsid == rhs.fsid && fileid == rhs.fileid;
}
// This _must not_ be used for anything security-sensitive. It exists solely to make
// the msleep/wakeup calls easier.
uint64_t unsafe_simple_id() const {
return (((uint64_t)fsid << 32) | fileid);
}
#endif
} santa_vnode_id_t;
// Message struct that is sent down the IODataQueue.
typedef struct {
santa_action_t action;
uint64_t vnode_id;
santa_vnode_id_t vnode_id;
uid_t uid;
gid_t gid;
pid_t pid;
@@ -99,4 +126,10 @@ typedef struct {
char pname[MAXPATHLEN];
} santa_message_t;
// Used for the kSantaUserClientCacheBucketCount request.
typedef struct {
uint16_t per_bucket[1024];
uint64_t start;
} santa_bucket_count_t;
#endif // SANTA__COMMON__KERNELCOMMON_H

View File

@@ -34,7 +34,7 @@
#else // KERNEL
@import Foundation;
#import <Foundation/Foundation.h>
typedef enum : NSUInteger {
LOG_LEVEL_ERROR,

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTLogging.h"
#import "Source/common/SNTLogging.h"
#import <asl.h>
#import <pthread.h>
@@ -24,17 +24,20 @@ static LogLevel logLevel = LOG_LEVEL_INFO; // default to info
#endif
void syslogClientDestructor(void *arg) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
asl_close((aslclient)arg);
#pragma clang diagnostic pop
}
void logMessage(LogLevel level, FILE *destination, NSString *format, ...) {
static BOOL useSyslog = NO;
static const char *binaryName;
static NSString *binaryName;
static dispatch_once_t pred;
static pthread_key_t syslogKey = 0;
dispatch_once(&pred, ^{
binaryName = [[[NSProcessInfo processInfo] processName] UTF8String];
binaryName = [[NSProcessInfo processInfo] processName];
// If debug logging is enabled, the process must be restarted.
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--debug"]) {
@@ -58,8 +61,11 @@ void logMessage(LogLevel level, FILE *destination, NSString *format, ...) {
if (useSyslog) {
aslclient client = (aslclient)pthread_getspecific(syslogKey);
if (client == NULL) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
client = asl_open(NULL, "com.google.santa", 0);
asl_set_filter(client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
#pragma clang diagnostic pop
pthread_setspecific(syslogKey, client);
}
@@ -76,7 +82,7 @@ void logMessage(LogLevel level, FILE *destination, NSString *format, ...) {
break;
case LOG_LEVEL_INFO:
levelName = "I";
syslogLevel = ASL_LEVEL_INFO;
syslogLevel = ASL_LEVEL_NOTICE; // Maps to ULS Default
break;
case LOG_LEVEL_DEBUG:
levelName = "D";
@@ -84,7 +90,10 @@ void logMessage(LogLevel level, FILE *destination, NSString *format, ...) {
break;
}
asl_log(client, NULL, syslogLevel, "%s %s: %s", levelName, binaryName, [s UTF8String]);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
asl_log(client, NULL, syslogLevel, "%s %s: %s", levelName, binaryName.UTF8String, s.UTF8String);
#pragma clang diagnostic pop
} else {
[s appendString:@"\n"];
size_t len = [s lengthOfBytesUsingEncoding:NSUTF8StringEncoding];

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
#import "SNTCommonEnums.h"
#import "Source/common/SNTCommonEnums.h"
///
/// Represents a Rule.
@@ -41,12 +41,32 @@
///
@property(copy) NSString *customMsg;
///
/// The time when this rule was last retrieved from the rules database, if rule is transitive.
/// Stored as number of seconds since 00:00:00 UTC on 1 January 2001.
///
@property(readonly) NSUInteger timestamp;
///
/// Designated initializer.
///
- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg
timestamp:(NSUInteger)timestamp;
///
/// Initialize with a default timestamp: current time if rule state is transitive, 0 otherwise.
///
- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg;
///
/// Sets timestamp of rule to the current time.
///
- (void)resetTimestamp;
@end

View File

@@ -12,26 +12,51 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTRule.h"
#import "Source/common/SNTRule.h"
@interface SNTRule()
@property(readwrite) NSUInteger timestamp;
@end
@implementation SNTRule
- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg {
customMsg:(NSString *)customMsg
timestamp:(NSUInteger)timestamp {
self = [super init];
if (self) {
_shasum = shasum;
_state = state;
_type = type;
_customMsg = customMsg;
_timestamp = timestamp;
}
return self;
}
- (instancetype)initWithShasum:(NSString *)shasum
state:(SNTRuleState)state
type:(SNTRuleType)type
customMsg:(NSString *)customMsg {
self = [self initWithShasum:shasum
state:state
type:type
customMsg:customMsg
timestamp:0];
// Initialize timestamp to current time if rule is transitive.
if (self && state == SNTRuleStateWhitelistTransitive) {
[self resetTimestamp];
}
return self;
}
#pragma mark NSSecureCoding
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-literal-conversion"
#define ENCODE(obj, key) if (obj) [coder encodeObject:obj forKey:key]
#define DECODE(cls, key) [decoder decodeObjectOfClass:[cls class] forKey:key]
@@ -44,6 +69,7 @@
ENCODE(@(self.state), @"state");
ENCODE(@(self.type), @"type");
ENCODE(self.customMsg, @"custommsg");
ENCODE(@(self.timestamp), @"timestamp");
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
@@ -53,12 +79,14 @@
_state = [DECODE(NSNumber, @"state") intValue];
_type = [DECODE(NSNumber, @"type") intValue];
_customMsg = DECODE(NSString, @"custommsg");
_timestamp = [DECODE(NSNumber, @"timestamp") unsignedIntegerValue];
}
return self;
}
#undef DECODE
#undef ENCODE
#pragma clang diagnostic pop
- (BOOL)isEqual:(id)other {
if (other == self) return YES;
@@ -77,8 +105,14 @@
}
- (NSString *)description {
return [NSString stringWithFormat:@"SNTRule: SHA-256: %@, State: %ld, Type: %ld",
self.shasum, self.state, self.type];
return [NSString stringWithFormat:@"SNTRule: SHA-256: %@, State: %ld, Type: %ld, Timestamp: %lu",
self.shasum, self.state, self.type, (unsigned long)self.timestamp];
}
# pragma mark Last-access Timestamp
- (void)resetTimestamp {
self.timestamp = (NSUInteger)[[NSDate date] timeIntervalSinceReferenceDate];
}
@end

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
#import "SNTCommonEnums.h"
#import "Source/common/SNTCommonEnums.h"
///
/// Represents an event stored in the database.

View File

@@ -12,12 +12,15 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTStoredEvent.h"
#import "Source/common/SNTStoredEvent.h"
#import <MOLCertificate/MOLCertificate.h>
@implementation SNTStoredEvent
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-literal-conversion"
#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) \
@@ -129,4 +132,6 @@
[NSString stringWithFormat:@"SNTStoredEvent[%@] with SHA-256: %@", self.idx, self.fileSHA256];
}
#pragma clang diagnostic pop
@end

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
///
/// Simple class for fetching system information

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTSystemInfo.h"
#import "Source/common/SNTSystemInfo.h"
@implementation SNTSystemInfo

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
@class SNTStoredEvent;

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTXPCBundleServiceInterface.h"
#import "Source/common/SNTXPCBundleServiceInterface.h"
#import "SNTStoredEvent.h"
#import "Source/common/SNTStoredEvent.h"
@implementation SNTXPCBundleServiceInterface

View File

@@ -1,135 +0,0 @@
/// 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 Foundation;
/**
A wrapper around NSXPCListener and NSXPCConnection to provide client multiplexing, signature
validation of connecting clients and forced connection establishment.
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 resume];
@endcode
Example client, connecting to above server:
@code
SNTXPCConnection *conn = [[SNTXPCConnection alloc] initClientWithName:"MyServer"
withOptions:0];
conn.remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)];
conn.invalidationHandler = ^{ NSLog(@"Connection invalidated") };
[conn resume];
@endcode
The client can send a message to the server with:
@code
[conn.remoteObjectProxy selectorInRemoteInterface];
@endcode
One advantage of the way that SNTXPCConnection works over using NSXPCConnection directly is that
from the client-side once the resume method has finished, the connection is either valid or the
invalidation handler will be called. Ordinarily, the connection doesn't actually get made until
the first message is sent across it.
@note messages are always delivered on a background thread!
*/
@interface SNTXPCConnection : NSObject<NSXPCListenerDelegate>
/**
Initialize a new server with a given listener, provided by `[NSXPCListener anonymousListener]`.
*/
- (nullable instancetype)initServerWithListener:(nonnull NSXPCListener *)listener;
/**
Initializer for the 'server' side of the connection, started by launchd.
@param name MachService name, must match the MachServices key in the launchd.plist
*/
- (nullable instancetype)initServerWithName:(nonnull NSString *)name;
/**
Initialize a new client to a service exported by a LaunchDaemon.
@param name MachService name
@param privileged Use YES if the server is running as root.
*/
- (nullable instancetype)initClientWithName:(nonnull NSString *)name privileged:(BOOL)privileged;
/**
Initialize a new client to a service within a bundle.
@param name service name
*/
- (nullable instancetype)initClientWithServiceName:(nonnull NSString *)name;
/**
Initialize a new client with a listener endpoint sent from another process.
@param listener An NSXPCListenerEndpoint to connect to.
*/
- (nullable instancetype)initClientWithListener:(nonnull NSXPCListenerEndpoint *)listener;
/**
Call when the properties of the object have been set-up and you're ready for connections.
For clients, this call can take up to 2s to complete for connection to finish establishing though
in basically all cases it will actually complete in a few milliseconds.
*/
- (void)resume;
/**
Invalidate the connection(s). This must be done before the object can be released.
*/
- (void)invalidate;
/**
The interface the remote object should conform to. (client)
*/
@property(retain, nullable) NSXPCInterface *remoteInterface;
/**
A proxy to the object at the other end of the connection. (client)
@note If the connection to the server failed, this will be nil, so you can safely send messages
and rely on the invalidationHandler for handling the failure.
*/
@property(readonly, nonatomic, nullable) id remoteObjectProxy;
/**
The interface this object exports. (server)
*/
@property(retain, nullable) NSXPCInterface *exportedInterface;
/**
The object that responds to messages from the other end. (server)
*/
@property(retain, nullable) id exportedObject;
/**
A block to run when a/the connection is accepted and fully established.
*/
@property(copy, nullable) void (^acceptedHandler)(void);
/**
A block to run when a/the connection is invalidated/interrupted/rejected.
*/
@property(copy, nullable) void (^invalidationHandler)(void);
@end

View File

@@ -1,210 +0,0 @@
/// 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 "SNTXPCConnection.h"
#import <MOLCodesignChecker/MOLCodesignChecker.h>
#import "SNTStrengthify.h"
/**
Protocol used during connection establishment, @see SNTXPCConnectionInterface
*/
@protocol SNTXPCConnectionProtocol
- (void)connectWithReply:(void (^)())reply;
@end
/**
Recipient object used during connection establishment. Each incoming connection
has one of these objects created which accept the message in the protocol
and call the block provided during creation before replying.
This allows the server to reset the connection's exported interface and
object to the correct values after the client has sent the establishment message.
*/
@interface SNTXPCConnectionInterface : NSObject<SNTXPCConnectionProtocol>
@property(strong) void (^block)(void);
@end
@implementation SNTXPCConnectionInterface
- (void)connectWithReply:(void (^)())reply {
if (self.block) self.block();
reply();
}
@end
@interface SNTXPCConnection ()
@property NSXPCInterface *validationInterface;
/// The XPC listener (server only).
@property NSXPCListener *listenerObject;
/// The current connection object (client only).
@property NSXPCConnection *currentConnection;
@end
@implementation SNTXPCConnection
#pragma mark Initializers
- (instancetype)initServerWithListener:(NSXPCListener *)listener {
self = [super init];
if (self) {
_listenerObject = listener;
_validationInterface =
[NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)];
}
return self;
}
- (instancetype)initServerWithName:(NSString *)name {
return [self initServerWithListener:[[NSXPCListener alloc] initWithMachServiceName:name]];
}
- (instancetype)initClientWithListener:(NSXPCListenerEndpoint *)listener {
self = [super init];
if (self) {
_currentConnection = [[NSXPCConnection alloc] initWithListenerEndpoint:listener];
if (!_currentConnection) return nil;
_validationInterface =
[NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)];
}
return self;
}
- (instancetype)initClientWithName:(NSString *)name privileged:(BOOL)privileged {
self = [super init];
if (self) {
NSXPCConnectionOptions options = (privileged ? NSXPCConnectionPrivileged : 0);
_currentConnection = [[NSXPCConnection alloc] initWithMachServiceName:name options:options];
if (!_currentConnection) return nil;
_validationInterface =
[NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)];
}
return self;
}
- (instancetype)initClientWithServiceName:(NSString *)name {
self = [super init];
if (self) {
_currentConnection = [[NSXPCConnection alloc] initWithServiceName:name];
if (!_currentConnection) return nil;
_validationInterface =
[NSXPCInterface interfaceWithProtocol:@protocol(SNTXPCConnectionProtocol)];
}
return self;
}
- (instancetype)init {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
#pragma mark Connection set-up
- (void)resume {
if (self.listenerObject) {
self.listenerObject.delegate = self;
[self.listenerObject resume];
} else {
WEAKIFY(self);
// Set-up the connection with the remote interface set to the validation interface,
// send a message to the listener to finish establishing the connection
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
self.currentConnection.remoteObjectInterface = self.validationInterface;
self.currentConnection.interruptionHandler = self.currentConnection.invalidationHandler = ^{
STRONGIFY(self);
if (self.invalidationHandler) self.invalidationHandler();
};
[self.currentConnection resume];
[[self.currentConnection remoteObjectProxy] connectWithReply:^{
STRONGIFY(self);
// The connection is now established
[self.currentConnection suspend];
self.currentConnection.remoteObjectInterface = self.remoteInterface;
[self.currentConnection resume];
dispatch_semaphore_signal(sema);
if (self.acceptedHandler) self.acceptedHandler();
}];
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC))) {
// This is unusual - as we're not inside a block - but necessary in case the caller sets an
// invalidation handler that causes this instance to be released (which is a reasonable
// approach). If establishing a connection fails, the invalidation handler will be called
// and then shortly after this bit of code will run causing a crash.
STRONGIFY(self);
// Connection was not established in a reasonable time, invalidate.
self.currentConnection.remoteObjectInterface = nil; // ensure clients don't try to use it.
[self.currentConnection invalidate];
}
}
}
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)connection {
pid_t pid = connection.processIdentifier;
MOLCodesignChecker *otherCS = [[MOLCodesignChecker alloc] initWithPID:pid];
if (![otherCS signingInformationMatches:[[MOLCodesignChecker alloc] initWithSelf]]) {
return NO;
}
// The client passed the code signature check, now we need to resume the listener and
// return YES so that the client can send the connectWithReply message. Once the client does
// we reset the connection's exportedInterface and exportedObject.
SNTXPCConnectionInterface *ci = [[SNTXPCConnectionInterface alloc] init];
WEAKIFY(self);
WEAKIFY(connection);
ci.block = ^{
STRONGIFY(self)
STRONGIFY(connection);
[connection suspend];
connection.invalidationHandler = connection.interruptionHandler = ^{
if (self.invalidationHandler) self.invalidationHandler();
};
connection.exportedInterface = self.exportedInterface;
connection.exportedObject = self.exportedObject;
[connection resume];
// The connection is now established.
if (self.acceptedHandler) self.acceptedHandler();
};
connection.exportedInterface = self.validationInterface;
connection.exportedObject = ci;
[connection resume];
return YES;
}
- (id)remoteObjectProxy {
if (self.currentConnection.remoteObjectInterface &&
self.currentConnection.remoteObjectInterface != self.validationInterface) {
return [self.currentConnection remoteObjectProxyWithErrorHandler:^(NSError *error) {
[self.currentConnection invalidate];
}];
}
return nil;
}
#pragma mark Connection tear-down
- (void)invalidate {
if (self.currentConnection) {
[self.currentConnection invalidate];
self.currentConnection = nil;
} else if (self.listenerObject) {
[self.listenerObject invalidate];
}
}
@end

View File

@@ -12,118 +12,57 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <MOLCertificate/MOLCertificate.h>
#import "SNTCachedDecision.h"
#import "SNTCommonEnums.h"
#import "SNTKernelCommon.h"
#import "SNTXPCBundleServiceInterface.h"
@class SNTRule;
@class SNTStoredEvent;
@class SNTXPCConnection;
#import "Source/common/SNTXPCUnprivilegedControlInterface.h"
///
/// Protocol implemented by santad and utilized by santactl
/// Protocol implemented by santad and utilized by santactl (privileged operations)
///
@protocol SNTDaemonControlXPC
@protocol SNTDaemonControlXPC <SNTUnprivilegedDaemonControlXPC>
///
/// Kernel ops
///
- (void)cacheCounts:(void (^)(uint64_t rootCache, uint64_t nonRootCache))reply;
- (void)flushCache:(void (^)(BOOL))reply;
- (void)checkCacheForVnodeID:(uint64_t)vnodeID withReply:(void (^)(santa_action_t))reply;
///
/// Database ops
///
- (void)databaseRuleCounts:(void (^)(int64_t binary, int64_t certificate))reply;
- (void)databaseRuleAddRules:(NSArray *)rules
cleanSlate:(BOOL)cleanSlate
reply:(void (^)(NSError *error))reply;
- (void)databaseEventCount:(void (^)(int64_t count))reply;
- (void)databaseEventsPending:(void (^)(NSArray *events))reply;
- (void)databaseRemoveEventsWithIDs:(NSArray *)ids;
- (void)databaseRuleForBinarySHA256:(NSString *)binarySHA256
certificateSHA256:(NSString *)certificateSHA256
reply:(void (^)(SNTRule *))reply;
///
/// Decision ops
///
///
/// @param filePath A Path to the file, can be nil.
/// @param fileSHA256 The pre-calculated SHA256 hash for the file, can be nil. If nil the hash will
/// be calculated by this method from the filePath.
/// @param certificateSHA256 A SHA256 hash of the signing certificate, can be nil.
/// @note If fileInfo and signingCertificate are both passed in, the most specific rule will be
/// returned. Binary rules take precedence over cert rules.
///
- (void)decisionForFilePath:(NSString *)filePath
fileSHA256:(NSString *)fileSHA256
certificateSHA256:(NSString *)certificateSHA256
reply:(void (^)(SNTEventState))reply;
///
/// Config ops
///
- (void)watchdogInfo:(void (^)(uint64_t, uint64_t, double, double))reply;
- (void)clientMode:(void (^)(SNTClientMode))reply;
- (void)setClientMode:(SNTClientMode)mode reply:(void (^)())reply;
- (void)xsrfToken:(void (^)(NSString *))reply;
- (void)setXsrfToken:(NSString *)token reply:(void (^)())reply;
- (void)fullSyncLastSuccess:(void (^)(NSDate *))reply;
- (void)setFullSyncLastSuccess:(NSDate *)date reply:(void (^)())reply;
- (void)ruleSyncLastSuccess:(void (^)(NSDate *))reply;
- (void)setRuleSyncLastSuccess:(NSDate *)date reply:(void (^)())reply;
- (void)syncCleanRequired:(void (^)(BOOL))reply;
- (void)setSyncCleanRequired:(BOOL)cleanReqd reply:(void (^)())reply;
- (void)setWhitelistPathRegex:(NSString *)pattern reply:(void (^)())reply;
- (void)setBlacklistPathRegex:(NSString *)pattern reply:(void (^)())reply;
- (void)bundlesEnabled:(void (^)(BOOL))reply;
- (void)setBundlesEnabled:(BOOL)bundlesEnabled reply:(void (^)())reply;
///
/// GUI Ops
///
- (void)setNotificationListener:(NSXPCListenerEndpoint *)listener;
- (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener;
- (void)setClientMode:(SNTClientMode)mode reply:(void (^)(void))reply;
- (void)setXsrfToken:(NSString *)token reply:(void (^)(void))reply;
- (void)setFullSyncLastSuccess:(NSDate *)date reply:(void (^)(void))reply;
- (void)setRuleSyncLastSuccess:(NSDate *)date reply:(void (^)(void))reply;
- (void)setSyncCleanRequired:(BOOL)cleanReqd reply:(void (^)(void))reply;
- (void)setWhitelistPathRegex:(NSString *)pattern reply:(void (^)(void))reply;
- (void)setBlacklistPathRegex:(NSString *)pattern reply:(void (^)(void))reply;
- (void)setEnableBundles:(BOOL)bundlesEnabled reply:(void (^)(void))reply;
- (void)setEnableTransitiveWhitelisting:(BOOL)enabled reply:(void (^)(void))reply;
///
/// Syncd Ops
///
- (void)setSyncdListener:(NSXPCListenerEndpoint *)listener;
- (void)pushNotifications:(void (^)(BOOL))reply;
- (void)postRuleSyncNotificationWithCustomMessage:(NSString *)message reply:(void (^)())reply;
///
/// Bundle Ops
///
- (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event reply:(SNTBundleHashBlock)reply;
- (void)syncBundleEvent:(SNTStoredEvent *)event relatedEvents:(NSArray<SNTStoredEvent *> *)events;
- (void)postRuleSyncNotificationWithCustomMessage:(NSString *)message reply:(void (^)(void))reply;
@end
@interface SNTXPCControlInterface : NSObject
@interface SNTXPCControlInterface : SNTXPCUnprivilegedControlInterface
///
/// Returns the MachService ID for this service.
/// Internal method used to initialize the control interface
///
+ (NSString *)serviceId;
///
/// Returns an initialized NSXPCInterface for the SNTDaemonControlXPC protocol.
/// Ensures any methods that accept custom classes as arguments are set-up before returning
///
+ (NSXPCInterface *)controlInterface;
///
/// Retrieve a pre-configured SNTXPCConnection for communicating with santad.
/// Connections just needs any handlers set and then can be resumed and used.
///
+ (SNTXPCConnection *)configuredConnection;
+ (void)initializeControlInterface:(NSXPCInterface *)r;
@end

View File

@@ -12,11 +12,12 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTXPCControlInterface.h"
#import "Source/common/SNTXPCControlInterface.h"
#import "SNTRule.h"
#import "SNTStoredEvent.h"
#import "SNTXPCConnection.h"
#import <MOLXPCConnection/MOLXPCConnection.h>
#import "Source/common/SNTRule.h"
#import "Source/common/SNTStoredEvent.h"
@implementation SNTXPCControlInterface
@@ -24,8 +25,8 @@
return @"SantaXPCControl";
}
+ (NSXPCInterface *)controlInterface {
NSXPCInterface *r = [NSXPCInterface interfaceWithProtocol:@protocol(SNTDaemonControlXPC)];
+ (void)initializeControlInterface:(NSXPCInterface *)r {
[super initializeControlInterface:r];
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
forSelector:@selector(databaseEventsPending:)
@@ -36,22 +37,17 @@
forSelector:@selector(databaseRuleAddRules:cleanSlate:reply:)
argumentIndex:0
ofReply:NO];
}
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
forSelector:@selector(hashBundleBinariesForEvent:reply:)
argumentIndex:1
ofReply:YES];
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
forSelector:@selector(syncBundleEvent:relatedEvents:)
argumentIndex:1
ofReply:NO];
+ (NSXPCInterface *)controlInterface {
NSXPCInterface *r = [NSXPCInterface interfaceWithProtocol:@protocol(SNTDaemonControlXPC)];
[self initializeControlInterface:r];
return r;
}
+ (SNTXPCConnection *)configuredConnection {
SNTXPCConnection *c = [[SNTXPCConnection alloc] initClientWithName:[self serviceId]
+ (MOLXPCConnection *)configuredConnection {
MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithName:[self serviceId]
privileged:YES];
c.remoteInterface = [self controlInterface];
return c;

View File

@@ -12,10 +12,10 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
#import "SNTCommonEnums.h"
#import "SNTXPCBundleServiceInterface.h"
#import "Source/common/SNTCommonEnums.h"
#import "Source/common/SNTXPCBundleServiceInterface.h"
@class SNTStoredEvent;

View File

@@ -12,7 +12,7 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTXPCNotifierInterface.h"
#import "Source/common/SNTXPCNotifierInterface.h"
@implementation SNTXPCNotifierInterface

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
@import Foundation;
#import <Foundation/Foundation.h>
#import "SNTCommonEnums.h"
#import "Source/common/SNTCommonEnums.h"
@class SNTStoredEvent;

View File

@@ -12,9 +12,9 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTXPCSyncdInterface.h"
#import "Source/common/SNTXPCSyncdInterface.h"
#import "SNTStoredEvent.h"
#import "Source/common/SNTStoredEvent.h"
@implementation SNTXPCSyncdInterface

View File

@@ -0,0 +1,121 @@
/// 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 <Foundation/Foundation.h>
#import <MOLCertificate/MOLCertificate.h>
#import "Source/common/SNTCommonEnums.h"
#import "Source/common/SNTKernelCommon.h"
#import "Source/common/SNTXPCBundleServiceInterface.h"
@class SNTRule;
@class SNTStoredEvent;
@class MOLXPCConnection;
///
/// Protocol implemented by santad and utilized by santactl (unprivileged operations)
///
@protocol SNTUnprivilegedDaemonControlXPC
///
/// Kernel ops
///
- (void)cacheCounts:(void (^)(uint64_t rootCache, uint64_t nonRootCache))reply;
- (void)cacheBucketCount:(void (^)(NSArray *))reply;
- (void)checkCacheForVnodeID:(santa_vnode_id_t)vnodeID withReply:(void (^)(santa_action_t))reply;
- (void)driverConnectionEstablished:(void (^)(BOOL))reply;
///
/// Database ops
///
- (void)databaseRuleCounts:(void (^)(int64_t binary,
int64_t certificate,
int64_t compiler,
int64_t transitive))reply;
- (void)databaseEventCount:(void (^)(int64_t count))reply;
///
/// Decision ops
///
///
/// @param filePath A Path to the file, can be nil.
/// @param fileSHA256 The pre-calculated SHA256 hash for the file, can be nil. If nil the hash will
/// be calculated by this method from the filePath.
/// @param certificateSHA256 A SHA256 hash of the signing certificate, can be nil.
/// @note If fileInfo and signingCertificate are both passed in, the most specific rule will be
/// returned. Binary rules take precedence over cert rules.
///
- (void)decisionForFilePath:(NSString *)filePath
fileSHA256:(NSString *)fileSHA256
certificateSHA256:(NSString *)certificateSHA256
reply:(void (^)(SNTEventState))reply;
///
/// Config ops
///
- (void)watchdogInfo:(void (^)(uint64_t, uint64_t, double, double))reply;
- (void)xsrfToken:(void (^)(NSString *))reply;
- (void)clientMode:(void (^)(SNTClientMode))reply;
- (void)fullSyncLastSuccess:(void (^)(NSDate *))reply;
- (void)ruleSyncLastSuccess:(void (^)(NSDate *))reply;
- (void)syncCleanRequired:(void (^)(BOOL))reply;
- (void)enableBundles:(void (^)(BOOL))reply;
- (void)enableTransitiveWhitelisting:(void (^)(BOOL))reply;
///
/// GUI Ops
///
- (void)setNotificationListener:(NSXPCListenerEndpoint *)listener;
- (void)setBundleNotificationListener:(NSXPCListenerEndpoint *)listener;
///
/// Syncd Ops
///
- (void)pushNotifications:(void (^)(BOOL))reply;
///
/// Bundle Ops
///
- (void)hashBundleBinariesForEvent:(SNTStoredEvent *)event reply:(SNTBundleHashBlock)reply;
- (void)syncBundleEvent:(SNTStoredEvent *)event relatedEvents:(NSArray<SNTStoredEvent *> *)events;
@end
@interface SNTXPCUnprivilegedControlInterface : NSObject
///
/// Returns the MachService ID for this service.
///
+ (NSString *)serviceId;
///
/// Returns an initialized NSXPCInterface for the SNTUnprivilegedDaemonControlXPC protocol.
/// Ensures any methods that accept custom classes as arguments are set-up before returning
///
+ (NSXPCInterface *)controlInterface;
///
/// Retrieve a pre-configured MOLXPCConnection for communicating with santad.
/// Connections just needs any handlers set and then can be resumed and used.
///
+ (MOLXPCConnection *)configuredConnection;
///
/// Internal method used to initialize the control interface
///
+ (void)initializeControlInterface:(NSXPCInterface *)r;
@end

View File

@@ -0,0 +1,54 @@
/// 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 "Source/common/SNTXPCUnprivilegedControlInterface.h"
#import <MOLXPCConnection/MOLXPCConnection.h>
#import "Source/common/SNTRule.h"
#import "Source/common/SNTStoredEvent.h"
@implementation SNTXPCUnprivilegedControlInterface
+ (NSString *)serviceId {
return @"SantaUnprivilegedXPCControl";
}
+ (void)initializeControlInterface:(NSXPCInterface *)r {
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
forSelector:@selector(hashBundleBinariesForEvent:reply:)
argumentIndex:1
ofReply:YES];
[r setClasses:[NSSet setWithObjects:[NSArray class], [SNTStoredEvent class], nil]
forSelector:@selector(syncBundleEvent:relatedEvents:)
argumentIndex:1
ofReply:NO];
}
+ (NSXPCInterface *)controlInterface {
NSXPCInterface *r = [NSXPCInterface interfaceWithProtocol:@protocol(SNTUnprivilegedDaemonControlXPC)];
[self initializeControlInterface:r];
return r;
}
+ (MOLXPCConnection *)configuredConnection {
MOLXPCConnection *c = [[MOLXPCConnection alloc] initClientWithName:[self serviceId]
privileged:YES];
c.remoteInterface = [self controlInterface];
return c;
}
@end

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>16F73</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>DirectoryBundle</string>
<key>CFBundleIdentifier</key>
<string>com.google.santa.DirectoryBundle</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>DirectoryBundle</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>7D1014</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>15E60</string>
<key>DTSDKName</key>
<string>macosx10.11</string>
<key>DTXcode</key>
<string>0731</string>
<key>DTXcodeBuild</key>
<string>7D1014</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 Google. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

Binary file not shown.

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>16F73</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>BundleExample</string>
<key>CFBundleIdentifier</key>
<string>com.google.santa.BundleExample</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>BundleExample</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>7D1014</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>15E60</string>
<key>DTSDKName</key>
<string>macosx10.11</string>
<key>DTXcode</key>
<string>0731</string>
<key>DTXcodeBuild</key>
<string>7D1014</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Google. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

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