2020
2121#import " Source/common/MOLXPCConnection.h"
2222#import " Source/common/SNTFileAccessRule.h"
23+ #import " Source/common/SNTNetworkFlowRule.h"
2324#import " Source/common/SNTRule.h"
2425#import " Source/common/SNTSyncConstants.h"
2526#import " Source/common/SNTXPCControlInterface.h"
3233#import " Source/santasyncservice/SNTSyncLogging.h"
3334#import " Source/santasyncservice/SNTSyncState.h"
3435#include " google/protobuf/arena.h"
36+ #import " src/santanetd/SNDNetworkFlowRuleValidator.h"
3537#include " syncv2/v2.pb.h"
3638
3739namespace pbv2 = ::santa::sync::v2;
@@ -56,20 +58,24 @@ void ProcessDeprecatedBundleNotificationsForRule(
5658NSDictionary * OptionsFromProtoFAARuleAdd (const ::pbv2::FileAccessRule::Add& pbAddRule);
5759NSArray * ProcessesFromProtoFAARuleProcesses (
5860 const google::protobuf::RepeatedPtrField<::pbv2::FileAccessRule::Process>& pbProcesses);
61+ SNTNetworkFlowRule* NetworkFlowRuleFromProto (const ::pbv2::NetworkFlowRule& nr);
5962
6063// Small local object to more easily return the different sets of downloaded rules.
6164@interface SNTDownloadedRuleSets : NSObject
6265@property (readonly ) NSArray <SNTRule*>* executionRules;
6366@property (readonly ) NSArray <SNTFileAccessRule*>* fileAccessRules;
67+ @property (readonly ) NSArray <SNTNetworkFlowRule*>* networkRules;
6468@end
6569
6670@implementation SNTDownloadedRuleSets
6771- (instancetype )initWithExecutionRules : (NSArray <SNTRule*>*)executionRules
68- fileAccessRules : (NSArray <SNTFileAccessRule*>*)fileAccessRules {
72+ fileAccessRules : (NSArray <SNTFileAccessRule*>*)fileAccessRules
73+ networkRules : (NSArray <SNTNetworkFlowRule*>*)networkRules {
6974 self = [super init ];
7075 if (self) {
7176 _executionRules = executionRules;
7277 _fileAccessRules = fileAccessRules;
78+ _networkRules = networkRules;
7379 }
7480 return self;
7581}
@@ -94,8 +100,10 @@ SNTRuleCleanup SyncTypeToRuleCleanup(SNTSyncType syncType) {
94100
95101 self.syncState .rulesReceived = 0 ;
96102 self.syncState .fileAccessRulesReceived = 0 ;
103+ self.syncState .networkFlowRulesReceived = 0 ;
97104 NSMutableArray <SNTRule*>* newRules = [NSMutableArray array ];
98105 NSMutableArray <SNTFileAccessRule*>* newFileAccessRules = [NSMutableArray array ];
106+ NSMutableArray <SNTNetworkFlowRule*>* newNetworkRules = [NSMutableArray array ];
99107 std::string cursor;
100108
101109 do {
@@ -135,22 +143,34 @@ SNTRuleCleanup SyncTypeToRuleCleanup(SNTSyncType syncType) {
135143 }
136144 [newFileAccessRules addObject: rule];
137145 }
146+
147+ for (const ::pbv2::NetworkFlowRule& networkRule : response.network_flow_rules ()) {
148+ SNTNetworkFlowRule* rule = NetworkFlowRuleFromProto (networkRule);
149+ if (!rule) {
150+ SLOGD (@" Ignoring bad network flow rule: %s " , networkRule.Utf8DebugString ().c_str ());
151+ continue ;
152+ }
153+ [newNetworkRules addObject: rule];
154+ }
138155 }
139156
140157 cursor = response.cursor ();
141158 SLOGI (@" Received %lu rules" , (unsigned long )response.rules_size ());
142159 self.syncState .rulesReceived += response.rules_size ();
143160 if constexpr (IsV2) {
144161 self.syncState .fileAccessRulesReceived += response.file_access_rules_size ();
162+ self.syncState .networkFlowRulesReceived += response.network_flow_rules_size ();
145163 }
146164 }
147165 } while (!cursor.empty ());
148166
149167 self.syncState .rulesProcessed = newRules.count ;
150168 self.syncState .fileAccessRulesProcessed = newFileAccessRules.count ;
169+ self.syncState .networkFlowRulesProcessed = newNetworkRules.count ;
151170
152171 return [[SNTDownloadedRuleSets alloc ] initWithExecutionRules: newRules
153- fileAccessRules: newFileAccessRules];
172+ fileAccessRules: newFileAccessRules
173+ networkRules: newNetworkRules];
154174}
155175
156176NSArray * PathsFromProtoFAARulePaths (
@@ -299,6 +319,27 @@ SNTRuleCleanup SyncTypeToRuleCleanup(SNTSyncType syncType) {
299319 }
300320}
301321
322+ SNTNetworkFlowRule* NetworkFlowRuleFromProto (const ::pbv2::NetworkFlowRule& nr) {
323+ switch (nr.action_case ()) {
324+ case ::pbv2::NetworkFlowRule::kAdd : {
325+ std::string serialized;
326+ nr.add ().SerializeToString (&serialized);
327+ NSData * blob = [NSData dataWithBytes: serialized.data () length: serialized.size ()];
328+
329+ NSError * err;
330+ if (!SNDValidateNetworkFlowRule (blob, &err)) {
331+ SLOGW (@" Dropping invalid network flow rule %lld : %@ " , (long long )nr.add ().rule_id (),
332+ err.localizedDescription ?: @" validation failed" );
333+ return nil ;
334+ }
335+ return [[SNTNetworkFlowRule alloc ] initAddRuleWithId: nr.add ().rule_id () protoBlob: blob];
336+ }
337+ case ::pbv2::NetworkFlowRule::kRemove :
338+ return [[SNTNetworkFlowRule alloc ] initRemoveRuleWithId: nr.remove ().rule_id ()];
339+ default : return nil ;
340+ }
341+ }
342+
302343template <bool IsV2>
303344SNTRule* RuleFromProtoRule (const typename santa::ProtoTraits<IsV2>::RuleT& rule) {
304345 using Traits = santa::ProtoTraits<IsV2>;
@@ -435,7 +476,8 @@ - (BOOL)sync {
435476 return NO ;
436477 }
437478 // If the request was successfully completed, but no new rules received, just return
438- if (!newRules.executionRules .count && !newRules.fileAccessRules .count ) {
479+ if (!newRules.executionRules .count && !newRules.fileAccessRules .count &&
480+ !newRules.networkRules .count ) {
439481 return YES ;
440482 }
441483
@@ -447,7 +489,7 @@ - (BOOL)sync {
447489 [[self .daemonConn remoteObjectProxy ]
448490 databaseRuleAddExecutionRules: newRules.executionRules
449491 fileAccessRules: newRules.fileAccessRules
450- networkFlowRules: nil
492+ networkFlowRules: newRules.networkRules
451493 ruleCleanup: SyncTypeToRuleCleanup (self .syncState.syncType)
452494 source: SNTRuleAddSourceSyncService
453495 reply: ^(BOOL didSucceed, NSArray <NSError *>* e) {
@@ -489,6 +531,10 @@ - (BOOL)sync {
489531 SLOGI (@" Processed %lu file access rules" , newRules.fileAccessRules .count );
490532 }
491533
534+ if (newRules.networkRules .count ) {
535+ SLOGI (@" Processed %lu network flow rules" , newRules.networkRules .count );
536+ }
537+
492538 // Send out push notifications about any newly allowed binaries
493539 // that had been previously blocked by santad.
494540 [self announceUnblockingRules: newRules.executionRules];
0 commit comments