1919#import " MTPrivileges.h"
2020#import " MTCodeSigning.h"
2121#import " MTDaemonConnection.h"
22+ #import " MTSystemExtension.h"
2223#import " MTSystemInfo.h"
2324#import " Constants.h"
2425#import " MTIdentity.h"
@@ -36,11 +37,13 @@ @interface AppDelegate ()
3637@property (nonatomic , strong , readwrite ) NSTimer *expirationTimer;
3738@property (nonatomic , strong , readwrite ) NSTimer *statusItemTimer;
3839@property (nonatomic , strong , readwrite ) NSTimer *animationTimer;
40+ @property (nonatomic , strong , readwrite ) NSTimer *fixTimeoutObserverTimer;
3941@property (nonatomic , strong , readwrite ) NSDate *timerExpirationDate;
4042@property (nonatomic , strong , readwrite ) NSUserDefaults *userDefaults;
4143@property (nonatomic , strong , readwrite ) NSUserDefaults *appGroupDefaults;
4244@property (nonatomic , strong , readwrite ) MTLocalNotification *userNotification;
4345@property (nonatomic , strong , readwrite ) MTDaemonConnection *daemonConnection;
46+ @property (nonatomic , strong , readwrite ) MTSystemExtension *systemExtension;
4447@property (nonatomic , strong , readwrite ) NSStatusItem *statusItem;
4548@property (nonatomic , strong , readwrite ) MTStatusItemMenu *statusMenu;
4649@property (nonatomic , strong , readwrite ) MTRemoteLoggingManager *logManager;
@@ -76,6 +79,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
7679 [_listener resume ];
7780
7881 _daemonConnection = [[MTDaemonConnection alloc ] init ];
82+ _systemExtension = [[MTSystemExtension alloc ] init ];
7983 _userDefaults = [NSUserDefaults standardUserDefaults ];
8084 _appGroupDefaults = [[NSUserDefaults alloc ] initWithSuiteName: kMTAppGroupIdentifier ];
8185
@@ -153,6 +157,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
153157 kMTDefaultsShowInMenuBarKey ,
154158 kMTDefaultsShowRemainingTimeInMenuBarKey ,
155159 kMTDefaultsRemoteLoggingKey ,
160+ kMTDefaultsEnableSystemExtensionKey ,
156161 nil
157162 ];
158163
@@ -236,6 +241,9 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
236241
237242 // initialize the logging manager
238243 [self initializeLogManager ];
244+
245+ // force system extension state if configured
246+ [self handleSystemExtensionConfigChange ];
239247 }
240248}
241249
@@ -260,12 +268,14 @@ - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConne
260268
261269 if (taskRef) {
262270
263- if (SecTaskValidateForRequirement (taskRef, (__bridge CFStringRef)(reqString)) == errSecSuccess) {
271+ OSStatus result = SecTaskValidateForRequirement (taskRef, (__bridge CFStringRef)(reqString));
272+
273+ if (result == errSecSuccess) {
264274
265275 acceptConnection = YES ;
266276
267- newConnection. exportedInterface = [NSXPCInterface interfaceWithProtocol: @protocol (PrivilegesAgentProtocol)];
268- newConnection. exportedObject = self;
277+ [ newConnection setExportedInterface: [NSXPCInterface interfaceWithProtocol: @protocol (PrivilegesAgentProtocol)] ];
278+ [ newConnection setExportedObject: self ] ;
269279
270280#pragma clang diagnostic push
271281#pragma clang diagnostic ignored "-Warc-retain-cycles"
@@ -282,7 +292,7 @@ - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConne
282292
283293 } else {
284294
285- os_log_with_type (OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, " SAPCorp: Code signature verification failed" );
295+ os_log_with_type (OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, " SAPCorp: Code signature verification failed (error %d ) " , result );
286296 }
287297
288298 CFRelease (taskRef);
@@ -612,7 +622,7 @@ - (void)displayNotificationOfType:(MTLocalNotificationType)type
612622 notificationMessage = NSLocalizedString(@" notificationMessage_RenewSuccess" , nil );
613623 break ;
614624
615- default :
625+ case MTLocalNotificationTypeNoChange :
616626 break ;
617627 }
618628
@@ -628,40 +638,92 @@ - (void)displayNotificationOfType:(MTLocalNotificationType)type
628638 }
629639}
630640
641+ - (void )handleSystemExtensionConfigChange
642+ {
643+ if (@available (macOS 13.0 , *)) {
644+
645+ if ([_privilegesApp systemExtensionIsForced ]) {
646+
647+ BOOL enableExtension = [_privilegesApp enableSystemExtension ];
648+ [_systemExtension statusWithReply: ^(NSString *status) {
649+
650+ dispatch_async (dispatch_get_main_queue (), ^{
651+
652+ if ([status isEqualToString: kMTExtensionStatusEnabled ] && !enableExtension) {
653+
654+ [self ->_systemExtension disableWithCompletionHandler: ^(BOOL success, NSError *error) {
655+
656+ return ;
657+ }];
658+
659+ } else if ([status isEqualToString: kMTExtensionStatusDisabled ] && enableExtension) {
660+
661+ [self ->_systemExtension enableWithCompletionHandler: ^(BOOL success, NSError *error) {
662+
663+ [self ->_systemExtension statusWithReply: ^(NSString *status) {
664+
665+ if ([status rangeOfString: @" waiting" ].location != NSNotFound ) {
666+
667+ os_log_with_type (OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, " SAPCorp: System extension is waiting for full disk access" );
668+ }
669+ }];
670+ }];
671+ }
672+ });
673+ }];
674+ }
675+ }
676+ }
677+
631678- (void )observeValueForKeyPath : (NSString *)keyPath ofObject : (id )object change : (NSDictionary <NSKeyValueChangeKey,id> *)change context : (void *)context
632679{
633680 if (object == [_privilegesApp userDefaults ] && [_keysToObserve containsObject: keyPath]) {
634681
635- if ([keyPath isEqualToString: kMTDefaultsEnforcePrivilegesKey ] ||
636- [keyPath isEqualToString: kMTDefaultsLimitToUserKey ] ||
637- [keyPath isEqualToString: kMTDefaultsLimitToGroupKey ]) {
682+ if ([keyPath isEqualToString: kMTDefaultsEnableSystemExtensionKey ]) {
638683
639- [self enforceFixedPrivileges ];
684+ // workaround for bug that is causing observeValueForKeyPath to be called multiple times.
685+ // so every notification resets the timer and if we got no new notifications for 5 seconds,
686+ // we evaluate the changes.
687+ if (_fixTimeoutObserverTimer) { [_fixTimeoutObserverTimer invalidate ]; };
688+ _fixTimeoutObserverTimer = [NSTimer scheduledTimerWithTimeInterval: 5.0
689+ repeats: NO
690+ block: ^(NSTimer *timer) {
691+ [self handleSystemExtensionConfigChange ];
692+ }];
640693
641- } else if ([keyPath isEqualToString: kMTDefaultsExpirationIntervalKey ] ||
642- [keyPath isEqualToString: kMTDefaultsExpirationIntervalMaxKey ]) {
694+ } else {
643695
644- // invalidate or (re)schedule our timer if needed
645- if ([_privilegesApp expirationInterval ] == 0 ) {
696+ if ([keyPath isEqualToString: kMTDefaultsEnforcePrivilegesKey ] ||
697+ [keyPath isEqualToString: kMTDefaultsLimitToUserKey ] ||
698+ [keyPath isEqualToString: kMTDefaultsLimitToGroupKey ]) {
646699
647- [self invalidateExpirationTimer ];
648-
649- } else if ([self privilegesTimeLeft ] > [_privilegesApp expirationInterval ] ||
650- ([self userHasAdminPrivileges ] && [self privilegesTimeLeft ] == 0 )) {
651-
652- [self scheduleExpirationTimerWithInterval: [_privilegesApp expirationInterval ] isSavedTimer: NO ];
700+ [self enforceFixedPrivileges ];
701+
702+ } else if ([keyPath isEqualToString: kMTDefaultsExpirationIntervalKey ] ||
703+ [keyPath isEqualToString: kMTDefaultsExpirationIntervalMaxKey ]) {
704+
705+ // invalidate or (re)schedule our timer if needed
706+ if ([_privilegesApp expirationInterval ] == 0 ) {
707+
708+ [self invalidateExpirationTimer ];
709+
710+ } else if ([self privilegesTimeLeft ] > [_privilegesApp expirationInterval ] ||
711+ ([self userHasAdminPrivileges ] && [self privilegesTimeLeft ] == 0 )) {
712+
713+ [self scheduleExpirationTimerWithInterval: [_privilegesApp expirationInterval ] isSavedTimer: NO ];
714+ }
715+
716+ } else if ([keyPath isEqualToString: kMTDefaultsRemoteLoggingKey ]) {
717+
718+ [self initializeLogManager ];
653719 }
654720
655- } else if ([keyPath isEqualToString: kMTDefaultsRemoteLoggingKey ]) {
656-
657- [self initializeLogManager ];
721+ // update the status item if needed
722+ [self showStatusItem: [self ->_privilegesApp showInMenuBar ]];
723+
724+ [self postConfigurationChangeNotificationForKeyPath: keyPath];
658725 }
659726
660- // update the status item if needed
661- [self showStatusItem: [self ->_privilegesApp showInMenuBar ]];
662-
663- [self postConfigurationChangeNotificationForKeyPath: keyPath];
664-
665727 } else if ((object == _appGroupDefaults && [_appGroupToObserve containsObject: keyPath]) ||
666728 (object == _statusItem && [keyPath isEqualToString: @" visible" ])) {
667729
0 commit comments