mirror of
https://github.com/google/santa.git
synced 2026-01-21 03:58:11 -05:00
101 lines
4.0 KiB
Objective-C
101 lines
4.0 KiB
Objective-C
/// Copyright 2017 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/santad/SNTCompilerController.h"
|
|
|
|
#import "Source/common/SNTCachedDecision.h"
|
|
#import "Source/common/SNTCommonEnums.h"
|
|
#import "Source/common/SNTFileInfo.h"
|
|
#import "Source/common/SNTKernelCommon.h"
|
|
#import "Source/common/SNTLogging.h"
|
|
#import "Source/common/SNTRule.h"
|
|
#import "Source/santad/SNTDatabaseController.h"
|
|
#import "Source/santad/DataLayer/SNTRuleTable.h"
|
|
#import "Source/santad/EventProviders/SNTEventProvider.h"
|
|
#import "Source/santad/Logs/SNTEventLog.h"
|
|
|
|
@interface SNTCompilerController ()
|
|
@property id<SNTEventProvider> eventProvider;
|
|
@property SNTEventLog *eventLog;
|
|
@end
|
|
|
|
@implementation SNTCompilerController
|
|
|
|
- (instancetype)initWithEventProvider:(id<SNTEventProvider>)eventProvider
|
|
eventLog:(SNTEventLog *)eventLog {
|
|
self = [super init];
|
|
if (self) {
|
|
_eventProvider = eventProvider;
|
|
_eventLog = eventLog;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
// Adds a fake cached decision to SNTEventLog for pending files. If the file
|
|
// is executed before we can create a transitive rule for it, then we can at
|
|
// least log the pending decision info.
|
|
- (void)saveFakeDecision:(santa_message_t)message {
|
|
SNTCachedDecision *cd = [[SNTCachedDecision alloc] init];
|
|
cd.decision = SNTEventStateAllowPendingTransitive;
|
|
cd.vnodeId = message.vnode_id;
|
|
cd.sha256 = @"pending";
|
|
[self.eventLog cacheDecision:cd];
|
|
}
|
|
|
|
- (void)removeFakeDecision:(santa_message_t)message {
|
|
[self.eventLog forgetCachedDecisionForVnodeId:message.vnode_id];
|
|
}
|
|
|
|
// Assume that this method is called only when we already know that the writing process is a
|
|
// compiler. It checks if the closed file is executable, and if so, transitively whitelists it.
|
|
// The passed in message contains the pid of the writing process and path of closed file.
|
|
- (void)createTransitiveRule:(santa_message_t)message {
|
|
[self saveFakeDecision:message];
|
|
|
|
char *target = message.path;
|
|
|
|
// Check if this file is an executable.
|
|
SNTFileInfo *fi = [[SNTFileInfo alloc] initWithPath:@(target)];
|
|
if (fi.isExecutable) {
|
|
// Check if there is an existing (non-transitive) rule for this file. We leave existing rules
|
|
// alone, so that a whitelist or blacklist rule can't be overwritten by a transitive one.
|
|
SNTRuleTable *ruleTable = [SNTDatabaseController ruleTable];
|
|
SNTRule *prevRule = [ruleTable ruleForBinarySHA256:fi.SHA256 certificateSHA256:nil];
|
|
if (!prevRule || prevRule.state == SNTRuleStateWhitelistTransitive) {
|
|
// Construct a new transitive whitelist rule for the executable.
|
|
SNTRule *rule = [[SNTRule alloc] initWithShasum:fi.SHA256
|
|
state:SNTRuleStateWhitelistTransitive
|
|
type:SNTRuleTypeBinary
|
|
customMsg:@""];
|
|
|
|
// Add the new rule to the rules database.
|
|
NSError *err;
|
|
if (![ruleTable addRules:@[ rule ] cleanSlate:NO error:&err]) {
|
|
LOGE(@"unable to add new transitive rule to database: %@", err.localizedDescription);
|
|
} else {
|
|
[self.eventLog
|
|
writeLog:[NSString stringWithFormat:@"action=WHITELIST|pid=%d|path=%s|sha256=%@",
|
|
message.pid, target, fi.SHA256]];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove the temporary allow rule in the kernel decision cache.
|
|
[self.eventProvider removeCacheEntryForVnodeID:message.vnode_id];
|
|
// Remove the "pending" decision info from SNTEventLog.
|
|
[self removeFakeDecision:message];
|
|
}
|
|
|
|
@end
|