• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / santa / 9272684788

28 May 2024 04:04PM UTC coverage: 62.536% (-0.1%) from 62.648%
9272684788

Pull #1359

github

web-flow
Merge 66ad2d6d8 into 7502bc247
Pull Request #1359: sync: Add a protobuf for the existing sync protocol

5215 of 12696 branches covered (41.08%)

Branch coverage included in aggregate %.

237 of 288 new or added lines in 6 files covered. (82.29%)

7 existing lines in 1 file now uncovered.

17810 of 24123 relevant lines covered (73.83%)

7007.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

23.87
/Source/common/SNTConfigurator.m
1
/// Copyright 2014-2022 Google Inc. All rights reserved.
2
///
3
/// Licensed under the Apache License, Version 2.0 (the "License");
4
/// you may not use this file except in compliance with the License.
5
/// You may obtain a copy of the License at
6
///
7
///    http://www.apache.org/licenses/LICENSE-2.0
8
///
9
///    Unless required by applicable law or agreed to in writing, software
10
///    distributed under the License is distributed on an "AS IS" BASIS,
11
///    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
///    See the License for the specific language governing permissions and
13
///    limitations under the License.
14

15
#import "Source/common/SNTConfigurator.h"
16

17
#include <sys/stat.h>
18

19
#import "Source/common/SNTRule.h"
20
#import "Source/common/SNTStrengthify.h"
21
#import "Source/common/SNTSystemInfo.h"
22

23
// Ensures the given object is an NSArray and only contains NSString value types
24
static NSArray<NSString *> *EnsureArrayOfStrings(id obj) {
×
25
  if (![obj isKindOfClass:[NSArray class]]) {
×
26
    return nil;
×
27
  }
×
28

29
  for (id item in obj) {
×
30
    if (![item isKindOfClass:[NSString class]]) {
×
31
      return nil;
×
32
    }
×
33
  }
×
34

35
  return obj;
×
36
}
×
37

38
@interface SNTConfigurator ()
39
/// A NSUserDefaults object set to use the com.google.santa suite.
40
@property(readonly, nonatomic) NSUserDefaults *defaults;
41

42
/// Keys and expected value types.
43
@property(readonly, nonatomic) NSDictionary *syncServerKeyTypes;
44
@property(readonly, nonatomic) NSDictionary *forcedConfigKeyTypes;
45

46
/// Holds the configurations from a sync server and mobileconfig.
47
@property NSDictionary *syncState;
48
@property NSMutableDictionary *configState;
49

50
/// Was --debug passed as an argument to this process?
51
@property(readonly, nonatomic) BOOL debugFlag;
52

53
/// Holds the last processed hash of the static rules list.
54
@property(atomic) NSDictionary *cachedStaticRules;
55

56
@property(readonly, nonatomic) NSString *syncStateFilePath;
57
@property(nonatomic, copy) BOOL (^syncStateAccessAuthorizerBlock)();
58

59
@end
60

61
@implementation SNTConfigurator
62

63
/// The hard-coded path to the sync state file.
64
NSString *const kSyncStateFilePath = @"/var/db/santa/sync-state.plist";
65

66
#ifdef DEBUG
67
NSString *const kConfigOverrideFilePath = @"/var/db/santa/config-overrides.plist";
68
#endif
69

70
/// The domain used by mobileconfig.
71
static NSString *const kMobileConfigDomain = @"com.google.santa";
72

73
/// The keys managed by a mobileconfig.
74
static NSString *const kStaticRules = @"StaticRules";
75
static NSString *const kSyncBaseURLKey = @"SyncBaseURL";
76
static NSString *const kSyncProxyConfigKey = @"SyncProxyConfiguration";
77
static NSString *const kSyncExtraHeadersKey = @"SyncExtraHeaders";
78
static NSString *const kSyncEnableCleanSyncEventUpload = @"SyncEnableCleanSyncEventUpload";
79
static NSString *const kClientAuthCertificateFileKey = @"ClientAuthCertificateFile";
80
static NSString *const kClientAuthCertificatePasswordKey = @"ClientAuthCertificatePassword";
81
static NSString *const kClientAuthCertificateCNKey = @"ClientAuthCertificateCN";
82
static NSString *const kClientAuthCertificateIssuerKey = @"ClientAuthCertificateIssuerCN";
83
static NSString *const kServerAuthRootsDataKey = @"ServerAuthRootsData";
84
static NSString *const kServerAuthRootsFileKey = @"ServerAuthRootsFile";
85

86
static NSString *const kMachineOwnerKey = @"MachineOwner";
87
static NSString *const kMachineIDKey = @"MachineID";
88
static NSString *const kMachineOwnerPlistFileKey = @"MachineOwnerPlist";
89
static NSString *const kMachineOwnerPlistKeyKey = @"MachineOwnerKey";
90
static NSString *const kMachineIDPlistFileKey = @"MachineIDPlist";
91
static NSString *const kMachineIDPlistKeyKey = @"MachineIDKey";
92

93
static NSString *const kEnableSilentModeKey = @"EnableSilentMode";
94
static NSString *const kEnableSilentTTYModeKey = @"EnableSilentTTYMode";
95
static NSString *const kAboutTextKey = @"AboutText";
96
static NSString *const kMoreInfoURLKey = @"MoreInfoURL";
97
static NSString *const kEventDetailURLKey = @"EventDetailURL";
98
static NSString *const kEventDetailTextKey = @"EventDetailText";
99
static NSString *const kUnknownBlockMessage = @"UnknownBlockMessage";
100
static NSString *const kBannedBlockMessage = @"BannedBlockMessage";
101
static NSString *const kBannedUSBBlockMessage = @"BannedUSBBlockMessage";
102
static NSString *const kRemountUSBBlockMessage = @"RemountUSBBlockMessage";
103

104
static NSString *const kModeNotificationMonitor = @"ModeNotificationMonitor";
105
static NSString *const kModeNotificationLockdown = @"ModeNotificationLockdown";
106

107
static NSString *const kEnablePageZeroProtectionKey = @"EnablePageZeroProtection";
108
static NSString *const kEnableBadSignatureProtectionKey = @"EnableBadSignatureProtection";
109
static NSString *const kFailClosedKey = @"FailClosed";
110
static NSString *const kDisableUnknownEventUploadKey = @"DisableUnknownEventUpload";
111

112
static NSString *const kFileChangesRegexKey = @"FileChangesRegex";
113
static NSString *const kFileChangesPrefixFiltersKey = @"FileChangesPrefixFilters";
114

115
static NSString *const kEventLogType = @"EventLogType";
116
static NSString *const kEventLogPath = @"EventLogPath";
117
static NSString *const kSpoolDirectory = @"SpoolDirectory";
118
static NSString *const kSpoolDirectoryFileSizeThresholdKB = @"SpoolDirectoryFileSizeThresholdKB";
119
static NSString *const kSpoolDirectorySizeThresholdMB = @"SpoolDirectorySizeThresholdMB";
120
static NSString *const kSpoolDirectoryEventMaxFlushTimeSec = @"SpoolDirectoryEventMaxFlushTimeSec";
121

122
static NSString *const kFileAccessPolicy = @"FileAccessPolicy";
123
static NSString *const kFileAccessPolicyPlist = @"FileAccessPolicyPlist";
124
static NSString *const kFileAccessBlockMessage = @"FileAccessBlockMessage";
125
static NSString *const kFileAccessPolicyUpdateIntervalSec = @"FileAccessPolicyUpdateIntervalSec";
126

127
static NSString *const kEnableMachineIDDecoration = @"EnableMachineIDDecoration";
128

129
static NSString *const kEnableForkAndExitLogging = @"EnableForkAndExitLogging";
130
static NSString *const kIgnoreOtherEndpointSecurityClients = @"IgnoreOtherEndpointSecurityClients";
131
static NSString *const kEnableDebugLogging = @"EnableDebugLogging";
132

133
static NSString *const kClientContentEncoding = @"SyncClientContentEncoding";
134

135
static NSString *const kFCMProject = @"FCMProject";
136
static NSString *const kFCMEntity = @"FCMEntity";
137
static NSString *const kFCMAPIKey = @"FCMAPIKey";
138

139
static NSString *const kEntitlementsPrefixFilterKey = @"EntitlementsPrefixFilter";
140
static NSString *const kEntitlementsTeamIDFilterKey = @"EntitlementsTeamIDFilter";
141

142
static NSString *const kOnStartUSBOptions = @"OnStartUSBOptions";
143

144
static NSString *const kMetricFormat = @"MetricFormat";
145
static NSString *const kMetricURL = @"MetricURL";
146
static NSString *const kMetricExportInterval = @"MetricExportInterval";
147
static NSString *const kMetricExportTimeout = @"MetricExportTimeout";
148
static NSString *const kMetricExtraLabels = @"MetricExtraLabels";
149

150
static NSString *const kEnabledProcessAnnotations = @"EnabledProcessAnnotations";
151

152
// The keys managed by a sync server or mobileconfig.
153
static NSString *const kClientModeKey = @"ClientMode";
154
static NSString *const kBlockUSBMountKey = @"BlockUSBMount";
155
static NSString *const kRemountUSBModeKey = @"RemountUSBMode";
156
static NSString *const kEnableTransitiveRulesKey = @"EnableTransitiveRules";
157
static NSString *const kEnableTransitiveRulesKeyDeprecated = @"EnableTransitiveWhitelisting";
158
static NSString *const kAllowedPathRegexKey = @"AllowedPathRegex";
159
static NSString *const kAllowedPathRegexKeyDeprecated = @"WhitelistRegex";
160
static NSString *const kBlockedPathRegexKey = @"BlockedPathRegex";
161
static NSString *const kBlockedPathRegexKeyDeprecated = @"BlacklistRegex";
162
static NSString *const kEnableAllEventUploadKey = @"EnableAllEventUpload";
163
static NSString *const kOverrideFileAccessActionKey = @"OverrideFileAccessAction";
164

165
// The keys managed by a sync server.
166
static NSString *const kFullSyncLastSuccess = @"FullSyncLastSuccess";
167
static NSString *const kRuleSyncLastSuccess = @"RuleSyncLastSuccess";
168
static NSString *const kSyncCleanRequiredDeprecated = @"SyncCleanRequired";
169
static NSString *const kSyncTypeRequired = @"SyncTypeRequired";
170

171
- (instancetype)init {
16✔
172
  return [self initWithSyncStateFile:kSyncStateFilePath
16✔
173
           syncStateAccessAuthorizer:^BOOL() {
16✔
174
             // Only access the sync state if a sync server is configured and running as root
175
             return self.syncBaseURL != nil && geteuid() == 0;
16!
176
           }];
16✔
177
}
16✔
178

179
- (instancetype)initWithSyncStateFile:(NSString *)syncStateFilePath
180
            syncStateAccessAuthorizer:(BOOL (^)(void))syncStateAccessAuthorizer {
19✔
181
  self = [super init];
19✔
182
  if (self) {
19!
183
    Class number = [NSNumber class];
19✔
184
    Class re = [NSRegularExpression class];
19✔
185
    Class date = [NSDate class];
19✔
186
    Class string = [NSString class];
19✔
187
    Class data = [NSData class];
19✔
188
    Class array = [NSArray class];
19✔
189
    Class dictionary = [NSDictionary class];
19✔
190
    _syncServerKeyTypes = @{
19✔
191
      kClientModeKey : number,
19✔
192
      kEnableTransitiveRulesKey : number,
19✔
193
      kEnableTransitiveRulesKeyDeprecated : number,
19✔
194
      kAllowedPathRegexKey : re,
19✔
195
      kAllowedPathRegexKeyDeprecated : re,
19✔
196
      kBlockedPathRegexKey : re,
19✔
197
      kBlockedPathRegexKeyDeprecated : re,
19✔
198
      kBlockUSBMountKey : number,
19✔
199
      kRemountUSBModeKey : array,
19✔
200
      kFullSyncLastSuccess : date,
19✔
201
      kRuleSyncLastSuccess : date,
19✔
202
      kSyncCleanRequiredDeprecated : number,
19✔
203
      kSyncTypeRequired : number,
19✔
204
      kEnableAllEventUploadKey : number,
19✔
205
      kOverrideFileAccessActionKey : string,
19✔
206
    };
19✔
207
    _forcedConfigKeyTypes = @{
19✔
208
      kClientModeKey : number,
19✔
209
      kFailClosedKey : number,
19✔
210
      kEnableTransitiveRulesKey : number,
19✔
211
      kEnableTransitiveRulesKeyDeprecated : number,
19✔
212
      kFileChangesRegexKey : re,
19✔
213
      kFileChangesPrefixFiltersKey : array,
19✔
214
      kAllowedPathRegexKey : re,
19✔
215
      kAllowedPathRegexKeyDeprecated : re,
19✔
216
      kBlockedPathRegexKey : re,
19✔
217
      kBlockedPathRegexKeyDeprecated : re,
19✔
218
      kBlockUSBMountKey : number,
19✔
219
      kRemountUSBModeKey : array,
19✔
220
      kOnStartUSBOptions : string,
19✔
221
      kEnablePageZeroProtectionKey : number,
19✔
222
      kEnableBadSignatureProtectionKey : number,
19✔
223
      kEnableSilentModeKey : number,
19✔
224
      kEnableSilentTTYModeKey : number,
19✔
225
      kAboutTextKey : string,
19✔
226
      kMoreInfoURLKey : string,
19✔
227
      kEventDetailURLKey : string,
19✔
228
      kEventDetailTextKey : string,
19✔
229
      kUnknownBlockMessage : string,
19✔
230
      kBannedBlockMessage : string,
19✔
231
      kBannedUSBBlockMessage : string,
19✔
232
      kRemountUSBBlockMessage : string,
19✔
233
      kModeNotificationMonitor : string,
19✔
234
      kModeNotificationLockdown : string,
19✔
235
      kStaticRules : array,
19✔
236
      kSyncBaseURLKey : string,
19✔
237
      kSyncEnableCleanSyncEventUpload : number,
19✔
238
      kSyncProxyConfigKey : dictionary,
19✔
239
      kSyncExtraHeadersKey : dictionary,
19✔
240
      kClientAuthCertificateFileKey : string,
19✔
241
      kClientAuthCertificatePasswordKey : string,
19✔
242
      kClientAuthCertificateCNKey : string,
19✔
243
      kClientAuthCertificateIssuerKey : string,
19✔
244
      kClientContentEncoding : string,
19✔
245
      kServerAuthRootsDataKey : data,
19✔
246
      kServerAuthRootsFileKey : string,
19✔
247
      kMachineOwnerKey : string,
19✔
248
      kMachineIDKey : string,
19✔
249
      kMachineOwnerPlistFileKey : string,
19✔
250
      kMachineOwnerPlistKeyKey : string,
19✔
251
      kMachineIDPlistFileKey : string,
19✔
252
      kMachineIDPlistKeyKey : string,
19✔
253
      kEventLogType : string,
19✔
254
      kEventLogPath : string,
19✔
255
      kSpoolDirectory : string,
19✔
256
      kSpoolDirectoryFileSizeThresholdKB : number,
19✔
257
      kSpoolDirectorySizeThresholdMB : number,
19✔
258
      kSpoolDirectoryEventMaxFlushTimeSec : number,
19✔
259
      kFileAccessPolicy : dictionary,
19✔
260
      kFileAccessPolicyPlist : string,
19✔
261
      kFileAccessBlockMessage : string,
19✔
262
      kFileAccessPolicyUpdateIntervalSec : number,
19✔
263
      kEnableMachineIDDecoration : number,
19✔
264
      kEnableForkAndExitLogging : number,
19✔
265
      kIgnoreOtherEndpointSecurityClients : number,
19✔
266
      kEnableDebugLogging : number,
19✔
267
      kFCMProject : string,
19✔
268
      kFCMEntity : string,
19✔
269
      kFCMAPIKey : string,
19✔
270
      kMetricFormat : string,
19✔
271
      kMetricURL : string,
19✔
272
      kMetricExportInterval : number,
19✔
273
      kMetricExportTimeout : number,
19✔
274
      kMetricExtraLabels : dictionary,
19✔
275
      kEnableAllEventUploadKey : number,
19✔
276
      kDisableUnknownEventUploadKey : number,
19✔
277
      kOverrideFileAccessActionKey : string,
19✔
278
      kEntitlementsPrefixFilterKey : array,
19✔
279
      kEntitlementsTeamIDFilterKey : array,
19✔
280
      kEnabledProcessAnnotations : array,
19✔
281
    };
19✔
282

283
    _syncStateFilePath = syncStateFilePath;
19✔
284
    _syncStateAccessAuthorizerBlock = syncStateAccessAuthorizer;
19✔
285

286
    _defaults = [NSUserDefaults standardUserDefaults];
19✔
287
    [_defaults addSuiteNamed:@"com.google.santa"];
19✔
288
    _configState = [self readForcedConfig];
19✔
289
    [self cacheStaticRules];
19✔
290

291
    _syncState = [self readSyncStateFromDisk] ?: [NSMutableDictionary dictionary];
19✔
292
    if ([self migrateDeprecatedSyncStateKeys]) {
19✔
293
      // Save the updated sync state if any keys were migrated.
294
      [self saveSyncStateToDisk];
2✔
295
    }
2✔
296

297
    _debugFlag = [[NSProcessInfo processInfo].arguments containsObject:@"--debug"];
19✔
298
    [self startWatchingDefaults];
19✔
299
  }
19✔
300
  return self;
19✔
301
}
19✔
302

303
#pragma mark Singleton retriever
304

305
// The returned value is marked unsafe_unretained to avoid unnecessary retain/release handling.
306
// The object returned is guaranteed to exist for the lifetime of the process so there's no need
307
// to do this handling.
308
+ (__unsafe_unretained instancetype)configurator {
114✔
309
  static SNTConfigurator *sharedConfigurator;
114✔
310
  static dispatch_once_t onceToken;
114✔
311
  dispatch_once(&onceToken, ^{
114✔
312
    sharedConfigurator = [[SNTConfigurator alloc] init];
16✔
313
  });
16✔
314
  return sharedConfigurator;
114✔
315
}
114✔
316

317
+ (NSSet *)syncAndConfigStateSet {
×
318
  static NSSet *set;
×
319
  static dispatch_once_t onceToken;
×
320
  dispatch_once(&onceToken, ^{
×
321
    set = [[self syncStateSet] setByAddingObjectsFromSet:[self configStateSet]];
×
322
  });
×
323
  return set;
×
324
}
×
325

326
+ (NSSet *)syncStateSet {
×
327
  static NSSet *set;
×
328
  static dispatch_once_t onceToken;
×
329
  dispatch_once(&onceToken, ^{
×
330
    set = [NSSet setWithObject:NSStringFromSelector(@selector(syncState))];
×
331
  });
×
332
  return set;
×
333
}
×
334

335
+ (NSSet *)configStateSet {
×
336
  static NSSet *set;
×
337
  static dispatch_once_t onceToken;
×
338
  dispatch_once(&onceToken, ^{
×
339
    set = [NSSet setWithObject:NSStringFromSelector(@selector(configState))];
×
340
  });
×
341
  return set;
×
342
}
×
343

344
#pragma mark KVO Dependencies
345

346
+ (NSSet *)keyPathsForValuesAffectingClientMode {
×
347
  return [self syncAndConfigStateSet];
×
348
}
×
349

350
+ (NSSet *)keyPathsForValuesAffectingAllowlistPathRegex {
×
351
  return [self syncAndConfigStateSet];
×
352
}
×
353

354
+ (NSSet *)keyPathsForValuesAffectingBlocklistPathRegex {
×
355
  return [self syncAndConfigStateSet];
×
356
}
×
357

358
+ (NSSet *)keyPathsForValuesAffectingFileChangesRegex {
×
359
  return [self configStateSet];
×
360
}
×
361

362
+ (NSSet *)keyPathsForValuesAffectingFileChangesPrefixFiltersKey {
×
363
  return [self configStateSet];
×
364
}
×
365

366
+ (NSSet *)keyPathsForValuesAffectingStaticRules {
×
367
  return [self configStateSet];
×
368
}
×
369

370
+ (NSSet *)keyPathsForValuesAffectingSyncBaseURL {
×
371
  return [self configStateSet];
×
372
}
×
373

374
+ (NSSet *)keyPathsForValuesAffectingSyncExtraHeaders {
×
375
  return [self configStateSet];
×
376
}
×
377

378
+ (NSSet *)keyPathsForValuesAffectingEnableCleanSyncEventUpload {
×
379
  return [self configStateSet];
×
380
}
×
381

382
+ (NSSet *)keyPathsForValuesAffectingEnablePageZeroProtection {
×
383
  return [self configStateSet];
×
384
}
×
385

386
+ (NSSet *)keyPathsForValuesAffectingEnableSilentMode {
×
387
  return [self configStateSet];
×
388
}
×
389

390
+ (NSSet *)keyPathsForValuesAffectingAboutText {
×
391
  return [self configStateSet];
×
392
}
×
393

394
+ (NSSet *)keyPathsForValuesAffectingMoreInfoURL {
×
395
  return [self configStateSet];
×
396
}
×
397

398
+ (NSSet *)keyPathsForValuesAffectingEventDetailURL {
×
399
  return [self configStateSet];
×
400
}
×
401

402
+ (NSSet *)keyPathsForValuesAffectingEventDetailText {
×
403
  return [self configStateSet];
×
404
}
×
405

406
+ (NSSet *)keyPathsForValuesAffectingUnknownBlockMessage {
×
407
  return [self configStateSet];
×
408
}
×
409

410
+ (NSSet *)keyPathsForValuesAffectingBannedBlockMessage {
×
411
  return [self configStateSet];
×
412
}
×
413

414
+ (NSSet *)keyPathsForValuesAffectingModeNotificationMonitor {
×
415
  return [self configStateSet];
×
416
}
×
417

418
+ (NSSet *)keyPathsForValuesAffectingModeNotificationLockdown {
×
419
  return [self configStateSet];
×
420
}
×
421

422
+ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateFile {
×
423
  return [self configStateSet];
×
424
}
×
425

426
+ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificatePassword {
×
427
  return [self configStateSet];
×
428
}
×
429

430
+ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateCn {
×
431
  return [self configStateSet];
×
432
}
×
433

434
+ (NSSet *)keyPathsForValuesAffectingSyncClientAuthCertificateIssuer {
×
435
  return [self configStateSet];
×
436
}
×
437

438
+ (NSSet *)keyPathsForValuesAffectingSyncServerAuthRootsData {
×
439
  return [self configStateSet];
×
440
}
×
441

442
+ (NSSet *)keyPathsForValuesAffectingSyncServerAuthRootsFile {
×
443
  return [self configStateSet];
×
444
}
×
445

446
+ (NSSet *)keyPathsForValuesAffectingMachineOwner {
×
447
  return [self configStateSet];
×
448
}
×
449

450
+ (NSSet *)keyPathsForValuesAffectingMachineID {
×
451
  return [self configStateSet];
×
452
}
×
453

454
+ (NSSet *)keyPathsForValuesAffectingFullSyncLastSuccess {
×
455
  return [self syncStateSet];
×
456
}
×
457

458
+ (NSSet *)keyPathsForValuesAffectingRuleSyncLastSuccess {
×
459
  return [self syncStateSet];
×
460
}
×
461

462
+ (NSSet *)keyPathsForValuesAffectingSyncTypeRequired {
×
463
  return [self syncStateSet];
×
464
}
×
465

466
+ (NSSet *)keyPathsForValuesAffectingEventLogType {
×
467
  return [self configStateSet];
×
468
}
×
469

470
+ (NSSet *)keyPathsForValuesAffectingEventLogPath {
×
471
  return [self configStateSet];
×
472
}
×
473

474
+ (NSSet *)keyPathsForValuesAffectingSpoolDirectory {
×
475
  return [self configStateSet];
×
476
}
×
477

478
+ (NSSet *)keyPathsForValuesAffectingSpoolDirectoryFileSizeThresholdKB {
×
479
  return [self configStateSet];
×
480
}
×
481

482
+ (NSSet *)keyPathsForValuesAffectingSpoolDirectorySizeThresholdMB {
×
483
  return [self configStateSet];
×
484
}
×
485

486
+ (NSSet *)keyPathsForValuesAffectingSpoolDirectoryEventMaxFlushTimeSec {
×
487
  return [self configStateSet];
×
488
}
×
489

490
+ (NSSet *)keyPathsForValuesAffectingFileAccessPolicy {
×
491
  return [self configStateSet];
×
492
}
×
493

494
+ (NSSet *)keyPathsForValuesAffectingFileAccessPolicyPlist {
×
495
  return [self configStateSet];
×
496
}
×
497

498
+ (NSSet *)keyPathsForValuesAffectingFileAccessBlockMessage {
×
499
  return [self configStateSet];
×
500
}
×
501

502
+ (NSSet *)keyPathsForValuesAffectingFileAccessPolicyUpdateIntervalSec {
×
503
  return [self configStateSet];
×
504
}
×
505

506
+ (NSSet *)keyPathsForValuesAffectingEnableMachineIDDecoration {
×
507
  return [self configStateSet];
×
508
}
×
509

510
+ (NSSet *)keyPathsForValuesAffectingEnableTransitiveRules {
×
511
  return [self syncAndConfigStateSet];
×
512
}
×
513

514
+ (NSSet *)keyPathsForValuesAffectingEnableAllEventUpload {
×
515
  return [self syncAndConfigStateSet];
×
516
}
×
517

518
+ (NSSet *)keyPathsForValuesAffectingDisableUnknownEventUpload {
×
519
  return [self syncAndConfigStateSet];
×
520
}
×
521

522
+ (NSSet *)keyPathsForValuesAffectingEnableForkAndExitLogging {
×
523
  return [self configStateSet];
×
524
}
×
525

526
+ (NSSet *)keyPathsForValuesAffectingIgnoreOtherEndpointSecurityClients {
×
527
  return [self configStateSet];
×
528
}
×
529

530
+ (NSSet *)keyPathsForValuesAffectingEnableDebugLogging {
×
531
  return [self configStateSet];
×
532
}
×
533

534
+ (NSSet *)keyPathsForValuesAffectingFcmProject {
×
535
  return [self configStateSet];
×
536
}
×
537

538
+ (NSSet *)keyPathsForValuesAffectingFcmEntity {
×
539
  return [self configStateSet];
×
540
}
×
541

542
+ (NSSet *)keyPathsForValuesAffectingFcmAPIKey {
×
543
  return [self configStateSet];
×
544
}
×
545

546
+ (NSSet *)keyPathsForValuesAffectingFcmEnabled {
×
547
  return [self configStateSet];
×
548
}
×
549

550
+ (NSSet *)keyPathsForValuesAffectingEnableBadSignatureProtection {
×
551
  return [self configStateSet];
×
552
}
×
553

554
+ (NSSet *)keyPathsForValuesAffectingBlockUSBMount {
×
555
  return [self syncAndConfigStateSet];
×
556
}
×
557

558
+ (NSSet *)keyPathsForValuesAffectingBannedUSBBlockMessage {
×
559
  return [self configStateSet];
×
560
}
×
561

562
+ (NSSet *)keyPathsForValuesAffectingRemountUSBMode {
×
563
  return [self syncAndConfigStateSet];
×
564
}
×
565

566
+ (NSSet *)keyPathsForValuesAffectingRemountUSBBlockMessage {
×
567
  return [self configStateSet];
×
568
}
×
569

570
+ (NSSet *)keyPathsForValuesAffectingUsbBlockMessage {
×
571
  return [self configStateSet];
×
572
}
×
573

574
+ (NSSet *)keyPathsForValuesAffectingOverrideFileAccessActionKey {
×
575
  return [self syncAndConfigStateSet];
×
576
}
×
577

578
+ (NSSet *)keyPathsForValuesAffectingEntitlementsPrefixFilter {
×
579
  return [self configStateSet];
×
580
}
×
581

582
+ (NSSet *)keyPathsForValuesAffectingEntitlementsTeamIDFilter {
×
583
  return [self configStateSet];
×
584
}
×
585

586
#pragma mark Public Interface
587

588
- (SNTClientMode)clientMode {
×
589
  SNTClientMode cm = [self.syncState[kClientModeKey] longLongValue];
×
590
  if (cm == SNTClientModeMonitor || cm == SNTClientModeLockdown) {
×
591
    return cm;
×
592
  }
×
593

594
  cm = [self.configState[kClientModeKey] longLongValue];
×
595
  if (cm == SNTClientModeMonitor || cm == SNTClientModeLockdown) {
×
596
    return cm;
×
597
  }
×
598

599
  return SNTClientModeMonitor;
×
600
}
×
601

602
- (void)setSyncServerClientMode:(SNTClientMode)newMode {
×
603
  if (newMode == SNTClientModeMonitor || newMode == SNTClientModeLockdown) {
×
604
    [self updateSyncStateForKey:kClientModeKey value:@(newMode)];
×
605
  }
×
606
}
×
607

608
- (BOOL)failClosed {
×
609
  NSNumber *n = self.configState[kFailClosedKey];
×
610
  return [n boolValue] && self.clientMode == SNTClientModeLockdown;
×
611
}
×
612

613
- (BOOL)enableTransitiveRules {
×
614
  NSNumber *n = self.syncState[kEnableTransitiveRulesKey];
×
615
  if (n) return [n boolValue];
×
616

617
  n = self.syncState[kEnableTransitiveRulesKeyDeprecated];
×
618
  if (n) return [n boolValue];
×
619

620
  n = self.configState[kEnableTransitiveRulesKeyDeprecated];
×
621
  if (n) return [n boolValue];
×
622

623
  return [self.configState[kEnableTransitiveRulesKey] boolValue];
×
624
}
×
625

626
- (void)setEnableTransitiveRules:(BOOL)enabled {
×
627
  [self updateSyncStateForKey:kEnableTransitiveRulesKey value:@(enabled)];
×
628
}
×
629

630
- (NSRegularExpression *)allowedPathRegex {
×
631
  NSRegularExpression *r = self.syncState[kAllowedPathRegexKey];
×
632
  if (r) return r;
×
633

634
  r = self.syncState[kAllowedPathRegexKeyDeprecated];
×
635
  if (r) return r;
×
636

637
  r = self.configState[kAllowedPathRegexKey];
×
638
  if (r) return r;
×
639

640
  return self.configState[kAllowedPathRegexKeyDeprecated];
×
641
}
×
642

643
- (void)setSyncServerAllowedPathRegex:(NSRegularExpression *)re {
×
644
  [self updateSyncStateForKey:kAllowedPathRegexKey value:re];
×
645
}
×
646

647
- (NSRegularExpression *)blockedPathRegex {
×
648
  NSRegularExpression *r = self.syncState[kBlockedPathRegexKey];
×
649
  if (r) return r;
×
650

651
  r = self.syncState[kBlockedPathRegexKeyDeprecated];
×
652
  if (r) return r;
×
653

654
  r = self.configState[kBlockedPathRegexKey];
×
655
  if (r) return r;
×
656

657
  return self.configState[kBlockedPathRegexKeyDeprecated];
×
658
}
×
659

660
- (void)setSyncServerBlockedPathRegex:(NSRegularExpression *)re {
×
661
  [self updateSyncStateForKey:kBlockedPathRegexKey value:re];
×
662
}
×
663

664
- (NSRegularExpression *)fileChangesRegex {
×
665
  return self.configState[kFileChangesRegexKey];
×
666
}
×
667

668
- (NSArray *)fileChangesPrefixFilters {
×
669
  NSArray *filters = self.configState[kFileChangesPrefixFiltersKey];
×
670
  for (id filter in filters) {
×
671
    if (![filter isKindOfClass:[NSString class]]) {
×
672
      return nil;
×
673
    }
×
674
  }
×
675
  return filters;
×
676
}
×
677

678
- (void)setRemountUSBMode:(NSArray<NSString *> *)args {
×
679
  [self updateSyncStateForKey:kRemountUSBModeKey value:args];
×
680
}
×
681

682
- (NSArray<NSString *> *)remountUSBMode {
×
683
  NSArray<NSString *> *args = self.syncState[kRemountUSBModeKey];
×
684
  if (!args) {
×
685
    args = (NSArray<NSString *> *)self.configState[kRemountUSBModeKey];
×
686
  }
×
687
  for (id arg in args) {
×
688
    if (![arg isKindOfClass:[NSString class]]) {
×
689
      return nil;
×
690
    }
×
691
  }
×
692
  return args;
×
693
}
×
694

695
- (SNTDeviceManagerStartupPreferences)onStartUSBOptions {
×
696
  NSString *action = [self.configState[kOnStartUSBOptions] lowercaseString];
×
697

698
  if ([action isEqualToString:@"unmount"]) {
×
699
    return SNTDeviceManagerStartupPreferencesUnmount;
×
700
  } else if ([action isEqualToString:@"forceunmount"]) {
×
701
    return SNTDeviceManagerStartupPreferencesForceUnmount;
×
702
  } else if ([action isEqualToString:@"remount"]) {
×
703
    return SNTDeviceManagerStartupPreferencesRemount;
×
704
  } else if ([action isEqualToString:@"forceremount"]) {
×
705
    return SNTDeviceManagerStartupPreferencesForceRemount;
×
706
  } else {
×
707
    return SNTDeviceManagerStartupPreferencesNone;
×
708
  }
×
709
}
×
710

711
- (NSDictionary<NSString *, SNTRule *> *)staticRules {
×
712
  return self.cachedStaticRules;
×
713
}
×
714

715
- (NSURL *)syncBaseURL {
16✔
716
  NSString *urlString = self.configState[kSyncBaseURLKey];
16✔
717
  if (![urlString hasSuffix:@"/"]) urlString = [urlString stringByAppendingString:@"/"];
16!
718
  NSURL *url = [NSURL URLWithString:urlString];
16✔
719
  return url;
16✔
720
}
16✔
721

722
- (NSDictionary *)syncProxyConfig {
×
723
  return self.configState[kSyncProxyConfigKey];
×
724
}
×
725

726
- (NSDictionary *)syncExtraHeaders {
39✔
727
  return self.configState[kSyncExtraHeadersKey];
39✔
728
}
39✔
729

730
- (BOOL)enablePageZeroProtection {
×
731
  NSNumber *number = self.configState[kEnablePageZeroProtectionKey];
×
732
  return number ? [number boolValue] : YES;
×
733
}
×
734

735
- (BOOL)enableBadSignatureProtection {
×
736
  NSNumber *number = self.configState[kEnableBadSignatureProtectionKey];
×
737
  return number ? [number boolValue] : NO;
×
738
}
×
739

740
- (BOOL)enableSilentMode {
1✔
741
  NSNumber *number = self.configState[kEnableSilentModeKey];
1✔
742
  return number ? [number boolValue] : NO;
1!
743
}
1✔
744

745
- (BOOL)enableSilentTTYMode {
×
746
  NSNumber *number = self.configState[kEnableSilentTTYModeKey];
×
747
  return number ? [number boolValue] : NO;
×
748
}
×
749

750
- (NSString *)aboutText {
×
751
  return self.configState[kAboutTextKey];
×
752
}
×
753

754
- (NSURL *)moreInfoURL {
×
755
  return [NSURL URLWithString:self.configState[kMoreInfoURLKey]];
×
756
}
×
757

758
- (NSString *)eventDetailURL {
1✔
759
  return self.configState[kEventDetailURLKey];
1✔
760
}
1✔
761

762
- (NSString *)eventDetailText {
×
763
  return self.configState[kEventDetailTextKey];
×
764
}
×
765

766
- (NSString *)unknownBlockMessage {
×
767
  return self.configState[kUnknownBlockMessage];
×
768
}
×
769

770
- (NSString *)bannedBlockMessage {
1✔
771
  return self.configState[kBannedBlockMessage];
1✔
772
}
1✔
773

774
- (NSString *)bannedUSBBlockMessage {
×
775
  if (!self.configState[kBannedUSBBlockMessage]) {
×
776
    return @"The following device has been blocked from mounting.";
×
777
  }
×
778

779
  return self.configState[kBannedUSBBlockMessage];
×
780
}
×
781

782
- (NSString *)remountUSBBlockMessage {
×
783
  if (!self.configState[kRemountUSBBlockMessage]) {
×
784
    return @"The following device has been remounted with reduced permissions.";
×
785
  }
×
786
  return self.configState[kRemountUSBBlockMessage];
×
787
}
×
788

789
- (NSString *)modeNotificationMonitor {
×
790
  return self.configState[kModeNotificationMonitor];
×
791
}
×
792

793
- (NSString *)modeNotificationLockdown {
×
794
  return self.configState[kModeNotificationLockdown];
×
795
}
×
796

797
- (NSString *)syncClientAuthCertificateFile {
×
798
  return self.configState[kClientAuthCertificateFileKey];
×
799
}
×
800

801
- (NSString *)syncClientAuthCertificatePassword {
×
802
  return self.configState[kClientAuthCertificatePasswordKey];
×
803
}
×
804

805
- (NSString *)syncClientAuthCertificateCn {
×
806
  return self.configState[kClientAuthCertificateCNKey];
×
807
}
×
808

809
- (NSString *)syncClientAuthCertificateIssuer {
×
810
  return self.configState[kClientAuthCertificateIssuerKey];
×
811
}
×
812

813
- (SNTSyncContentEncoding)syncClientContentEncoding {
×
814
  NSString *contentEncoding = [self.configState[kClientContentEncoding] lowercaseString];
×
815
  if ([contentEncoding isEqualToString:@"deflate"]) {
×
816
    return SNTSyncContentEncodingDeflate;
×
817
  } else if ([contentEncoding isEqualToString:@"gzip"]) {
×
818
    return SNTSyncContentEncodingGzip;
×
819
  } else if ([contentEncoding isEqualToString:@"none"]) {
×
820
    return SNTSyncContentEncodingNone;
×
821
  } else {
×
822
    // Ensure we have the same default zlib behavior Santa's always had otherwise.
823
    return SNTSyncContentEncodingDeflate;
×
824
  }
×
825
}
×
826

827
- (NSData *)syncServerAuthRootsData {
×
828
  return self.configState[kServerAuthRootsDataKey];
×
829
}
×
830

831
- (NSString *)syncServerAuthRootsFile {
×
832
  return self.configState[kServerAuthRootsFileKey];
×
833
}
×
834

835
- (NSDate *)fullSyncLastSuccess {
×
836
  return self.syncState[kFullSyncLastSuccess];
×
837
}
×
838

839
- (void)setFullSyncLastSuccess:(NSDate *)fullSyncLastSuccess {
×
840
  [self updateSyncStateForKey:kFullSyncLastSuccess value:fullSyncLastSuccess];
×
841
  self.ruleSyncLastSuccess = fullSyncLastSuccess;
×
842
}
×
843

844
- (NSDate *)ruleSyncLastSuccess {
×
845
  return self.syncState[kRuleSyncLastSuccess];
×
846
}
×
847

848
- (void)setRuleSyncLastSuccess:(NSDate *)ruleSyncLastSuccess {
×
849
  [self updateSyncStateForKey:kRuleSyncLastSuccess value:ruleSyncLastSuccess];
×
850
}
×
851

852
- (SNTSyncType)syncTypeRequired {
×
853
  return (SNTSyncType)[self.syncState[kSyncTypeRequired] integerValue];
×
854
}
×
855

856
- (void)setSyncTypeRequired:(SNTSyncType)syncTypeRequired {
21✔
857
  [self updateSyncStateForKey:kSyncTypeRequired value:@(syncTypeRequired)];
21✔
858
}
21✔
859

860
- (NSString *)machineOwner {
×
861
  NSString *machineOwner = self.configState[kMachineOwnerKey];
×
862
  if (machineOwner) return machineOwner;
×
863

864
  NSString *plistPath = self.configState[kMachineOwnerPlistFileKey];
×
865
  NSString *plistKey = self.configState[kMachineOwnerPlistKeyKey];
×
866
  if (plistPath && plistKey) {
×
867
    NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistPath];
×
868
    machineOwner = [plist[plistKey] isKindOfClass:[NSString class]] ? plist[plistKey] : nil;
×
869
  }
×
870

871
  return machineOwner ?: @"";
×
872
}
×
873

874
- (NSString *)machineID {
1✔
875
  NSString *machineId = self.configState[kMachineIDKey];
1✔
876
  if (machineId) return machineId;
1!
877

878
  NSString *plistPath = self.configState[kMachineIDPlistFileKey];
1✔
879
  NSString *plistKey = self.configState[kMachineIDPlistKeyKey];
1✔
880

881
  if (plistPath && plistKey) {
1!
882
    NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistPath];
×
883
    machineId = [plist[plistKey] isKindOfClass:[NSString class]] ? plist[plistKey] : nil;
×
884
  }
×
885

886
  return machineId.length ? machineId : [SNTSystemInfo hardwareUUID];
1!
887
}
1✔
888

889
- (SNTEventLogType)eventLogType {
×
890
  NSString *logType = [self.configState[kEventLogType] lowercaseString];
×
891
  if ([logType isEqualToString:@"protobuf"]) {
×
892
    return SNTEventLogTypeProtobuf;
×
893
  } else if ([logType isEqualToString:@"syslog"]) {
×
894
    return SNTEventLogTypeSyslog;
×
895
  } else if ([logType isEqualToString:@"null"]) {
×
896
    return SNTEventLogTypeNull;
×
897
  } else if ([logType isEqualToString:@"json"]) {
×
898
    return SNTEventLogTypeJSON;
×
899
  } else if ([logType isEqualToString:@"file"]) {
×
900
    return SNTEventLogTypeFilelog;
×
901
  } else {
×
902
    return SNTEventLogTypeFilelog;
×
903
  }
×
904
}
×
905

906
- (NSString *)eventLogTypeRaw {
×
907
  return self.configState[kEventLogType] ?: @"file";
×
908
}
×
909

910
- (NSString *)eventLogPath {
×
911
  return self.configState[kEventLogPath] ?: @"/var/db/santa/santa.log";
×
912
}
×
913

914
- (NSString *)spoolDirectory {
×
915
  return self.configState[kSpoolDirectory] ?: @"/var/db/santa/spool";
×
916
}
×
917

918
- (NSUInteger)spoolDirectoryFileSizeThresholdKB {
×
919
  return self.configState[kSpoolDirectoryFileSizeThresholdKB]
×
920
           ? [self.configState[kSpoolDirectoryFileSizeThresholdKB] unsignedIntegerValue]
×
921
           : 250;
×
922
}
×
923

924
- (NSUInteger)spoolDirectorySizeThresholdMB {
×
925
  return self.configState[kSpoolDirectorySizeThresholdMB]
×
926
           ? [self.configState[kSpoolDirectorySizeThresholdMB] unsignedIntegerValue]
×
927
           : 100;
×
928
}
×
929

930
- (float)spoolDirectoryEventMaxFlushTimeSec {
×
931
  return self.configState[kSpoolDirectoryEventMaxFlushTimeSec]
×
932
           ? [self.configState[kSpoolDirectoryEventMaxFlushTimeSec] floatValue]
×
933
           : 15.0;
×
934
}
×
935

936
- (NSDictionary *)fileAccessPolicy {
×
937
  return self.configState[kFileAccessPolicy];
×
938
}
×
939

940
- (NSString *)fileAccessPolicyPlist {
×
941
  // This property is ignored when kFileAccessPolicy is set
942
  if (self.configState[kFileAccessPolicy]) {
×
943
    return nil;
×
944
  } else {
×
945
    return self.configState[kFileAccessPolicyPlist];
×
946
  }
×
947
}
×
948

949
- (NSString *)fileAccessBlockMessage {
×
950
  return self.configState[kFileAccessBlockMessage];
×
951
}
×
952

953
- (uint32_t)fileAccessPolicyUpdateIntervalSec {
×
954
  return self.configState[kFileAccessPolicyUpdateIntervalSec]
×
955
           ? [self.configState[kFileAccessPolicyUpdateIntervalSec] unsignedIntValue]
×
956
           : 60 * 10;
×
957
}
×
958

959
- (BOOL)enableMachineIDDecoration {
12✔
960
  NSNumber *number = self.configState[kEnableMachineIDDecoration];
12✔
961
  return number ? [number boolValue] : NO;
12!
962
}
12✔
963

964
- (BOOL)enableCleanSyncEventUpload {
×
965
  NSNumber *number = self.configState[kSyncEnableCleanSyncEventUpload];
×
966
  return number ? [number boolValue] : NO;
×
967
}
×
968

969
- (BOOL)enableAllEventUpload {
×
970
  NSNumber *n = self.syncState[kEnableAllEventUploadKey];
×
971
  if (n) return [n boolValue];
×
972

973
  return [self.configState[kEnableAllEventUploadKey] boolValue];
×
974
}
×
975

976
- (void)setEnableAllEventUpload:(BOOL)enabled {
×
977
  [self updateSyncStateForKey:kEnableAllEventUploadKey value:@(enabled)];
×
978
}
×
979

980
- (BOOL)disableUnknownEventUpload {
×
981
  NSNumber *n = self.syncState[kDisableUnknownEventUploadKey];
×
982
  if (n) return [n boolValue];
×
983

984
  return [self.configState[kDisableUnknownEventUploadKey] boolValue];
×
985
}
×
986

987
- (void)setDisableUnknownEventUpload:(BOOL)enabled {
×
988
  [self updateSyncStateForKey:kDisableUnknownEventUploadKey value:@(enabled)];
×
989
}
×
990

991
- (BOOL)enableForkAndExitLogging {
×
992
  NSNumber *number = self.configState[kEnableForkAndExitLogging];
×
993
  return number ? [number boolValue] : NO;
×
994
}
×
995

996
- (BOOL)ignoreOtherEndpointSecurityClients {
×
997
  NSNumber *number = self.configState[kIgnoreOtherEndpointSecurityClients];
×
998
  return number ? [number boolValue] : NO;
×
999
}
×
1000

1001
- (BOOL)enableDebugLogging {
12✔
1002
  NSNumber *number = self.configState[kEnableDebugLogging];
12✔
1003
  return [number boolValue] || self.debugFlag;
12!
1004
}
12✔
1005

1006
- (NSString *)fcmProject {
×
1007
  return self.configState[kFCMProject];
×
1008
}
×
1009

1010
- (NSString *)fcmEntity {
×
1011
  return self.configState[kFCMEntity];
×
1012
}
×
1013

1014
- (NSString *)fcmAPIKey {
×
1015
  return self.configState[kFCMAPIKey];
×
1016
}
×
1017

1018
- (BOOL)fcmEnabled {
×
1019
  return (self.fcmProject.length && self.fcmEntity.length && self.fcmAPIKey.length);
×
1020
}
×
1021

1022
- (void)setBlockUSBMount:(BOOL)enabled {
×
1023
  [self updateSyncStateForKey:kBlockUSBMountKey value:@(enabled)];
×
1024
}
×
1025

1026
- (BOOL)blockUSBMount {
×
1027
  NSNumber *n = self.syncState[kBlockUSBMountKey];
×
1028
  if (n) return [n boolValue];
×
1029

1030
  return [self.configState[kBlockUSBMountKey] boolValue];
×
1031
}
×
1032

1033
- (void)setSyncServerOverrideFileAccessAction:(NSString *)action {
×
1034
  NSString *a = [action lowercaseString];
×
1035
  if ([a isEqualToString:@"auditonly"] || [a isEqualToString:@"disable"] ||
×
1036
      [a isEqualToString:@"none"] || [a isEqualToString:@""]) {
×
1037
    [self updateSyncStateForKey:kOverrideFileAccessActionKey value:action];
×
1038
  }
×
1039
}
×
1040

1041
- (SNTOverrideFileAccessAction)overrideFileAccessAction {
×
1042
  NSString *action = [self.syncState[kOverrideFileAccessActionKey] lowercaseString];
×
1043

1044
  if (!action) {
×
1045
    action = [self.configState[kOverrideFileAccessActionKey] lowercaseString];
×
1046
    if (!action) {
×
1047
      return SNTOverrideFileAccessActionNone;
×
1048
    }
×
1049
  }
×
1050

1051
  if ([action isEqualToString:@"auditonly"]) {
×
1052
    return SNTOverrideFileAccessActionAuditOnly;
×
1053
  } else if ([action isEqualToString:@"disable"]) {
×
1054
    return SNTOverrideFileAccessActionDiable;
×
1055
  } else {
×
1056
    return SNTOverrideFileAccessActionNone;
×
1057
  }
×
1058
}
×
1059

1060
///
1061
/// Returns YES if all of the necessary options are set to export metrics, NO
1062
/// otherwise.
1063
///
1064
- (BOOL)exportMetrics {
×
1065
  return [self metricFormat] != SNTMetricFormatTypeUnknown &&
×
1066
         ![self.configState[kMetricURL] isEqualToString:@""];
×
1067
}
×
1068

1069
- (SNTMetricFormatType)metricFormat {
×
1070
  NSString *normalized = [self.configState[kMetricFormat] lowercaseString];
×
1071

1072
  normalized = [normalized stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
×
1073

1074
  if ([normalized isEqualToString:@"rawjson"]) {
×
1075
    return SNTMetricFormatTypeRawJSON;
×
1076
  } else if ([normalized isEqualToString:@"monarchjson"]) {
×
1077
    return SNTMetricFormatTypeMonarchJSON;
×
1078
  } else {
×
1079
    return SNTMetricFormatTypeUnknown;
×
1080
  }
×
1081
}
×
1082

1083
- (NSURL *)metricURL {
×
1084
  return [NSURL URLWithString:self.configState[kMetricURL]];
×
1085
}
×
1086

1087
// Returns a default value of 30 (for 30 seconds).
1088
- (NSUInteger)metricExportInterval {
×
1089
  NSNumber *configuredInterval = self.configState[kMetricExportInterval];
×
1090

1091
  if (configuredInterval == nil) {
×
1092
    return 30;
×
1093
  }
×
1094
  return [configuredInterval unsignedIntegerValue];
×
1095
}
×
1096

1097
// Returns a default value of 30 (for 30 seconds).
1098
- (NSUInteger)metricExportTimeout {
1✔
1099
  NSNumber *configuredInterval = self.configState[kMetricExportTimeout];
1✔
1100

1101
  if (configuredInterval == nil) {
1!
1102
    return 30;
1✔
1103
  }
1✔
1104
  return [configuredInterval unsignedIntegerValue];
×
1105
}
1✔
1106

1107
- (NSDictionary *)extraMetricLabels {
×
1108
  return self.configState[kMetricExtraLabels];
×
1109
}
×
1110

1111
- (NSArray<NSString *> *)enabledProcessAnnotations {
×
1112
  NSArray<NSString *> *annotations = self.configState[kEnabledProcessAnnotations];
×
1113
  for (id annotation in annotations) {
×
1114
    if (![annotation isKindOfClass:[NSString class]]) {
×
1115
      return nil;
×
1116
    }
×
1117
  }
×
1118
  return annotations;
×
1119
}
×
1120

1121
#pragma mark Private
1122

1123
///
1124
///  Update the syncState. Triggers a KVO event for all dependents.
1125
///
1126
- (void)updateSyncStateForKey:(NSString *)key value:(id)value {
21✔
1127
  dispatch_async(dispatch_get_main_queue(), ^{
21✔
UNCOV
1128
    NSMutableDictionary *syncState = self.syncState.mutableCopy;
×
UNCOV
1129
    syncState[key] = value;
×
UNCOV
1130
    self.syncState = syncState;
×
UNCOV
1131
    [self saveSyncStateToDisk];
×
UNCOV
1132
  });
×
1133
}
21✔
1134

1135
///
1136
///  Read the saved syncState.
1137
///
1138
- (NSMutableDictionary *)readSyncStateFromDisk {
19✔
1139
  if (!self.syncStateAccessAuthorizerBlock()) {
19✔
1140
    return nil;
16✔
1141
  }
16✔
1142

1143
  NSMutableDictionary *syncState =
3✔
1144
    [NSMutableDictionary dictionaryWithContentsOfFile:self.syncStateFilePath];
3✔
1145
  for (NSString *key in syncState.allKeys) {
3✔
1146
    if (self.syncServerKeyTypes[key] == [NSRegularExpression class]) {
2!
1147
      NSString *pattern = [syncState[key] isKindOfClass:[NSString class]] ? syncState[key] : nil;
×
1148
      syncState[key] = [self expressionForPattern:pattern];
×
1149
    } else if (![syncState[key] isKindOfClass:self.syncServerKeyTypes[key]]) {
2!
1150
      syncState[key] = nil;
×
1151
      continue;
×
1152
    }
×
1153
  }
2✔
1154

1155
  return syncState;
2✔
1156
}
19✔
1157

1158
///
1159
///  Migrate any deprecated sync state keys/values to alternative keys/values.
1160
///
1161
///  Returns YES if any keys were migrated. Otherwise NO.
1162
///
1163
- (BOOL)migrateDeprecatedSyncStateKeys {
19✔
1164
  // Currently only one key to migrate
1165
  if (!self.syncState[kSyncCleanRequiredDeprecated]) {
19✔
1166
    return NO;
17✔
1167
  }
17✔
1168

1169
  NSMutableDictionary *syncState = self.syncState.mutableCopy;
2✔
1170

1171
  // If the kSyncTypeRequired key exists, its current value will take precedence.
1172
  // Otherwise, migrate the old value to be compatible with the new logic.
1173
  if (!self.syncState[kSyncTypeRequired]) {
2!
1174
    syncState[kSyncTypeRequired] = [self.syncState[kSyncCleanRequiredDeprecated] boolValue]
2✔
1175
                                     ? @(SNTSyncTypeClean)
2✔
1176
                                     : @(SNTSyncTypeNormal);
2✔
1177
  }
2✔
1178

1179
  // Delete the deprecated key
1180
  syncState[kSyncCleanRequiredDeprecated] = nil;
2✔
1181

1182
  self.syncState = syncState;
2✔
1183

1184
  return YES;
2✔
1185
}
19✔
1186

1187
///
1188
///  Saves the current effective syncState to disk.
1189
///
1190
- (void)saveSyncStateToDisk {
2✔
1191
  if (!self.syncStateAccessAuthorizerBlock()) {
2!
UNCOV
1192
    return;
×
UNCOV
1193
  }
×
1194

1195
  // Either remove
1196
  NSMutableDictionary *syncState = self.syncState.mutableCopy;
2✔
1197
  syncState[kAllowedPathRegexKey] = [syncState[kAllowedPathRegexKey] pattern];
2✔
1198
  syncState[kBlockedPathRegexKey] = [syncState[kBlockedPathRegexKey] pattern];
2✔
1199
  [syncState writeToFile:self.syncStateFilePath atomically:YES];
2✔
1200
  [[NSFileManager defaultManager] setAttributes:@{NSFilePosixPermissions : @0600}
2✔
1201
                                   ofItemAtPath:self.syncStateFilePath
2✔
1202
                                          error:NULL];
2✔
1203
}
2✔
1204

1205
- (void)clearSyncState {
×
1206
  self.syncState = [NSMutableDictionary dictionary];
×
1207
}
×
1208

1209
- (NSArray *)entitlementsPrefixFilter {
×
1210
  return EnsureArrayOfStrings(self.configState[kEntitlementsPrefixFilterKey]);
×
1211
}
×
1212

1213
- (NSArray *)entitlementsTeamIDFilter {
×
1214
  return EnsureArrayOfStrings(self.configState[kEntitlementsTeamIDFilterKey]);
×
1215
}
×
1216

1217
#pragma mark Private Defaults Methods
1218

1219
- (NSRegularExpression *)expressionForPattern:(NSString *)pattern {
95✔
1220
  if (!pattern) return nil;
95!
1221
  if (![pattern hasPrefix:@"^"]) pattern = [@"^" stringByAppendingString:pattern];
×
1222
  return [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL];
×
1223
}
95✔
1224

1225
- (void)applyOverrides:(NSMutableDictionary *)forcedConfig {
19✔
1226
  // Overrides should only be applied under debug builds.
1227
#ifdef DEBUG
19✔
1228
  if ([[[NSProcessInfo processInfo] processName] isEqualToString:@"xctest"] &&
19!
1229
      ![[[NSProcessInfo processInfo] environment] objectForKey:@"ENABLE_CONFIG_OVERRIDES"]) {
19!
1230
    // By default, config overrides are not applied when running tests to help
1231
    // mitigate potential issues due to unexpected config values. This behavior
1232
    // can be overriden if desired by using the env variable: `ENABLE_CONFIG_OVERRIDES`.
1233
    //
1234
    // E.g.:
1235
    //   bazel test --test_env=ENABLE_CONFIG_OVERRIDES=1 ...other test args...
1236
    return;
19✔
1237
  }
19✔
1238

1239
  NSDictionary *overrides = [NSDictionary dictionaryWithContentsOfFile:kConfigOverrideFilePath];
×
1240
  for (NSString *key in overrides) {
×
1241
    id obj = overrides[key];
×
1242
    if (![obj isKindOfClass:self.forcedConfigKeyTypes[key]] ||
×
1243
        ([self.forcedConfigKeyTypes[key] isKindOfClass:[NSRegularExpression class]] &&
×
1244
         ![obj isKindOfClass:[NSString class]])) {
×
1245
      continue;
×
1246
    }
×
1247

1248
    forcedConfig[key] = obj;
×
1249

1250
    if (self.forcedConfigKeyTypes[key] == [NSRegularExpression class]) {
×
1251
      NSString *pattern = [obj isKindOfClass:[NSString class]] ? obj : nil;
×
1252
      forcedConfig[key] = [self expressionForPattern:pattern];
×
1253
    }
×
1254
  }
×
1255
#endif
×
1256
}
×
1257

1258
- (NSMutableDictionary *)readForcedConfig {
19✔
1259
  NSMutableDictionary *forcedConfig = [NSMutableDictionary dictionary];
19✔
1260
  for (NSString *key in self.forcedConfigKeyTypes) {
1,387✔
1261
    id obj = [self forcedConfigValueForKey:key];
1,387✔
1262
    forcedConfig[key] = [obj isKindOfClass:self.forcedConfigKeyTypes[key]] ? obj : nil;
1,387✔
1263
    // Create the regex objects now
1264
    if (self.forcedConfigKeyTypes[key] == [NSRegularExpression class]) {
1,387✔
1265
      NSString *pattern = [obj isKindOfClass:[NSString class]] ? obj : nil;
95!
1266
      forcedConfig[key] = [self expressionForPattern:pattern];
95✔
1267
    }
95✔
1268
  }
1,387✔
1269

1270
  [self applyOverrides:forcedConfig];
19✔
1271

1272
  return forcedConfig;
19✔
1273
}
19✔
1274

1275
- (id)forcedConfigValueForKey:(NSString *)key {
1,387✔
1276
  id obj = [self.defaults objectForKey:key];
1,387✔
1277
  return [self.defaults objectIsForcedForKey:key inDomain:kMobileConfigDomain] ? obj : nil;
1,387!
1278
}
1,387✔
1279

1280
- (void)startWatchingDefaults {
19✔
1281
  // Only com.google.santa.daemon should listen.
1282
  NSString *processName = [[NSProcessInfo processInfo] processName];
19✔
1283
  if (![processName isEqualToString:@"com.google.santa.daemon"]) return;
19!
1284
  [[NSNotificationCenter defaultCenter] addObserver:self
×
1285
                                           selector:@selector(defaultsChanged:)
×
1286
                                               name:NSUserDefaultsDidChangeNotification
×
1287
                                             object:nil];
×
1288
#ifdef DEBUG
×
1289
  dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{
×
1290
    [self watchOverridesFile];
×
1291
  });
×
1292
#endif
×
1293
}
×
1294

1295
#ifdef DEBUG
1296
- (void)watchOverridesFile {
×
1297
  while (![[NSFileManager defaultManager] fileExistsAtPath:kConfigOverrideFilePath]) {
×
1298
    [NSThread sleepForTimeInterval:0.2];
×
1299
  }
×
1300
  [self defaultsChanged:nil];
×
1301

1302
  int descriptor = open([kConfigOverrideFilePath fileSystemRepresentation], O_EVTONLY);
×
1303
  if (descriptor < 0) {
×
1304
    return;
×
1305
  }
×
1306

1307
  dispatch_source_t source =
×
1308
    dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, descriptor,
×
1309
                           DISPATCH_VNODE_WRITE | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_DELETE,
×
1310
                           dispatch_get_global_queue(QOS_CLASS_UTILITY, 0));
×
1311
  dispatch_source_set_event_handler(source, ^{
×
1312
    dispatch_async(dispatch_get_main_queue(), ^{
×
1313
      [self defaultsChanged:nil];
×
1314
    });
×
1315
    unsigned long events = dispatch_source_get_data(source);
×
1316
    if ((events & DISPATCH_VNODE_DELETE) || (events & DISPATCH_VNODE_RENAME)) {
×
1317
      dispatch_source_cancel(source);
×
1318
    }
×
1319
  });
×
1320
  dispatch_source_set_cancel_handler(source, ^{
×
1321
    close(descriptor);
×
1322
    [self watchOverridesFile];
×
1323
  });
×
1324
  dispatch_resume(source);
×
1325
}
×
1326
#endif
1327

1328
- (void)defaultsChanged:(void *)v {
×
1329
  SEL handleChange = @selector(handleChange);
×
1330
  [NSObject cancelPreviousPerformRequestsWithTarget:self selector:handleChange object:nil];
×
1331
  [self performSelector:handleChange withObject:nil afterDelay:1.0f];
×
1332
}
×
1333

1334
///
1335
///  Update the configState. Triggers a KVO event for all dependents.
1336
///
1337
- (void)handleChange {
×
1338
  self.configState = [self readForcedConfig];
×
1339
  [self cacheStaticRules];
×
1340
}
×
1341

1342
///
1343
///  Processes the StaticRules key to create SNTRule objects and caches them for quick use
1344
///
1345
- (void)cacheStaticRules {
19✔
1346
  NSArray *staticRules = self.configState[kStaticRules];
19✔
1347
  if (![staticRules isKindOfClass:[NSArray class]]) return;
19!
1348

1349
  NSMutableDictionary<NSString *, SNTRule *> *rules =
×
1350
    [NSMutableDictionary dictionaryWithCapacity:staticRules.count];
×
1351
  for (id rule in staticRules) {
×
1352
    if (![rule isKindOfClass:[NSDictionary class]]) return;
×
1353
    SNTRule *r = [[SNTRule alloc] initWithDictionary:rule];
×
1354
    if (!r) continue;
×
1355
    rules[r.identifier] = r;
×
1356
  }
×
1357
  self.cachedStaticRules = [rules copy];
×
1358
}
×
1359

1360
@end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2024 Coveralls, Inc