Compare commits

..

18 Commits
0.8 ... 0.8.2

Author SHA1 Message Date
Russell Hancox
56d4a6b9fb santa-driver: Change when we consider the client connected to avoid getting into a state where events are being held but no memory descriptor is in place yet. 2015-03-10 17:40:03 -04:00
Russell Hancox
28a94cd56a santa-driver: each error state is already logged, don't log again 2015-03-10 17:39:29 -04:00
Russell Hancox
4344fc3d7d santa-driver: Remove process listener, it doesn't do anything useful and stops Hopper from working 2015-03-09 18:38:22 -04:00
Russell Hancox
40431d835e SNTStoredEvent: pid and ppid need to be encoded/decoded to be included in database/uploads 2015-03-09 12:19:26 -04:00
Russell Hancox
942804c478 santa-driver: Fix typo 2015-03-09 11:44:09 -04:00
Russell Hancox
d109aae6ef santad/santactl: include pid and ppid in event upload 2015-03-09 09:52:56 -04:00
Russell Hancox
b89040c37a santactl/sync: Add ability to refuse redirects 2015-03-06 17:41:31 -05:00
Russell Hancox
63aefb4654 santa-driver: increase max queue events to 256 2015-03-06 12:00:48 -05:00
Russell Hancox
1c92e968e3 SNTAuthenticatingURLSession: remove unnecessary import 2015-03-06 12:00:33 -05:00
Russell Hancox
c1b7f9ae63 SNTAuthenticatingURLSession: fix potential crash where client identity
is released before NSURLCredential is created
2015-03-05 13:58:31 -05:00
Russell Hancox
0507bc83d2 SNTCertificate: comment updats 2015-03-05 12:04:19 -05:00
Russell Hancox
7028c24425 Add missing copyright header from SNTDERDecoder.m 2015-03-05 12:03:55 -05:00
Russell Hancox
6ede057521 Update README.md 2015-02-04 10:26:12 -05:00
Russell Hancox
6f2ccca60a Tests: Add to SNTDERDecoderTest and SNTCertificateTest 2015-02-03 22:48:04 -05:00
Russell Hancox
a59d2aa8a9 Merge branch 'kext-listener-move' 2015-02-03 18:58:46 -05:00
Russell Hancox
d88fa4ecfe santad: sleep for less time when waiting for driver 2015-02-03 18:56:25 -05:00
Russell Hancox
4df93bfe6c Project: Fix version info 2015-02-03 18:56:08 -05:00
Russell Hancox
08ca3c9d95 Driver: Move SantaDecisionManager ownership to IOService level, start listeners ASAP but allow and log until daemon connects. Remove useless close method in SantaDriverClient. 2015-02-03 18:55:24 -05:00
26 changed files with 354 additions and 263 deletions

View File

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

View File

@@ -42,6 +42,7 @@
0D1B477119A53419008CADD3 /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0D1B476F19A53419008CADD3 /* AboutWindow.xib */; };
0D20710E1A7C4A86008B0A9A /* SNTStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD604A19105433006B445C /* SNTStoredEvent.m */; };
0D28D53819D9F5910015C5EB /* SNTConfigurator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D42D2B719D2042900955F08 /* SNTConfigurator.m */; };
0D2CD4611A81C7B100C9C910 /* dn.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0D2CD4601A81C7B100C9C910 /* dn.plist */; };
0D31DF4718D254B3002B300D /* SNTCodesignChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D59C0E317710E6000748EBF /* SNTCodesignChecker.m */; };
0D35BD9F18FD71CE00921A21 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D9A7F3E1759330500035EB5 /* Foundation.framework */; };
0D35BDA218FD71CE00921A21 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDA118FD71CE00921A21 /* main.m */; };
@@ -213,6 +214,7 @@
0D28E5E119269B3600280F87 /* SNTLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTLogging.h; sourceTree = "<group>"; };
0D28E5E31926AFE400280F87 /* SNTKernelCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SNTKernelCommon.h; sourceTree = "<group>"; };
0D28E5E41926B55600280F87 /* santactl-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "santactl-Info.plist"; sourceTree = "<group>"; };
0D2CD4601A81C7B100C9C910 /* dn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = dn.plist; sourceTree = "<group>"; };
0D35BD9E18FD71CE00921A21 /* santactl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = santactl; sourceTree = BUILT_PRODUCTS_DIR; };
0D35BDA118FD71CE00921A21 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
0D35BDA418FD71CE00921A21 /* santactl-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "santactl-Prefix.pch"; sourceTree = "<group>"; };
@@ -403,6 +405,7 @@
0D260DB018B68E12002A0B55 /* Resources */ = {
isa = PBXGroup;
children = (
0D2CD4601A81C7B100C9C910 /* dn.plist */,
0D6FDC8618C6913D0044685C /* apple.pem */,
0D6FDC8218C68D7E0044685C /* GIAG2.crt */,
0D6FDC8418C68E500044685C /* GIAG2.pem */,
@@ -568,12 +571,12 @@
0D91BCB9174E8A7E00131A7D /* santa-driver */ = {
isa = PBXGroup;
children = (
0D4644C4182AF81700098690 /* SantaDecisionManager.h */,
0D4644C3182AF81700098690 /* SantaDecisionManager.cc */,
0D9A7F321759144800035EB5 /* SantaDriver.h */,
0D9A7F311759144800035EB5 /* SantaDriver.cc */,
0D9A7F361759148E00035EB5 /* SantaDriverClient.h */,
0D9A7F351759148E00035EB5 /* SantaDriverClient.cc */,
0D4644C4182AF81700098690 /* SantaDecisionManager.h */,
0D4644C3182AF81700098690 /* SantaDecisionManager.cc */,
0D7A7AF2174FCF4C00B77646 /* SantaMessage.h */,
0D7A7AF1174FCF4C00B77646 /* SantaMessage.cc */,
0DA36C1F199EA46600A129D6 /* Resources */,
@@ -863,6 +866,7 @@
0D6FDC8518C68E500044685C /* GIAG2.pem in Resources */,
0D6FDC8318C68D7E0044685C /* GIAG2.crt in Resources */,
0D6F12DA19EDE51E006B218E /* tubitak.crt in Resources */,
0D2CD4611A81C7B100C9C910 /* dn.plist in Resources */,
0D6FDC8718C6913D0044685C /* apple.pem in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -894,7 +898,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\n newVersion=\"${GIT_TAG}d${GIT_COMMIT}\"\nelse\n newVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\n newVersion=\"${GIT_TAG}d ${GIT_COMMIT}\"\nelse\n newVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
};
0D673DAD18FC9017009C5B06 /* Delete existing coverage files */ = {
isa = PBXShellScriptBuildPhase;
@@ -925,7 +929,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\nnewVersion=\"${GIT_TAG}d${GIT_COMMIT}\"\nelse\nnewVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\nnewVersion=\"${GIT_TAG}d ${GIT_COMMIT}\"\nelse\nnewVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
};
0DD98E671A5DD02000A754C6 /* Update Version Info */ = {
isa = PBXShellScriptBuildPhase;
@@ -941,7 +945,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\nnewVersion=\"${GIT_TAG}d${GIT_COMMIT}\"\nelse\nnewVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\nnewVersion=\"${GIT_TAG}d ${GIT_COMMIT}\"\nelse\nnewVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
};
0DD98E681A5DD03E00A754C6 /* Update Version Info */ = {
isa = PBXShellScriptBuildPhase;
@@ -957,7 +961,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\nnewVersion=\"${GIT_TAG}d${GIT_COMMIT}\"\nelse\nnewVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
shellScript = "GIT_TAG=$(git describe --abbrev=0 --tags)\nGIT_COMMIT=$(git rev-parse --short HEAD)\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\n\nif [ $CONFIGURATION = \"Debug\" ]; then\nnewVersion=\"${GIT_TAG}d ${GIT_COMMIT}\"\nelse\nnewVersion=\"${GIT_TAG}\"\nfi\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion ${GIT_TAG}\" ${SCRIPT_OUTPUT_FILE_0}\n/usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString ${newVersion}\" ${SCRIPT_OUTPUT_FILE_0}";
};
0DD98E691A5DD5C900A754C6 /* Update Module Version */ = {
isa = PBXShellScriptBuildPhase;

View File

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

View File

@@ -30,7 +30,6 @@
// List of methods supported by the driver.
enum SantaDriverMethods {
kSantaUserClientOpen,
kSantaUserClientClose,
kSantaUserClientAllowBinary,
kSantaUserClientDenyBinary,
kSantaUserClientClearCache,

View File

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

View File

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

View File

@@ -19,40 +19,15 @@ OSDefineMetaClassAndStructors(SantaDecisionManager, OSObject);
#pragma mark Object Lifecycle
SantaDecisionManager *SantaDecisionManager::WithQueueAndPID(
IOSharedDataQueue *queue, pid_t pid) {
SantaDecisionManager *me = new SantaDecisionManager;
bool SantaDecisionManager::init() {
dataqueue_lock_ = IORWLockAlloc();
cached_decisions_lock_ = IORWLockAlloc();
cached_decisions_ = OSDictionary::withCapacity(1000);
if (me && !me->InitWithQueueAndPID(queue, pid)) {
me->free();
return NULL;
}
return me;
}
bool SantaDecisionManager::InitWithQueueAndPID(
IOSharedDataQueue *queue, pid_t pid) {
if (!super::init()) return false;
if (!pid) return false;
if (!queue) return false;
listener_invocations_ = 0;
dataqueue_ = queue;
owning_pid_ = pid;
owning_proc_ = proc_find(pid);
if (!(dataqueue_lock_ = IORWLockAlloc())) return FALSE;
if (!(cached_decisions_lock_ = IORWLockAlloc())) return FALSE;
if (!(cached_decisions_ = OSDictionary::withCapacity(1000))) return FALSE;
return TRUE;
return kIOReturnSuccess;
}
void SantaDecisionManager::free() {
proc_rele(owning_proc_);
if (cached_decisions_) {
cached_decisions_->release();
cached_decisions_ = NULL;
@@ -63,7 +38,7 @@ void SantaDecisionManager::free() {
cached_decisions_lock_ = NULL;
}
if (dataqueue_lock_) {
if (dataqueue_lock_ ) {
IORWLockFree(dataqueue_lock_);
dataqueue_lock_ = NULL;
}
@@ -71,7 +46,77 @@ void SantaDecisionManager::free() {
super::free();
}
# pragma mark Cache Management
#pragma mark Client Management
void SantaDecisionManager::ConnectClient(IOSharedDataQueue *queue, pid_t pid) {
if (!pid) return;
if (!queue) return;
// Any decisions made while the daemon wasn't
// connected should be cleared
cached_decisions_->flushCollection();
dataqueue_ = queue;
dataqueue_->retain();
owning_pid_ = pid;
owning_proc_ = proc_find(pid);
}
void SantaDecisionManager::DisconnectClient() {
owning_pid_ = -1;
// Ask santad to shutdown, in case it's running.
santa_message_t message;
message.action = ACTION_REQUEST_SHUTDOWN;
message.userId = 0;
message.pid = 0;
message.ppid = 0;
message.vnode_id = 0;
PostToQueue(message);
dataqueue_->release();
dataqueue_ = NULL;
proc_rele(owning_proc_);
owning_proc_ = NULL;
}
bool SantaDecisionManager::ClientConnected() {
return owning_pid_ > 0;
}
# pragma mark Listener Control
kern_return_t SantaDecisionManager::StartListener() {
vnode_listener_ = kauth_listen_scope(KAUTH_SCOPE_VNODE,
vnode_scope_callback,
reinterpret_cast<void *>(this));
if (!vnode_listener_) return kIOReturnInternalError;
LOGD("Vnode listener started.");
return kIOReturnSuccess;
}
kern_return_t SantaDecisionManager::StopListener() {
kauth_unlisten_scope(vnode_listener_);
vnode_listener_ = NULL;
// Wait for any active invocations to finish before returning
do {
IOSleep(5);
} while (listener_invocations_);
// Delete any cached decisions
ClearCache();
LOGD("Vnode listener stopped.");
return kIOReturnSuccess;
}
#pragma mark Cache Management
void SantaDecisionManager::AddToCache(
const char *identifier, santa_action_t decision, uint64_t microsecs) {
@@ -169,7 +214,10 @@ santa_action_t SantaDecisionManager::GetFromCache(const char *identifier) {
bool SantaDecisionManager::PostToQueue(santa_message_t message) {
IORWLockWrite(dataqueue_lock_);
bool kr = dataqueue_->enqueue(&message, sizeof(message));
bool kr = false;
if (dataqueue_) {
kr = dataqueue_->enqueue(&message, sizeof(message));
}
IORWLockUnlock(dataqueue_lock_);
return kr;
}
@@ -200,6 +248,14 @@ santa_action_t SantaDecisionManager::FetchDecision(
path[0] = '\0';
}
if (!ClientConnected()) {
LOGI("Execution request without daemon running: %s", path);
AddToCache(vnode_id_str,
ACTION_RESPOND_CHECKBW_ALLOW,
GetCurrentUptime());
return ACTION_RESPOND_CHECKBW_ALLOW;
}
// Prepare to send message to daemon
santa_message_t message;
strncpy(message.path, path, MAX_PATH_LEN);
@@ -260,10 +316,6 @@ uint64_t SantaDecisionManager::GetCurrentUptime() {
# pragma mark Invocation Tracking & PID comparison
SInt32 SantaDecisionManager::GetListenerInvocations() {
return listener_invocations_;
}
void SantaDecisionManager::IncrementListenerInvocations() {
OSIncrementAtomic(&listener_invocations_);
}
@@ -272,78 +324,9 @@ void SantaDecisionManager::DecrementListenerInvocations() {
OSDecrementAtomic(&listener_invocations_);
}
bool SantaDecisionManager::MatchesOwningPID(const pid_t other_pid) {
return (owning_pid_ == other_pid);
}
# pragma mark Listener Control
kern_return_t SantaDecisionManager::StartListener() {
process_listener_ = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
process_scope_callback,
reinterpret_cast<void *>(this));
if (!process_listener_) return kIOReturnInternalError;
LOGD("Process listener started.");
vnode_listener_ = kauth_listen_scope(KAUTH_SCOPE_VNODE,
vnode_scope_callback,
reinterpret_cast<void *>(this));
if (!vnode_listener_) return kIOReturnInternalError;
LOGD("Vnode listener started.");
return kIOReturnSuccess;
}
kern_return_t SantaDecisionManager::StopListener() {
kauth_unlisten_scope(vnode_listener_);
vnode_listener_ = NULL;
kauth_unlisten_scope(process_listener_);
process_listener_ = NULL;
// Wait for any active invocations to finish before returning
do {
IOSleep(5);
} while (GetListenerInvocations());
// Delete any cached decisions
ClearCache();
LOGD("Vnode listener stopped.");
LOGD("Process listener stopped.");
return kIOReturnSuccess;
}
#undef super
#pragma mark Kauth Callbacks
extern "C" int process_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) {
if (idata == NULL) {
LOGE("Process callback established without valid decision manager.");
return KAUTH_RESULT_ALLOW;
}
SantaDecisionManager *sdm = OSDynamicCast(
SantaDecisionManager, reinterpret_cast<OSObject *>(idata));
// NOTE: this prevents a debugger from attaching to an existing santad
// process but doesn't prevent starting santad under a debugger. This check
// is only here to try and prevent the user from deadlocking their machine
// by attaching a debugger, so if they work around it and end up deadlocking,
// that's their problem.
if (action == KAUTH_PROCESS_CANTRACE &&
sdm->MatchesOwningPID(proc_pid((proc_t)arg0))) {
*(reinterpret_cast<int *>(arg1)) = EPERM;
LOGD("Denied debugger access");
return KAUTH_RESULT_DENY;
}
return KAUTH_RESULT_ALLOW;
}
#pragma mark Kauth Callback
extern "C" int vnode_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
@@ -368,7 +351,7 @@ extern "C" int vnode_scope_callback(
// Don't operate on ACCESS events, as they're advisory
if (action & KAUTH_VNODE_ACCESS) return returnResult;
// Filter for only WRITE_DATA actions
// Filter for only writes
if (action & KAUTH_VNODE_WRITE_DATA ||
action & KAUTH_VNODE_APPEND_DATA ||
action & KAUTH_VNODE_DELETE) {
@@ -408,17 +391,7 @@ extern "C" int vnode_scope_callback(
default:
// NOTE: Any unknown response or error condition causes us to fail open.
// Whilst from a security perspective this is bad, it's important that
// we don't break user's machines. Every fallen open response will come
// through this code path and cause this log entry to be created, so we
// can investigate each case and try to fix the root cause.
char path[MAX_PATH_LEN];
int name_len = MAX_PATH_LEN;
if (vn_getpath(vnode, path, &name_len) != 0) {
path[0] = '\0';
}
LOGW("Didn't receive a valid response for %s. Received: %d.",
path,
returnedAction);
// we don't break user's machines.
break;
}

View File

@@ -66,47 +66,73 @@ class SantaDecisionManager : public OSObject {
OSDeclareDefaultStructors(SantaDecisionManager);
public:
// Convenience constructor
// Queue remains owned by caller but must exist for lifetime of
// SantaDecisionManager instance.
static SantaDecisionManager *WithQueueAndPID(
IOSharedDataQueue *queue, pid_t pid);
/// Used for initialization after instantiation. Required because
/// constructors cannot throw inside kernel-space.
bool init();
bool InitWithQueueAndPID(IOSharedDataQueue *queue, pid_t pid);
/// Called automatically when retain count drops to 0.
void free();
// Decision Fetching / Daemon Communication
/// Called by SantaDriverClient when a client connects, providing the data
/// queue used to pass messages and the pid of the client process.
void ConnectClient(IOSharedDataQueue *queue, pid_t pid);
/// Called by SantaDriverClient when a client disconnects
void DisconnectClient();
/// Returns whether a client is currently connected or not.
bool ClientConnected();
/// Starts the kauth listener.
kern_return_t StartListener();
/// Stops the kauth listener. After stopping new callback requests,
/// waits until all current invocations have finished before clearing the
/// cache and returning.
kern_return_t StopListener();
/// Adds a decision to the cache, with a timestamp.
void AddToCache(const char *identifier,
const santa_action_t decision,
const uint64_t microsecs);
/// Checks to see if a given identifier is in the cache and removes it.
void CacheCheck(const char *identifier);
/// Returns the number of entries in the cache.
uint64_t CacheCount();
/// Clears the cache.
void ClearCache();
/// Fetches a response from the cache, first checking to see if the
/// entry has expired.
santa_action_t GetFromCache(const char *identifier);
/// Posts the requested message to the client data queue, if there is one.
/// Uses dataqueue_lock_ to ensure two threads don't try to write to the
/// queue at the same time.
bool PostToQueue(santa_message_t);
/// Fetches an execution decision for a file, first using the cache and then
/// by sending a message to the daemon and waiting until a response arrives.
/// If a daemon isn't connected, will allow execution and cache, logging
/// the path to the executed file.
santa_action_t FetchDecision(const kauth_cred_t credential,
const vfs_context_t vfs_context,
const vnode_t vnode);
// Vnode ID string
/// Fetches the vnode_id for a given vnode.
uint64_t GetVnodeIDForVnode(const vfs_context_t context, const vnode_t vp);
// Cache management
void AddToCache(const char *identifier,
const santa_action_t decision,
const uint64_t microsecs);
void CacheCheck(const char *identifier);
uint64_t CacheCount();
void ClearCache();
santa_action_t GetFromCache(const char *identifier);
// Listener invocation management
SInt32 GetListenerInvocations();
void IncrementListenerInvocations();
void DecrementListenerInvocations();
// Owning PID comparison
bool MatchesOwningPID(const pid_t other_pid);
// Returns the current system uptime in microseconds
/// Returns the current system uptime in microseconds
uint64_t GetCurrentUptime();
// Starting and stopping the listener
kern_return_t StartListener();
kern_return_t StopListener();
/// Increments the count of active vnode callback's pending.
void IncrementListenerInvocations();
/// Decrements the count of active vnode callback's pending.
void DecrementListenerInvocations();
private:
OSDictionary *cached_decisions_;
@@ -121,7 +147,6 @@ class SantaDecisionManager : public OSObject {
proc_t owning_proc_;
kauth_listener_t vnode_listener_;
kauth_listener_t process_listener_;
};
///
@@ -138,18 +163,4 @@ extern "C" int vnode_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
///
/// The kauth callback function for the Process scope
/// @param actor's credentials
/// @param data that was passed when the listener was registered
/// @param action that was requested (KAUTH_PROCESS_{CANTRACE,CANSIGNAL})
/// @param target process
/// @param Pointer to an errno-style error.
/// @param unused
/// @param unused
///
extern "C" int process_scope_callback(
kauth_cred_t credential, void *idata, kauth_action_t action,
uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
#endif // SANTA__SANTA_DRIVER__SANTADECISIONMANAGER_H

View File

@@ -23,6 +23,10 @@ OSDefineMetaClassAndStructors(com_google_SantaDriver, IOService);
bool SantaDriver::start(IOService *provider) {
if (!super::start(provider)) return false;
santaDecisionManager = new SantaDecisionManager;
santaDecisionManager->init();
santaDecisionManager->StartListener();
registerService();
LOGI("Loaded, version %s.", OSKextGetCurrentVersionString());
@@ -31,7 +35,17 @@ bool SantaDriver::start(IOService *provider) {
}
void SantaDriver::stop(IOService *provider) {
santaDecisionManager->StopListener();
santaDecisionManager->release();
santaDecisionManager = NULL;
LOGI("Unloaded.");
super::stop(provider);
}
SantaDecisionManager* SantaDriver::GetDecisionManager() {
return santaDecisionManager;
}
#undef super

View File

@@ -22,14 +22,26 @@
#include "SNTLogging.h"
///
/// The driver class, which provides just the start/stop functions.
/// The driver class, which provides the start/stop functions and holds
/// the SantaDecisionManager instance which the connected client
/// communicates with.
///
class com_google_SantaDriver : public IOService {
OSDeclareDefaultStructors(com_google_SantaDriver);
public:
/// Called by the kernel when the kext is loaded
bool start(IOService *provider);
/// Called by the kernel when the kext is unloaded
void stop(IOService *provider);
/// Returns a pointer to the SantaDecisionManager created in start().
SantaDecisionManager* GetDecisionManager();
private:
SantaDecisionManager *santaDecisionManager;
};
#endif // SANTA__SANTA_DRIVER__SANTADRIVER_H

View File

@@ -20,7 +20,7 @@
// The defines above can'be used in this function, must use the full names.
OSDefineMetaClassAndStructors(com_google_SantaDriverClient, IOUserClient);
# pragma mark Driver Management
#pragma mark Driver Management
bool SantaDriverClient::initWithTask(
task_t owningTask, void *securityID, UInt32 type) {
@@ -41,52 +41,38 @@ bool SantaDriverClient::start(IOService *provider) {
if (!fProvider) return false;
if (!super::start(provider)) return false;
fSDMLock = IOLockAlloc();
fSDM = fProvider->GetDecisionManager();
return true;
}
void SantaDriverClient::stop(IOService *provider) {
super::stop(provider);
fProvider = NULL;
}
IOReturn SantaDriverClient::clientClose() {
close();
terminate(kIOServiceSynchronous);
fProvider = NULL;
return kIOReturnSuccess;
}
bool SantaDriverClient::terminate(IOOptionBits options) {
// We have to lock before this check in case the client exits and the kext
// is unloaded very shortly afterwards.
IOLockLock(fSDMLock);
if (fSDM) {
fSDM->StopListener();
fSDM->DisconnectClient();
LOGI("Client disconnected.");
// Ask santad to shutdown
santa_message_t message;
message.action = ACTION_REQUEST_SHUTDOWN;
message.userId = 0;
message.pid = 0;
message.ppid = 0;
message.vnode_id = 0;
fSDM->PostToQueue(message);
fSharedMemory->release();
fDataQueue->release();
LOGI("Client disconnected.");
fSDM->release();
fSDM = NULL;
}
IOLockUnlock(fSDMLock);
fSharedMemory = NULL;
fDataQueue = NULL;
if (fProvider && fProvider->isOpen(this)) fProvider->close(this);
return super::terminate(options);
}
#pragma mark Fetching memory and data queue notifications
IOReturn SantaDriverClient::registerNotificationPort(mach_port_t port,
UInt32 type,
UInt32 ref) {
@@ -108,7 +94,10 @@ IOReturn SantaDriverClient::clientMemoryForType(UInt32 type,
fSharedMemory->retain(); // client will decrement this ref
*memory = fSharedMemory;
return fSDM->StartListener();
fSDM->ConnectClient(fDataQueue, proc_selfpid());
LOGI("Client connected, PID: %d.", proc_selfpid());
return kIOReturnSuccess;
}
return kIOReturnNoMemory;
@@ -136,12 +125,6 @@ IOReturn SantaDriverClient::open() {
return kIOReturnVMError;
}
IOLockLock(fSDMLock);
fSDM = SantaDecisionManager::WithQueueAndPID(fDataQueue, proc_selfpid());
IOLockUnlock(fSDMLock);
LOGI("Client connected, PID: %d.", proc_selfpid());
return kIOReturnSuccess;
}
@@ -153,21 +136,6 @@ IOReturn SantaDriverClient::static_open(
return target->open();
}
IOReturn SantaDriverClient::close() {
if (!fProvider) return kIOReturnNotAttached;
if (fProvider->isOpen(this)) fProvider->close(this);
return kIOReturnSuccess;
}
IOReturn SantaDriverClient::static_close(
SantaDriverClient *target,
void *reference,
IOExternalMethodArguments *arguments) {
if (!target) return kIOReturnBadArgument;
return target->close();
}
IOReturn SantaDriverClient::allow_binary(const uint64_t vnode_id) {
char vnode_id_str[21];
snprintf(vnode_id_str, sizeof(vnode_id_str), "%llu", vnode_id);
@@ -240,8 +208,8 @@ IOReturn SantaDriverClient::externalMethod(
IOExternalMethodDispatch *dispatch,
OSObject *target,
void *reference) {
// Array of methods callable by clients. The order of these must match the
// order of the items in |SantaDriverMethods| in SNTKernelCommon.h
/// Array of methods callable by clients. The order of these must match the
/// order of the items in SantaDriverMethods in SNTKernelCommon.h
IOExternalMethodDispatch sMethods[kSantaUserClientNMethods] = {
{
reinterpret_cast<IOExternalMethodAction>(&SantaDriverClient::static_open),
@@ -250,14 +218,6 @@ IOReturn SantaDriverClient::externalMethod(
0, // output scalar
0 // output struct
},
{
reinterpret_cast<IOExternalMethodAction>(
&SantaDriverClient::static_close),
0,
0,
0,
0
},
{
reinterpret_cast<IOExternalMethodAction>(
&SantaDriverClient::static_allow_binary),

View File

@@ -29,7 +29,7 @@
#include "SNTKernelCommon.h"
// The maximum number of messages can be kept in the IODataQueue at any time.
const int kMaxQueueEvents = 64;
const int kMaxQueueEvents = 256;
///
/// This class is instantiated by IOKit when a new client process attempts to
@@ -38,7 +38,7 @@ const int kMaxQueueEvents = 64;
///
/// Documentation on how the IOUserClient parts of this code work can be found
/// here:
/// @link https://developer.apple.com/library/mac/samplecode/SimpleUserClient/Listings/User_Client_Info_txt.html
/// https://developer.apple.com/library/mac/samplecode/SimpleUserClient/Listings/User_Client_Info_txt.html
///
class com_google_SantaDriverClient : public IOUserClient {
OSDeclareDefaultStructors(com_google_SantaDriverClient);
@@ -48,61 +48,75 @@ class com_google_SantaDriverClient : public IOUserClient {
IOMemoryDescriptor *fSharedMemory;
com_google_SantaDriver *fProvider;
SantaDecisionManager *fSDM;
IOLock *fSDMLock;
public:
bool start(IOService *provider);
void stop(IOService *provider);
IOReturn clientClose();
bool terminate(IOOptionBits options);
/// Called as part of IOServiceOpen in clients
bool initWithTask(task_t owningTask, void *securityID, UInt32 type);
/// Called after initWithTask as part of IOServiceOpen
bool start(IOService *provider);
/// Called when this class is stopping
void stop(IOService *provider);
/// Called when a client disconnects
IOReturn clientClose();
/// Called when the driver is shutting down
bool terminate(IOOptionBits options);
/// Called in clients with IOConnectSetNotificationPort
IOReturn registerNotificationPort(
mach_port_t port, UInt32 type, UInt32 refCon);
/// Called in clients with IOConnectMapMemory
IOReturn clientMemoryForType(
UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory);
/// Called in clients with IOConnectCallScalarMethod etc. Dispatches
/// to the requested selector using the SantaDriverMethods enum in
/// SNTKernelCommon.
IOReturn externalMethod(
UInt32 selector,
IOExternalMethodArguments *arguments,
IOExternalMethodDispatch *dispatch,
OSObject *target, void *reference);
///
/// The userpsace callable methods are below. Each method corresponds
/// to an entry in SantaDriverMethods. Each method has a static version
/// which just calls the method on the provided target.
///
/// Called during client connection
IOReturn open();
static IOReturn static_open(
com_google_SantaDriverClient *target,
void *reference,
IOExternalMethodArguments *arguments);
IOReturn close();
static IOReturn static_close(
com_google_SantaDriverClient *target,
void *reference,
IOExternalMethodArguments *arguments);
/// The daemon calls this to allow a binary.
/// The daemon calls this to allow a binary.
IOReturn allow_binary(uint64_t vnode_id);
static IOReturn static_allow_binary(
com_google_SantaDriverClient *target,
void *reference,
IOExternalMethodArguments *arguments);
/// The daemon calls this to deny a binary.
/// The daemon calls this to deny a binary.
IOReturn deny_binary(uint64_t vnode_id);
static IOReturn static_deny_binary(
com_google_SantaDriverClient *target,
void *reference,
IOExternalMethodArguments *arguments);
/// The daemon calls this to empty the cache.
/// The daemon calls this to empty the cache.
IOReturn clear_cache();
static IOReturn static_clear_cache(
com_google_SantaDriverClient *target,
void *reference,
IOExternalMethodArguments *arguments);
/// The daemon calls this to find out how many items are in the cache
/// The daemon calls this to find out how many items are in the cache
IOReturn cache_count(uint64_t *output);
static IOReturn static_cache_count(
com_google_SantaDriverClient *target,

View File

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

View File

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

View File

@@ -78,6 +78,7 @@ REGISTER_COMMAND_NAME(@"sync");
if (santactlVersion) {
authURLSession.userAgent = [authURLSession.userAgent stringByAppendingString:santactlVersion];
}
authURLSession.refusesRedirects = YES;
// Configure server auth
if ([config syncServerAuthRootsFile]) {

View File

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

View File

@@ -1,3 +1,17 @@
/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// This is a simple ASN.1 decoder that utilizes Apple's SecAsn1Decode
/// to parse the @c distinguishedNames property of NSURLProtectionSpace.

View File

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

View File

@@ -138,6 +138,7 @@
[self.execController validateBinaryWithPath:@(message.path)
userName:userName
pid:@(message.pid)
ppid:@(message.ppid)
vnodeId:message.vnode_id];
});
break;

View File

@@ -48,7 +48,7 @@
if (!serviceObject) {
LOGD(@"Waiting for Santa driver to become available");
sleep(10);
sleep(5);
}
} while (!serviceObject);
CFRelease(classToMatch);

View File

@@ -53,11 +53,13 @@
/// @param path the binary that's being executed
/// @param userName the user who's executing the binary
/// @param pid the process id being executed
/// @param ppid the parent process id
/// @param vnoteId the id of the vnode being executed
///
- (void)validateBinaryWithPath:(NSString *)path
userName:(NSString *)userName
pid:(NSNumber *)pid
ppid:(NSNumber *)ppid
vnodeId:(uint64_t)vnodeId;

View File

@@ -61,6 +61,7 @@
- (void)validateBinaryWithPath:(NSString *)path
userName:(NSString *)userName
pid:(NSNumber *)pid
ppid:(NSNumber *)ppid
vnodeId:(uint64_t)vnodeId {
SNTFileInfo *binInfo = [[SNTFileInfo alloc] initWithPath:path];
NSString *sha256 = [binInfo SHA256];
@@ -121,6 +122,7 @@
se.occurrenceDate = [[NSDate alloc] init];
se.decision = [self eventStateForDecision:respondedAction type:rule.type];
se.pid = pid;
se.ppid = ppid;
NSArray *loggedInUsers, *currentSessions;
[self loggedInUsers:&loggedInUsers sessions:&currentSessions];

View File

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

View File

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

View File

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

View File

@@ -80,6 +80,7 @@
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
@@ -101,6 +102,7 @@
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_DENY
@@ -125,6 +127,7 @@
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
@@ -149,6 +152,7 @@
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_DENY
@@ -160,7 +164,11 @@
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(YES);
[self.sut setOperatingMode:CLIENTMODE_MONITOR];
[self.sut validateBinaryWithPath:@"/a/file" userName:@"nobody" pid:@(12) vnodeId:1234];
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
forVnodeID:1234]);
@@ -168,6 +176,7 @@
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(12)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_DENY
forVnodeID:1234]);
@@ -178,7 +187,11 @@
OCMStub([mockSut fileIsInScope:OCMOCK_ANY]).andReturn(NO);
[self.sut setOperatingMode:CLIENTMODE_LOCKDOWN];
[self.sut validateBinaryWithPath:@"/a/file" userName:@"nobody" pid:@(24) vnodeId:1234];
[self.sut validateBinaryWithPath:@"/a/file"
userName:@"nobody"
pid:@(24)
ppid:@(1)
vnodeId:1234];
OCMVerify([self.mockDriverManager postToKernelAction:ACTION_RESPOND_CHECKBW_ALLOW
forVnodeID:1234]);
}