Skip to content

Commit f5486f6

Browse files
committed
Uploading Privileges 2.5 source code
1 parent 20d231a commit f5486f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+4632
-291
lines changed

source/Icon Dummy/AppDelegate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,5 @@
1919

2020
@interface AppDelegate : NSObject <NSApplicationDelegate>
2121

22-
2322
@end
2423

source/Privileges.xcodeproj/project.pbxproj

Lines changed: 716 additions & 145 deletions
Large diffs are not rendered by default.

source/Privileges/AppDelegate.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ - (void)showMainWindow
268268
}
269269

270270
if (![_privilegesApp hideSettingsButton]) { [_alert addButtonWithTitle:NSLocalizedString(@"settingsButton", nil)]; }
271-
[_alert addButtonWithTitle:NSLocalizedString(@"cancelButton", nil)];
271+
NSButton *cancelButton = [_alert addButtonWithTitle:NSLocalizedString(@"cancelButton", nil)];
272272
[_alert setAlertStyle:NSAlertStyleInformational];
273273
if (![[NSWorkspace sharedWorkspace] isVoiceOverEnabled] && ![_privilegesApp hideHelpButton]) { [_alert setShowsHelp:YES]; }
274274
[_alert setDelegate:self];
@@ -286,6 +286,9 @@ - (void)showMainWindow
286286
NSHeight([[_alert accessoryView] frame])
287287
)
288288
];
289+
290+
// make sure the text field is selected
291+
[cancelButton setRefusesFirstResponder:YES];
289292
}
290293
}
291294

source/Privileges/Base.lproj/Main.storyboard

Lines changed: 135 additions & 41 deletions
Large diffs are not rendered by default.

source/Privileges/Privileges.mobileconfig

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,22 @@
536536
you are doing so.
537537
-->
538538
<key>ForceUpdatePrebootVolume</key>
539+
<true/>
540+
541+
<!--
542+
key: EnableSystemExtension
543+
value: a boolean
544+
545+
When set to true, the Privileges system extension is enabled. The system
546+
extension protects the Privileges application and its components against
547+
unauthorized modifications, deactivation, or uninstallation. Once this
548+
key has been set, it is no longer possible to enable or disable the
549+
extension using PrivilegesCLI.
550+
551+
Please make sure you grant the Privileges system extension full disk
552+
access, otherwise it will not work.
553+
-->
554+
<key>EnableSystemExtension</key>
539555
<true/>
540556

541557
<!--
@@ -698,9 +714,9 @@
698714
<key>SyslogOptions</key>
699715
<dict>
700716
<key>ServerPort</key>
701-
<integer>514</integer>
717+
<integer>6514</integer>
702718
<key>UseTLS</key>
703-
<false/>
719+
<true/>
704720
<key>LogFacility</key>
705721
<integer>4</integer>
706722
<key>LogSeverity</key>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>MachServices</key>
6+
<dict>
7+
<key>corp.sap.privileges.helper.xpc</key>
8+
<true/>
9+
</dict>
10+
<key>Label</key>
11+
<string>corp.sap.privileges.helper</string>
12+
<key>Program</key>
13+
<string>/Applications/Privileges.app/Contents/MacOS/PrivilegesHelper.app/Contents/MacOS/PrivilegesHelper</string>
14+
<key>AssociatedBundleIdentifiers</key>
15+
<string>corp.sap.privileges</string>
16+
<key>SpawnConstraint</key>
17+
<dict>
18+
<key>team-identifier</key>
19+
<string>7R5ZEU67FQ</string>
20+
<key>signing-identifier</key>
21+
<string>corp.sap.privileges.helper</string>
22+
</dict>
23+
</dict>
24+
</plist>

source/PrivilegesAgent/AppDelegate.m

Lines changed: 89 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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

source/PrivilegesAgent/Classes/MTDaemonConnection.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
#import <Foundation/Foundation.h>
1919
#import "PrivilegesDaemonProtocol.h"
20-
#import <OSLog/OSLog.h>
2120
#import <os/log.h>
2221

2322
/*!
@@ -35,7 +34,7 @@
3534
@property (atomic, strong, readonly) NSXPCConnection *connection;
3635

3736
/*!
38-
@method connectToDaemonWithExportedObject:andExecuteCommandBlock:
37+
@method connectToDaemonAndExecuteCommandBlock:
3938
@abstract Connects to the daemon and executes the given command block.
4039
@param commandBlock The command block that should be executed after the connection has been established.
4140
*/

source/PrivilegesAgent/Classes/MTRemoteLoggingManager.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ - (instancetype)initWithRetryIntervals:(NSArray<NSNumber*>*)intervals
6565

6666
_loggingObject = syslogObject;
6767
_serverType = kMTRemoteLoggingServerTypeSyslog;
68+
69+
if (![syslogOptions useTLS]) {
70+
71+
os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, "SAPCorp: Remote syslog is configured without TLS. Events will be sent as clear text until TLS is enabled.");
72+
}
6873

6974
} else if ([[remoteLoggingConfiguration serverType] isEqualToString:kMTRemoteLoggingServerTypeWebhook]) {
7075

source/PrivilegesAgent/Main.storyboard

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
2+
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="24128" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
33
<dependencies>
44
<deployment identifier="macosx"/>
5-
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
5+
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24128"/>
66
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
77
</dependencies>
88
<scenes>

0 commit comments

Comments
 (0)