Skip to content

Commit

Permalink
Merge branch 'main' into santactl-rule-types
Browse files Browse the repository at this point in the history
  • Loading branch information
russellhancox authored May 21, 2024
2 parents bbf19d5 + d8928ac commit 5ff438d
Show file tree
Hide file tree
Showing 15 changed files with 302 additions and 56 deletions.
5 changes: 4 additions & 1 deletion Source/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -478,13 +478,16 @@ santa_unit_test(
name = "SNTBlockMessageTest",
srcs = ["SNTBlockMessageTest.m"],
deps = [
":SNTBlockMessage",
":SNTBlockMessage_SantaGUI",
":SNTConfigurator",
":SNTFileAccessEvent",
":SNTStoredEvent",
":SNTSystemInfo",
"@OCMock",
],
sdk_frameworks = [
"AppKit",
],
)

santa_unit_test(
Expand Down
6 changes: 5 additions & 1 deletion Source/common/SNTBlockMessage.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ + (NSAttributedString *)formatMessage:(NSString *)message {

#ifdef SANTAGUI
NSData *htmlData = [fullHTML dataUsingEncoding:NSUTF8StringEncoding];
return [[NSAttributedString alloc] initWithHTML:htmlData documentAttributes:NULL];
NSDictionary *options = @{
NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute : @(NSUTF8StringEncoding),
};
return [[NSAttributedString alloc] initWithHTML:htmlData options:options documentAttributes:NULL];
#else
NSString *strippedHTML = [self stringFromHTML:fullHTML];
if (!strippedHTML) {
Expand Down
6 changes: 6 additions & 0 deletions Source/common/SNTBlockMessageTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ - (void)setUp {
OCMStub([self.mockSystemInfo serialNumber]).andReturn(@"my_s");
}

- (void)testFormatMessage {
NSString *input = @"Testing with somé Ünicode çharacters";
NSAttributedString *got = [SNTBlockMessage formatMessage:input];
XCTAssertEqualObjects([got string], input);
}

- (void)testEventDetailURLForEvent {
SNTStoredEvent *se = [[SNTStoredEvent alloc] init];

Expand Down
14 changes: 14 additions & 0 deletions Source/common/SNTCommonEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ typedef NS_ENUM(NSInteger, SNTRuleCleanup) {
};

#ifdef __cplusplus

enum class FileAccessPolicyDecision {
kNoPolicy,
kDenied,
Expand All @@ -190,6 +191,19 @@ enum class FileAccessPolicyDecision {
kAllowedReadAccess,
kAllowedAuditOnly,
};

enum class StatChangeStep {
kNoChange = 0,
kMessageCreate,
kCodesignValidation,
};

enum class StatResult {
kOK = 0,
kStatError,
kDevnoInodeMismatch,
};

#endif

static const char *kSantaDPath =
Expand Down
9 changes: 9 additions & 0 deletions Source/santabundleservice/SNTBundleService.m
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,15 @@ - (NSDictionary *)generateEventsFromBinaries:(NSArray *)fis

MOLCodesignChecker *cs = [fi codesignCheckerWithError:NULL];
se.signingChain = cs.certificates;
se.cdhash = cs.cdhash;
se.teamID = cs.teamID;
if (cs.signingID) {
if (cs.teamID) {
se.signingID = [NSString stringWithFormat:@"%@:%@", cs.teamID, cs.signingID];
} else if (cs.platformBinary) {
se.signingID = [NSString stringWithFormat:@"platform:%@", cs.signingID];
}
}

dispatch_sync(dispatch_get_main_queue(), ^{
relatedEvents[se.fileSHA256] = se;
Expand Down
5 changes: 5 additions & 0 deletions Source/santad/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ objc_library(
deps = [
":EndpointSecurityClient",
":WatchItemPolicy",
"//Source/common:SNTCommonEnums",
"//Source/santad/ProcessTree:process_tree",
],
)
Expand Down Expand Up @@ -718,6 +719,7 @@ objc_library(
srcs = ["Metrics.mm"],
hdrs = ["Metrics.h"],
deps = [
":EndpointSecurityMessage",
":SNTApplicationCoreMetrics",
"//Source/common:SNTCommonEnums",
"//Source/common:SNTLogging",
Expand Down Expand Up @@ -1183,7 +1185,10 @@ santa_unit_test(
name = "MetricsTest",
srcs = ["MetricsTest.mm"],
deps = [
":EndpointSecurityMessage",
":Metrics",
":MockEndpointSecurityAPI",
"//Source/common:SNTCommonEnums",
"//Source/common:SNTMetricSet",
"//Source/common:TestUtils",
"@OCMock",
Expand Down
12 changes: 12 additions & 0 deletions Source/santad/EventProviders/EndpointSecurity/Message.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
#include <memory>
#include <string>

#import "Source/common/SNTCommonEnums.h"
#include "Source/santad/ProcessTree/process_tree.h"

namespace santa::santad::event_providers::endpoint_security {

class EndpointSecurityAPI;
class MessagePeer;

class Message {
public:
Expand Down Expand Up @@ -53,12 +55,22 @@ class Message {

std::string ParentProcessName() const;

void UpdateStatState(enum StatChangeStep step) const;

inline StatChangeStep StatChangeStep() const { return stat_change_step_; }
inline StatResult StatResult() const { return stat_result_; }

friend class santa::santad::event_providers::endpoint_security::MessagePeer;

private:
std::shared_ptr<EndpointSecurityAPI> esapi_;
const es_message_t* es_msg_;
std::optional<process_tree::ProcessToken> process_token_;

std::string GetProcessName(pid_t pid) const;

mutable enum StatChangeStep stat_change_step_ = StatChangeStep::kNoChange;
mutable enum StatResult stat_result_ = StatResult::kOK;
};

} // namespace santa::santad::event_providers::endpoint_security
Expand Down
25 changes: 25 additions & 0 deletions Source/santad/EventProviders/EndpointSecurity/Message.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <bsm/libbsm.h>
#include <libproc.h>
#include <sys/stat.h>

#include "Source/santad/EventProviders/EndpointSecurity/EndpointSecurityAPI.h"

Expand All @@ -24,6 +25,7 @@
Message::Message(std::shared_ptr<EndpointSecurityAPI> esapi, const es_message_t *es_msg)
: esapi_(std::move(esapi)), es_msg_(es_msg), process_token_(std::nullopt) {
esapi_->RetainMessage(es_msg);
UpdateStatState(StatChangeStep::kMessageCreate);
}

Message::~Message() {
Expand All @@ -38,13 +40,36 @@
other.es_msg_ = nullptr;
process_token_ = std::move(other.process_token_);
other.process_token_ = std::nullopt;
stat_change_step_ = other.stat_change_step_;
stat_result_ = other.stat_result_;
}

Message::Message(const Message &other) {
esapi_ = other.esapi_;
es_msg_ = other.es_msg_;
esapi_->RetainMessage(es_msg_);
process_token_ = other.process_token_;
stat_change_step_ = other.stat_change_step_;
stat_result_ = other.stat_result_;
}

void Message::UpdateStatState(enum StatChangeStep step) const {
// Only update state for AUTH EXEC events and if no previous change was detected
if (es_msg_->event_type == ES_EVENT_TYPE_AUTH_EXEC &&
stat_change_step_ == StatChangeStep::kNoChange &&
// Note: The following checks are required due to tests that only
// partially construct an es_message_t.
es_msg_->event.exec.target && es_msg_->event.exec.target->executable) {
struct stat &es_sb = es_msg_->event.exec.target->executable->stat;
struct stat sb;
int ret = stat(es_msg_->event.exec.target->executable->path.data, &sb);
// If stat failed, or if devno/inode changed, update state.
if (ret != 0 || es_sb.st_ino != sb.st_ino || es_sb.st_dev != sb.st_dev) {
stat_change_step_ = step;
// Determine the specific condition that failed for tracking purposes
stat_result_ = (ret != 0) ? StatResult::kStatError : StatResult::kDevnoInodeMismatch;
}
}
}

void Message::SetProcessToken(process_tree::ProcessToken tok) {
Expand Down
14 changes: 6 additions & 8 deletions Source/santad/EventProviders/SNTEndpointSecurityClient.mm
Original file line number Diff line number Diff line change
Expand Up @@ -146,26 +146,24 @@ - (void)establishClientOrDie {
// sequence numbers are processed in order.
self->_metrics->UpdateEventStats(self->_processor, esMsg.operator->());

es_event_type_t eventType = esMsg->event_type;

if ([self handleContextMessage:esMsg]) {
int64_t processingEnd = clock_gettime_nsec_np(CLOCK_MONOTONIC);
self->_metrics->SetEventMetrics(self->_processor, eventType, EventDisposition::kProcessed,
processingEnd - processingStart);
self->_metrics->SetEventMetrics(self->_processor, EventDisposition::kProcessed,
processingEnd - processingStart, esMsg);
return;
}

if ([self shouldHandleMessage:esMsg]) {
[self handleMessage:std::move(esMsg)
recordEventMetrics:^(EventDisposition disposition) {
int64_t processingEnd = clock_gettime_nsec_np(CLOCK_MONOTONIC);
self->_metrics->SetEventMetrics(self->_processor, eventType, disposition,
processingEnd - processingStart);
self->_metrics->SetEventMetrics(self->_processor, disposition,
processingEnd - processingStart, esMsg);
}];
} else {
int64_t processingEnd = clock_gettime_nsec_np(CLOCK_MONOTONIC);
self->_metrics->SetEventMetrics(self->_processor, eventType, EventDisposition::kDropped,
processingEnd - processingStart);
self->_metrics->SetEventMetrics(self->_processor, EventDisposition::kDropped,
processingEnd - processingStart, esMsg);
}
});

Expand Down
12 changes: 8 additions & 4 deletions Source/santad/Metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#import "Source/common/SNTCommonEnums.h"
#import "Source/common/SNTMetricSet.h"
#include "Source/santad/EventProviders/EndpointSecurity/Message.h"

namespace santa::santad {

Expand Down Expand Up @@ -54,6 +55,7 @@ enum class FileAccessMetricStatus {
using EventCountTuple = std::tuple<Processor, es_event_type_t, EventDisposition>;
using EventTimesTuple = std::tuple<Processor, es_event_type_t>;
using EventStatsTuple = std::tuple<Processor, es_event_type_t>;
using EventStatChangeTuple = std::tuple<StatChangeStep, StatResult>;
using FileAccessMetricsPolicyVersion = std::string;
using FileAccessMetricsPolicyName = std::string;
using FileAccessEventCountTuple =
Expand All @@ -67,8 +69,8 @@ class Metrics : public std::enable_shared_from_this<Metrics> {
Metrics(dispatch_queue_t q, dispatch_source_t timer_source, uint64_t interval,
SNTMetricInt64Gauge *event_processing_times, SNTMetricCounter *event_counts,
SNTMetricCounter *rate_limit_counts, SNTMetricCounter *drop_counts,
SNTMetricCounter *faa_event_counts, SNTMetricSet *metric_set,
void (^run_on_first_start)(Metrics *));
SNTMetricCounter *faa_event_counts, SNTMetricCounter *stat_change_counts,
SNTMetricSet *metric_set, void (^run_on_first_start)(Metrics *));

~Metrics();

Expand All @@ -83,8 +85,8 @@ class Metrics : public std::enable_shared_from_this<Metrics> {
// Used for tracking event sequence numbers to determine if drops occured
void UpdateEventStats(Processor processor, const es_message_t *msg);

void SetEventMetrics(Processor processor, es_event_type_t event_type,
EventDisposition disposition, int64_t nanos);
void SetEventMetrics(Processor processor, EventDisposition event_disposition, int64_t nanos,
const santa::santad::event_providers::endpoint_security::Message &msg);

void SetRateLimitingMetrics(Processor processor, int64_t events_rate_limited_count);

Expand Down Expand Up @@ -112,6 +114,7 @@ class Metrics : public std::enable_shared_from_this<Metrics> {
SNTMetricCounter *rate_limit_counts_;
SNTMetricCounter *faa_event_counts_;
SNTMetricCounter *drop_counts_;
SNTMetricCounter *stat_change_counts_;
SNTMetricSet *metric_set_;
// Tracks whether or not the timer_source should be running.
// This helps manage dispatch source state to ensure the source is not
Expand All @@ -129,6 +132,7 @@ class Metrics : public std::enable_shared_from_this<Metrics> {
std::map<Processor, int64_t> rate_limit_counts_cache_;
std::map<FileAccessEventCountTuple, int64_t> faa_event_counts_cache_;
std::map<EventStatsTuple, SequenceStats> drop_cache_;
std::map<EventStatChangeTuple, int64_t> stat_change_cache_;
};

} // namespace santa::santad
Expand Down
Loading

0 comments on commit 5ff438d

Please sign in to comment.