diff --git a/Source/common/santa.proto b/Source/common/santa.proto index eaa9d2d2..dc2c15d3 100644 --- a/Source/common/santa.proto +++ b/Source/common/santa.proto @@ -488,6 +488,8 @@ message FileAccess { ACCESS_TYPE_CLONE = 5; ACCESS_TYPE_EXCHANGEDATA = 6; ACCESS_TYPE_COPYFILE = 7; + ACCESS_TYPE_CREATE = 8; + ACCESS_TYPE_TRUNCATE = 9; } optional AccessType access_type = 5; diff --git a/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizer.mm b/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizer.mm index c967acfe..dfb9786a 100644 --- a/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizer.mm +++ b/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizer.mm @@ -118,13 +118,46 @@ es_auth_result_t CombinePolicyResults(es_auth_result_t result1, es_auth_result_t void PopulatePathTargets(const Message &msg, std::vector &targets) { switch (msg->event_type) { - case ES_EVENT_TYPE_AUTH_OPEN: - PushBackIfNotTruncated(targets, msg->event.open.file, true); + case ES_EVENT_TYPE_AUTH_CLONE: + PushBackIfNotTruncated(targets, msg->event.clone.source, true); + PushBackIfNotTruncated(targets, msg->event.clone.target_dir, msg->event.clone.target_name); break; + + case ES_EVENT_TYPE_AUTH_CREATE: + // AUTH CREATE events should always be ES_DESTINATION_TYPE_NEW_PATH + if (msg->event.create.destination_type == ES_DESTINATION_TYPE_NEW_PATH) { + PushBackIfNotTruncated(targets, msg->event.create.destination.new_path.dir, + msg->event.create.destination.new_path.filename); + } else { + LOGW(@"Unexpected destination type for create event: %d. Ignoring target.", + msg->event.create.destination_type); + } + break; + + case ES_EVENT_TYPE_AUTH_COPYFILE: + PushBackIfNotTruncated(targets, msg->event.copyfile.source, true); + if (msg->event.copyfile.target_file) { + PushBackIfNotTruncated(targets, msg->event.copyfile.target_file); + } else { + PushBackIfNotTruncated(targets, msg->event.copyfile.target_dir, + msg->event.copyfile.target_name); + } + break; + + case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: + PushBackIfNotTruncated(targets, msg->event.exchangedata.file1); + PushBackIfNotTruncated(targets, msg->event.exchangedata.file2); + break; + case ES_EVENT_TYPE_AUTH_LINK: PushBackIfNotTruncated(targets, msg->event.link.source); PushBackIfNotTruncated(targets, msg->event.link.target_dir, msg->event.link.target_filename); break; + + case ES_EVENT_TYPE_AUTH_OPEN: + PushBackIfNotTruncated(targets, msg->event.open.file, true); + break; + case ES_EVENT_TYPE_AUTH_RENAME: PushBackIfNotTruncated(targets, msg->event.rename.source); if (msg->event.rename.destination_type == ES_DESTINATION_TYPE_EXISTING_FILE) { @@ -137,26 +170,15 @@ void PopulatePathTargets(const Message &msg, std::vector &targets) { msg->event.rename.destination_type); } break; + + case ES_EVENT_TYPE_AUTH_TRUNCATE: + PushBackIfNotTruncated(targets, msg->event.truncate.target); + break; + case ES_EVENT_TYPE_AUTH_UNLINK: PushBackIfNotTruncated(targets, msg->event.unlink.target); break; - case ES_EVENT_TYPE_AUTH_CLONE: - PushBackIfNotTruncated(targets, msg->event.clone.source, true); - PushBackIfNotTruncated(targets, msg->event.clone.target_dir, msg->event.clone.target_name); - break; - case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: - PushBackIfNotTruncated(targets, msg->event.exchangedata.file1); - PushBackIfNotTruncated(targets, msg->event.exchangedata.file2); - break; - case ES_EVENT_TYPE_AUTH_COPYFILE: - PushBackIfNotTruncated(targets, msg->event.copyfile.source, true); - if (msg->event.copyfile.target_file) { - PushBackIfNotTruncated(targets, msg->event.copyfile.target_file); - } else { - PushBackIfNotTruncated(targets, msg->event.copyfile.target_dir, - msg->event.copyfile.target_name); - } - break; + default: [NSException raise:@"Unexpected event type" @@ -269,9 +291,11 @@ void PopulatePathTargets(const Message &msg, std::vector &targets) { } break; + case ES_EVENT_TYPE_AUTH_CREATE: case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: - case ES_EVENT_TYPE_AUTH_RENAME: case ES_EVENT_TYPE_AUTH_LINK: + case ES_EVENT_TYPE_AUTH_RENAME: + case ES_EVENT_TYPE_AUTH_TRUNCATE: case ES_EVENT_TYPE_AUTH_UNLINK: // These event types have no special case break; @@ -451,8 +475,9 @@ void PopulatePathTargets(const Message &msg, std::vector &targets) { - (void)enable { // TODO(xyz): Expand to support ES_EVENT_TYPE_AUTH_CREATE, ES_EVENT_TYPE_AUTH_TRUNCATE std::set events = { - ES_EVENT_TYPE_AUTH_CLONE, ES_EVENT_TYPE_AUTH_EXCHANGEDATA, ES_EVENT_TYPE_AUTH_LINK, - ES_EVENT_TYPE_AUTH_OPEN, ES_EVENT_TYPE_AUTH_RENAME, ES_EVENT_TYPE_AUTH_UNLINK, + ES_EVENT_TYPE_AUTH_CLONE, ES_EVENT_TYPE_AUTH_CREATE, ES_EVENT_TYPE_AUTH_EXCHANGEDATA, + ES_EVENT_TYPE_AUTH_LINK, ES_EVENT_TYPE_AUTH_OPEN, ES_EVENT_TYPE_AUTH_RENAME, + ES_EVENT_TYPE_AUTH_TRUNCATE, ES_EVENT_TYPE_AUTH_UNLINK, }; #if HAVE_MACOS_12 diff --git a/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizerTest.mm b/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizerTest.mm index 4ca2fe21..fa9245df 100644 --- a/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizerTest.mm +++ b/Source/santad/EventProviders/SNTEndpointSecurityFileAccessAuthorizerTest.mm @@ -342,10 +342,8 @@ void SetExpectationsForFileAccessAuthorizerInit( // Ensure other handled event types do not have a special case std::set eventTypes = { - ES_EVENT_TYPE_AUTH_LINK, - ES_EVENT_TYPE_AUTH_RENAME, - ES_EVENT_TYPE_AUTH_UNLINK, - ES_EVENT_TYPE_AUTH_EXCHANGEDATA, + ES_EVENT_TYPE_AUTH_CREATE, ES_EVENT_TYPE_AUTH_EXCHANGEDATA, ES_EVENT_TYPE_AUTH_LINK, + ES_EVENT_TYPE_AUTH_RENAME, ES_EVENT_TYPE_AUTH_TRUNCATE, ES_EVENT_TYPE_AUTH_UNLINK, }; for (const auto &event : eventTypes) { @@ -493,8 +491,9 @@ void SetExpectationsForFileAccessAuthorizerInit( - (void)testEnable { std::set expectedEventSubs = { - ES_EVENT_TYPE_AUTH_CLONE, ES_EVENT_TYPE_AUTH_EXCHANGEDATA, ES_EVENT_TYPE_AUTH_LINK, - ES_EVENT_TYPE_AUTH_OPEN, ES_EVENT_TYPE_AUTH_RENAME, ES_EVENT_TYPE_AUTH_UNLINK, + ES_EVENT_TYPE_AUTH_CLONE, ES_EVENT_TYPE_AUTH_CREATE, ES_EVENT_TYPE_AUTH_EXCHANGEDATA, + ES_EVENT_TYPE_AUTH_LINK, ES_EVENT_TYPE_AUTH_OPEN, ES_EVENT_TYPE_AUTH_RENAME, + ES_EVENT_TYPE_AUTH_TRUNCATE, ES_EVENT_TYPE_AUTH_UNLINK, }; #if HAVE_MACOS_12 @@ -663,6 +662,32 @@ void SetExpectationsForFileAccessAuthorizerInit( XCTAssertFalse(targets[1].isReadable); } + { + esMsg.event_type = ES_EVENT_TYPE_AUTH_CREATE; + esMsg.event.create.destination_type = ES_DESTINATION_TYPE_NEW_PATH; + esMsg.event.create.destination.new_path.dir = &testDir; + esMsg.event.create.destination.new_path.filename = testTok; + + std::vector targets; + PopulatePathTargets(msg, targets); + + XCTAssertEqual(targets.size(), 1); + XCTAssertCppStringEqual(targets[0].path, dirTok); + XCTAssertFalse(targets[0].isReadable); + } + + { + esMsg.event_type = ES_EVENT_TYPE_AUTH_TRUNCATE; + esMsg.event.truncate.target = &testFile1; + + std::vector targets; + PopulatePathTargets(msg, targets); + + XCTAssertEqual(targets.size(), 1); + XCTAssertCStringEqual(targets[0].path.c_str(), testFile1.path.data); + XCTAssertFalse(targets[0].isReadable); + } + if (@available(macOS 12.0, *)) { { esMsg.event_type = ES_EVENT_TYPE_AUTH_COPYFILE; diff --git a/Source/santad/Logs/EndpointSecurity/Serializers/BasicString.mm b/Source/santad/Logs/EndpointSecurity/Serializers/BasicString.mm index 26bd4b00..046b8af7 100644 --- a/Source/santad/Logs/EndpointSecurity/Serializers/BasicString.mm +++ b/Source/santad/Logs/EndpointSecurity/Serializers/BasicString.mm @@ -113,13 +113,15 @@ std::string GetModeString(SNTClientMode mode) { std::string GetAccessTypeString(es_event_type_t event_type) { switch (event_type) { - case ES_EVENT_TYPE_AUTH_OPEN: return "OPEN"; - case ES_EVENT_TYPE_AUTH_LINK: return "LINK"; - case ES_EVENT_TYPE_AUTH_RENAME: return "RENAME"; - case ES_EVENT_TYPE_AUTH_UNLINK: return "UNLINK"; case ES_EVENT_TYPE_AUTH_CLONE: return "CLONE"; - case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: return "EXCHANGEDATA"; case ES_EVENT_TYPE_AUTH_COPYFILE: return "COPYFILE"; + case ES_EVENT_TYPE_AUTH_CREATE: return "CREATE"; + case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: return "EXCHANGEDATA"; + case ES_EVENT_TYPE_AUTH_LINK: return "LINK"; + case ES_EVENT_TYPE_AUTH_OPEN: return "OPEN"; + case ES_EVENT_TYPE_AUTH_RENAME: return "RENAME"; + case ES_EVENT_TYPE_AUTH_TRUNCATE: return "TRUNCATE"; + case ES_EVENT_TYPE_AUTH_UNLINK: return "UNLINK"; default: return "UNKNOWN_TYPE_" + std::to_string(event_type); } } diff --git a/Source/santad/Logs/EndpointSecurity/Serializers/BasicStringTest.mm b/Source/santad/Logs/EndpointSecurity/Serializers/BasicStringTest.mm index 854b0226..7a0b101a 100644 --- a/Source/santad/Logs/EndpointSecurity/Serializers/BasicStringTest.mm +++ b/Source/santad/Logs/EndpointSecurity/Serializers/BasicStringTest.mm @@ -255,6 +255,7 @@ std::string BasicStringSerializeMessage(es_message_t *esMsg) { {ES_EVENT_TYPE_AUTH_OPEN, "OPEN"}, {ES_EVENT_TYPE_AUTH_LINK, "LINK"}, {ES_EVENT_TYPE_AUTH_RENAME, "RENAME"}, {ES_EVENT_TYPE_AUTH_UNLINK, "UNLINK"}, {ES_EVENT_TYPE_AUTH_CLONE, "CLONE"}, {ES_EVENT_TYPE_AUTH_EXCHANGEDATA, "EXCHANGEDATA"}, + {ES_EVENT_TYPE_AUTH_CREATE, "CREATE"}, {ES_EVENT_TYPE_AUTH_TRUNCATE, "TRUNCATE"}, {ES_EVENT_TYPE_AUTH_COPYFILE, "COPYFILE"}, {(es_event_type_t)1234, "UNKNOWN_TYPE_1234"}, }; diff --git a/Source/santad/Logs/EndpointSecurity/Serializers/Protobuf.mm b/Source/santad/Logs/EndpointSecurity/Serializers/Protobuf.mm index a28185d3..b65ec3da 100644 --- a/Source/santad/Logs/EndpointSecurity/Serializers/Protobuf.mm +++ b/Source/santad/Logs/EndpointSecurity/Serializers/Protobuf.mm @@ -327,13 +327,15 @@ static inline void EncodeCertificateInfo(::pbv1::CertificateInfo *pb_cert_info, ::pbv1::FileAccess::AccessType GetAccessType(es_event_type_t event_type) { switch (event_type) { - case ES_EVENT_TYPE_AUTH_OPEN: return ::pbv1::FileAccess::ACCESS_TYPE_OPEN; - case ES_EVENT_TYPE_AUTH_LINK: return ::pbv1::FileAccess::ACCESS_TYPE_LINK; - case ES_EVENT_TYPE_AUTH_RENAME: return ::pbv1::FileAccess::ACCESS_TYPE_RENAME; - case ES_EVENT_TYPE_AUTH_UNLINK: return ::pbv1::FileAccess::ACCESS_TYPE_UNLINK; case ES_EVENT_TYPE_AUTH_CLONE: return ::pbv1::FileAccess::ACCESS_TYPE_CLONE; - case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: return ::pbv1::FileAccess::ACCESS_TYPE_EXCHANGEDATA; + case ES_EVENT_TYPE_AUTH_CREATE: return ::pbv1::FileAccess::ACCESS_TYPE_CREATE; case ES_EVENT_TYPE_AUTH_COPYFILE: return ::pbv1::FileAccess::ACCESS_TYPE_COPYFILE; + case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: return ::pbv1::FileAccess::ACCESS_TYPE_EXCHANGEDATA; + case ES_EVENT_TYPE_AUTH_LINK: return ::pbv1::FileAccess::ACCESS_TYPE_LINK; + case ES_EVENT_TYPE_AUTH_OPEN: return ::pbv1::FileAccess::ACCESS_TYPE_OPEN; + case ES_EVENT_TYPE_AUTH_RENAME: return ::pbv1::FileAccess::ACCESS_TYPE_RENAME; + case ES_EVENT_TYPE_AUTH_TRUNCATE: return ::pbv1::FileAccess::ACCESS_TYPE_TRUNCATE; + case ES_EVENT_TYPE_AUTH_UNLINK: return ::pbv1::FileAccess::ACCESS_TYPE_UNLINK; default: return ::pbv1::FileAccess::ACCESS_TYPE_UNKNOWN; } } diff --git a/Source/santad/Logs/EndpointSecurity/Serializers/ProtobufTest.mm b/Source/santad/Logs/EndpointSecurity/Serializers/ProtobufTest.mm index 6f9b7d3d..5c9b44c6 100644 --- a/Source/santad/Logs/EndpointSecurity/Serializers/ProtobufTest.mm +++ b/Source/santad/Logs/EndpointSecurity/Serializers/ProtobufTest.mm @@ -536,13 +536,15 @@ void SerializeAndCheckNonESEvents( - (void)testGetAccessType { std::map eventTypeToAccessType = { - {ES_EVENT_TYPE_AUTH_OPEN, ::pbv1::FileAccess::ACCESS_TYPE_OPEN}, - {ES_EVENT_TYPE_AUTH_LINK, ::pbv1::FileAccess::ACCESS_TYPE_LINK}, - {ES_EVENT_TYPE_AUTH_RENAME, ::pbv1::FileAccess::ACCESS_TYPE_RENAME}, - {ES_EVENT_TYPE_AUTH_UNLINK, ::pbv1::FileAccess::ACCESS_TYPE_UNLINK}, {ES_EVENT_TYPE_AUTH_CLONE, ::pbv1::FileAccess::ACCESS_TYPE_CLONE}, - {ES_EVENT_TYPE_AUTH_EXCHANGEDATA, ::pbv1::FileAccess::ACCESS_TYPE_EXCHANGEDATA}, {ES_EVENT_TYPE_AUTH_COPYFILE, ::pbv1::FileAccess::ACCESS_TYPE_COPYFILE}, + {ES_EVENT_TYPE_AUTH_CREATE, ::pbv1::FileAccess::ACCESS_TYPE_CREATE}, + {ES_EVENT_TYPE_AUTH_EXCHANGEDATA, ::pbv1::FileAccess::ACCESS_TYPE_EXCHANGEDATA}, + {ES_EVENT_TYPE_AUTH_LINK, ::pbv1::FileAccess::ACCESS_TYPE_LINK}, + {ES_EVENT_TYPE_AUTH_OPEN, ::pbv1::FileAccess::ACCESS_TYPE_OPEN}, + {ES_EVENT_TYPE_AUTH_RENAME, ::pbv1::FileAccess::ACCESS_TYPE_RENAME}, + {ES_EVENT_TYPE_AUTH_TRUNCATE, ::pbv1::FileAccess::ACCESS_TYPE_TRUNCATE}, + {ES_EVENT_TYPE_AUTH_UNLINK, ::pbv1::FileAccess::ACCESS_TYPE_UNLINK}, {(es_event_type_t)1234, ::pbv1::FileAccess::ACCESS_TYPE_UNKNOWN}, }; diff --git a/Source/santad/Metrics.mm b/Source/santad/Metrics.mm index e5bef2dd..83704392 100644 --- a/Source/santad/Metrics.mm +++ b/Source/santad/Metrics.mm @@ -29,6 +29,7 @@ static NSString *const kProcessorFileAccessAuthorizer = @"FileAccessAuthorizer"; static NSString *const kEventTypeAuthClone = @"AuthClone"; static NSString *const kEventTypeAuthCopyfile = @"AuthCopyfile"; +static NSString *const kEventTypeAuthCreate = @"AuthCreate"; static NSString *const kEventTypeAuthExchangedata = @"AuthExchangedata"; static NSString *const kEventTypeAuthExec = @"AuthExec"; static NSString *const kEventTypeAuthKextload = @"AuthKextload"; @@ -37,6 +38,7 @@ static NSString *const kEventTypeAuthMount = @"AuthMount"; static NSString *const kEventTypeAuthOpen = @"AuthOpen"; static NSString *const kEventTypeAuthRemount = @"AuthRemount"; static NSString *const kEventTypeAuthRename = @"AuthRename"; +static NSString *const kEventTypeAuthTruncate = @"AuthTruncate"; static NSString *const kEventTypeAuthUnlink = @"AuthUnlink"; static NSString *const kEventTypeNotifyClose = @"NotifyClose"; static NSString *const kEventTypeNotifyExchangedata = @"NotifyExchangedata"; @@ -70,6 +72,7 @@ const NSString *EventTypeToString(es_event_type_t eventType) { switch (eventType) { case ES_EVENT_TYPE_AUTH_CLONE: return kEventTypeAuthClone; case ES_EVENT_TYPE_AUTH_COPYFILE: return kEventTypeAuthCopyfile; + case ES_EVENT_TYPE_AUTH_CREATE: return kEventTypeAuthCreate; case ES_EVENT_TYPE_AUTH_EXCHANGEDATA: return kEventTypeAuthExchangedata; case ES_EVENT_TYPE_AUTH_EXEC: return kEventTypeAuthExec; case ES_EVENT_TYPE_AUTH_KEXTLOAD: return kEventTypeAuthKextload; @@ -78,6 +81,7 @@ const NSString *EventTypeToString(es_event_type_t eventType) { case ES_EVENT_TYPE_AUTH_OPEN: return kEventTypeAuthOpen; case ES_EVENT_TYPE_AUTH_REMOUNT: return kEventTypeAuthRemount; case ES_EVENT_TYPE_AUTH_RENAME: return kEventTypeAuthRename; + case ES_EVENT_TYPE_AUTH_TRUNCATE: return kEventTypeAuthTruncate; case ES_EVENT_TYPE_AUTH_UNLINK: return kEventTypeAuthUnlink; case ES_EVENT_TYPE_NOTIFY_CLOSE: return kEventTypeNotifyClose; case ES_EVENT_TYPE_NOTIFY_EXCHANGEDATA: return kEventTypeNotifyExchangedata; diff --git a/Source/santad/MetricsTest.mm b/Source/santad/MetricsTest.mm index c7976a9a..81baae69 100644 --- a/Source/santad/MetricsTest.mm +++ b/Source/santad/MetricsTest.mm @@ -129,6 +129,7 @@ using santa::santad::ProcessorToString; std::map eventTypeToString = { {ES_EVENT_TYPE_AUTH_CLONE, @"AuthClone"}, {ES_EVENT_TYPE_AUTH_COPYFILE, @"AuthCopyfile"}, + {ES_EVENT_TYPE_AUTH_CREATE, @"AuthCreate"}, {ES_EVENT_TYPE_AUTH_EXCHANGEDATA, @"AuthExchangedata"}, {ES_EVENT_TYPE_AUTH_EXEC, @"AuthExec"}, {ES_EVENT_TYPE_AUTH_KEXTLOAD, @"AuthKextload"}, @@ -136,6 +137,7 @@ using santa::santad::ProcessorToString; {ES_EVENT_TYPE_AUTH_MOUNT, @"AuthMount"}, {ES_EVENT_TYPE_AUTH_REMOUNT, @"AuthRemount"}, {ES_EVENT_TYPE_AUTH_RENAME, @"AuthRename"}, + {ES_EVENT_TYPE_AUTH_TRUNCATE, @"AuthTruncate"}, {ES_EVENT_TYPE_AUTH_UNLINK, @"AuthUnlink"}, {ES_EVENT_TYPE_NOTIFY_CLOSE, @"NotifyClose"}, {ES_EVENT_TYPE_NOTIFY_EXCHANGEDATA, @"NotifyExchangedata"},